漏洞簡介
CVE-2024-4577是一個 PHP CGI 的參數注入漏洞,這個漏洞繞過了 CVE-2012-2311 的保護,透過 windows BEST-Fit 的特性,構造不存在的 urlencode 字元讓 Windows 解析出 -
字元,從而繞過 php cgi 的保護機制。
漏洞分析
要了解這個漏洞,我們需要先坐時光機回到最初的漏洞,也就是CVE-2012-2311更之前的 PHP 5.3.11
CVE-2012-1823
漏洞成因
首先,我們有一個先備知識要知道,那就是 http server
呼叫 CGI
時,會連同 request 的 query 一起當成參數傳給 CGI
,例如:我今天存取了 http://192.168.22.16/php-cgi/php-cgi.exe?foo 時,apache
啟動CGI
的 commandline 其實長這樣:
因此攻擊者只要構造出開頭為 -
的 querystring , CGI
就會把他當成參數解析,從而導致參數注入漏洞。
漏洞修補
針對 CVE-2012–1823 出現的漏洞,PHP在 5.3.12 將漏洞 patch 掉,方法是檢查 querystring
的開頭是不是 -
1 | - while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0)) != -1) { |
CVE-2012-2311
漏洞成因
在 5.3.12 發佈後不到一個禮拜就被人 bypass 了,因為只要在-
前面塞空格就好(?)
漏洞修補
PHP官方很快就發佈了 5.3.13 版本,這次他們先把前面的空白都變不見(pointer往後移),再檢查開頭是不是 -
1 | for (p = decoded_query_string; *p && *p <= ' '; p++) { |
CVE-2024-4577
時隔12年,這個保護機制又被繞掉了,但這次並不影響到全部的php版本,而是只有某些特定語系的 Windows 作業系統,且需要由 CGI 解析才會觸發。
漏洞成因
這個漏洞是因為在 Windows 上有 BEST-Fit 的特性,讓攻擊者在繁體中文等特定語系環境的 Windows 直接生出一個完全不存在的字元(0xad)卻可以被解析成 -
,當然,你也可以透過這份文件,找找看其他語系的 windows 有沒有可以 bypass 的字元。
如何利用
首先,我們可以來看看 PHP CGI 有哪些參數可以下:
1 | ❯ php-cgi --help ─╯ |
應該可以馬上發現, -d
參數非常有用,你可以把所有會妨礙你使用 LFI
to RCE 的安全選項全部關掉,然後再用偽協議把髒髒的東西都寫進來
1 | POST http://example.com/?-d%20allow_url_include%3Don%20-d%20auto_prepend%3Dphp%3A%2F%2Finput%2F%0A |