high · 8.6CVE-2026-81889Aug 31, 2026

CVE-2026-81889: elFinder SSRF Protection Bypass via DNS Rebinding

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

elFinder's URL upload feature can be tricked into fetching content from internal servers by exploiting a gap between DNS validation and the actual socket connection, letting attackers read private…

Packagestudio-42/elfinder
Ecosystemcomposer
Affected<= 2.1.69
Fixed in2.1.70
CVE-2026-81889: elFinder SSRF Protection Bypass via DNS Rebinding

The problem

elFinder 2.1.69 validates a URL's IP address with validate_address() (using gethostbyname()), then stores the resolved address in $info['ip']. When PHP cURL is absent, get_remote_contents() falls back to fsock_get_contents(), which ignores $info['ip'] and opens the socket with the original hostname.

This means the OS resolves DNS a second time at connect. An attacker who controls a hostname can serve a public IP on the first query (passing validation) and a loopback or private IP on the second (used for the real connection). The response body is saved as an uploaded file, making this a non-blind SSRF with full response readback.

A separate get_headers($url, true) call after the fetch adds an additional blind SSRF path that fires even when cURL is available.

Proof of concept

A working proof-of-concept for CVE-2026-81889 in studio-42/elfinder, with the exact payload below.

bash
# 1. Point rebind.test to a public IP on first DNS query, then 127.0.0.1 on all subsequent queries.
# 2. In the elFinder UI, open Upload > "Upload from URL" and submit:
http://rebind.test:9001/secret.txt

# DNS server behavior (deterministic PoC):
#   Query 1  -> 203.0.113.10  (passes validate_address() check)
#   Query 2+ -> 127.0.0.1     (used by fsockopen() at connect time)

# Expected server log:
# DNS rebind.test type=1 answer=203.0.113.10 count=1
# DNS rebind.test type=1 answer=127.0.0.1   count=2
# GET /secret.txt

# The resulting file is readable inside elFinder; content: INTERNAL_SECRET_MANUAL

# Redirect variant also works:
http://rebind.test:9001/redirect-secret

The root cause is a TOCTOU (CWE-367) flaw inside fsock_get_contents(). The validated IP in $info['ip'] is never passed to fsockopen(); the call is fsockopen($ssl . $arr['host'], $arr['port'], ...), so the kernel resolves the hostname fresh at connect time. cURL avoids this correctly using CURLOPT_RESOLVE to pin the validated IP, but the socket fallback has no equivalent pinning.

The patch in 2.1.70 takes the simplest safe approach: URL uploads are rejected outright when curl_exec() is unavailable, eliminating the unguarded fallback path entirely. The advisory also flags get_headers($url, true) as a secondary blind-SSRF source that fires on its own DNS lookup after any successful fetch.

The fix

Upgrade to elFinder 2.1.70. The release removes the fsock_get_contents() fallback for URL uploads, requiring cURL. If you cannot upgrade immediately, disable URL upload functionality or set urlUploadFilter to block all URLs. Deployments running PHP without the cURL extension are most exposed.

Reported by Marco Lunardi.

References: [1][2][3][4][5]

Related research