DNS Rebinding in Draw.io ProxyServlet Allows Cloud Metadata and Internal Network Bypass
A server-side request forgery vulnerability has been disclosed in the proxy functionality of draw.io, enabling attackers to bypass private IP blocklists via DNS rebinding. The vulnerability manifests specifically in deployments where the proxy feature is activated through the `ENABLE_DRAWIO_PROXY=1` configuration flag. The root cause lies in how the application performs domain name resolution across two distinct execution stages without maintaining shared state. When handling an incoming request, the `Utils.sanitizeUrl()` method first invokes `InetAddress.getByName(host)` to confirm that the destination IP does not belong to private or restricted network blocks. Once the sanitization check completes successfully, execution flows to `ProxyServlet`, which instantiates a fresh `URL` object and invokes `url.openConnection()`. This operation initiates a completely independent, secondary DNS resolution process within the JVM. An attacker controlling an authoritative nameserver configured with a Time to Live (TTL) of zero can serve a benign public IP address during the initial validation check. The attacker then rapidly flips the DNS record to an internal IP address before the second lookup executes. Because the JVM's DNS caching TTL can be configured as low as zero, this race condition is reliably exploitable in practice. Successful exploitation allows attackers to force the server to issue HTTP requests to internal endpoints such as the cloud instance metadata service at `169.254.169.254`. The application subsequently base64-encodes the fetched response body and returns it directly to the requester. This behavior permits the exfiltration of sensitive cloud tokens, such as AWS IMDSv1 temporary IAM credentials or GCP service account tokens, as well as the probing of intranet services.
Commentary
This flaw is a textbook Time-of-Check to Time-of-Use (TOCTOU) vulnerability rooted in split-resolution architecture. Implementing IP blocklists by resolving hostnames separately from the actual socket connection is an anti-pattern that frequently plagues web proxies. In Java environments, developers often assume the standard library or OS will cache the DNS record between `InetAddress.getByName()` and `URL.openConnection()`, but JVM configurations or zero-TTL responses easily invalidate that assumption. Organizations self-hosting draw.io with `ENABLE_DRAWIO_PROXY=1` in cloud environments (like AWS EC2, ECS, or GCP Compute Engine) face the highest exposure. If the cloud infrastructure relies on unauthenticated metadata endpoints (such as AWS IMDSv1), remote attackers can leverage this SSRF to pull temporary role credentials and pivot deeper into the cloud estate. Remediation requires pinning the resolved IP: resolve the domain once, validate the resulting IP against private and link-local ranges, and rewrite the outbound request URL to connect directly to that validated IP (while setting the appropriate `Host` HTTP header). Administrators operating draw.io instances in AWS should immediately enforce IMDSv2 (requiring a token hop limit of 1) across their underlying infrastructure to prevent metadata retrieval even if SSRF flaws exist at the application layer.
The Quote to Remember
“The issue arises because the security check and the actual network connection each trigger a separate DNS lookup, and an attacker with control over a DNS record can change the resolved IP between those two moments.”
“Replace the hostname in the URL with the resolved IP string before calling openConnection(), so the JVM cannot perform a second independent DNS lookup and the checked address is guaranteed to be the one used.”