![[buuctf]cat flag題解](http://pic.xiahunao.cn/yaotu/[buuctf]cat flag題解)
[BUUCTF] cat flag 題解1. 題目源碼題目給出的 PHP 源代碼如下?phpif(isset($_GET[cmd])){$cmd$_GET[cmd];if(!preg_match(/flag/i,$cmd)){$cmdescapeshellarg($cmd);system(cat .$cmd);}}else{highlight_file(__FILE__);}?邏輯分析程序通過GET方式接收cmd參數(shù)。使用正則preg_match(/flag/i, $cmd)對字符串中的flag關(guān)鍵字不區(qū)分大小寫進(jìn)行過濾。若未觸發(fā)正則攔截則對$cmd調(diào)用escapeshellarg()函數(shù)進(jìn)行轉(zhuǎn)義最后拼接至system(cat . $cmd)并執(zhí)行命令。2. 漏洞原理與延伸1.escapeshellarg()剝離非法 UTF-8 字符繞過escapeshellarg()的設(shè)計(jì)初衷是為字符串兩端包裹單引號并轉(zhuǎn)義已有的單引號使得整個(gè)字符串作為單一安全參數(shù)傳遞給 Shell防止命令注入。但是在PHP 7.3某些具體版本中escapeshellarg()在處理包含非法 UTF-8 字符字節(jié)例如%80/\x80的字符串時(shí)會(huì)將該非法字節(jié)直接從結(jié)果中剝離刪除。繞過正則傳入fl%80ag時(shí)原始輸入字符串為fl\x80ag不匹配正則表達(dá)式flag從而順利繞過preg_match(/flag/i, $cmd)黑名單檢測。執(zhí)行命令經(jīng)過escapeshellarg()處理后0x80字節(jié)被系統(tǒng)剔除處理后的字符串恢復(fù)為flag最終拼接為cat flag并成功執(zhí)行。2. 知識點(diǎn)拓展escapeshellarg()escapeshellcmd()經(jīng)典組合漏洞在 CTF 題目中經(jīng)常會(huì)見到將這兩個(gè)轉(zhuǎn)義函數(shù)組合使用的場景例如?phpif(isset($_SERVER[HTTP_X_FORWARDED_FOR])){$_SERVER[REMOTE_ADDR]$_SERVER[HTTP_X_FORWARDED_FOR];}if(!isset($_GET[host])){highlight_file(__FILE__);}else{$host$_GET[host];$hostescapeshellarg($host);$hostescapeshellcmd($host);$sandboxmd5(glzjin.$_SERVER[REMOTE_ADDR]);echoyou are in sandbox .$sandbox;mkdir($sandbox);chdir($sandbox);echosystem(nmap -T5 -sT -Pn --host-timeout 2 -F .$host);}產(chǎn)生機(jī)制escapeshellarg()率先把$host轉(zhuǎn)義并用單引號包裹成單一參數(shù)。緊接著對處理結(jié)果調(diào)用escapeshellcmd()后者會(huì)再次轉(zhuǎn)義字符串中的 Shell 元字符如 | ; \及未配對的單引號。這破壞了原本建立的單引號邊界。危害后果攻擊者可利用單引號配對錯(cuò)位拆分參數(shù)形成參數(shù)注入Argument Injection例如向nmap注入追加參數(shù)以實(shí)現(xiàn)任意文件寫入/命令執(zhí)行而非直接通過;進(jìn)行簡單的指令拼接。3. 解題過程Step 1. 嘗試?yán)@過限制并讀取 flag構(gòu)造包含非法 UTF-8 字節(jié)的 Payload 繞過黑名單限制?cmd/fl%80ag頁面返回提示我們并沒有完整拿到 flag。Step 2. 抓包分析 HTTP 響應(yīng)頭抓包查看完整的 HTTP 響應(yīng)包數(shù)據(jù)從響應(yīng)頭中可注意到Server: openresty。這表明服務(wù)器使用了 OpenResty/Nginx 架構(gòu)提示我們可以嘗試讀取 Nginx 的日志文件來獲取更多線索。Step 3. 讀取日志定位真實(shí) Flag 文件利用cmd參數(shù)讀取默認(rèn)的 Nginx 訪問日志文件access.log?cmd/var/log/nginx/access.log在日志記錄中成功找到真實(shí)的 flag 文件名this_is_final_flag_e2a457126032b42d.php。Step 4. 讀取真實(shí) Flag 文件源碼再次結(jié)合%80字符繞過黑名單讀取目標(biāo) PHP 文件?cmdthis_is_final_fl%80ag_e2a457126032b42d.php由于目標(biāo)文件是.php文件內(nèi)容會(huì)被 PHP 解析執(zhí)行或被瀏覽器當(dāng)作 HTML 隱藏按下Ctrl U查看網(wǎng)頁源代碼CTF2{f02ea6b9-aa0b-442e-907b-213b82b99107}成功獲取最終 Flag