這題目寫起來很有趣,反斜線看到時覺得好像有問題,卻過一小時後才去確認有沒有問題,前面都在找其他的洞,非常失策
[正文]
題目有給 source code
1 | <?php |
Analysis
觀察 source code,發現在最後會用 system 去執行
file $file1 $file2
,且$file1
,$file2
的內容會被雙引號包住來防止 injection,如果可以繞過 WAF 和雙引號,就可以控制 system 的內容!觀察 WAF,可以發現在 preg_match 的 regular expression 中有反斜線的漏洞
7
8
9
10
11
12// WAF
if(preg_match("/\'|\"|;|,|\`|\*|\\|\n|\t|\r|\xA0|\{|\}|\(|\)|<|\&[^\d]|@|\||ls|cat|sh|flag|find|grep|echo|w/is", $file1))
$file1 = "";
if(preg_match("/\'|\"|;|,|\`|\*|\\|\n|\t|\r|\xA0|\{|\}|\(|\)|<|\&[^\d]|@|\||ls|cat|sh|flag|find|grep|echo|w/is", $file2))
$file2 = "";可以看到反斜線的 escape 為
\\
,但是在 php 中要 escape 反斜線要四個\\\\
,這個錯誤會引發後面的\n
也會出錯,\\|\n
在 string escape 變成\|\n
,導致在 preg_match 中要|\n
才會被 match 到。這樣就可以使用 反斜線 和 換行符號!Escape backslash in PHP
根據 PHP Manual 的說明,PHP 在建構 string 時會先 escape 反斜線一次,所以要表示一個反斜線,會變成
\\
,在 preg_match 中 pattern 又會在 escape,所以會變成\\\\
才能成功過濾反斜線。
Payload
知道可以使用反斜線和換行符號,那可以嘗試使用反斜線去 escape 雙引號,換行符號 (%0a) 來讓 system 以為有兩行命令
$file1 = \ |
換行符號
這裡使用 %0a
當換行符號,主要是因為傳資料的時候會經過 http,會被 urlencode,%0a 就是 url 中的urlencode 換行符號,另外就是 %0a 本來就不會被 preg_match 批配到換行字元。
WAF pattern 的後半段有 ls|cat|sh|flag|find|grep|echo|w
,這些簡單地用 $3 來 bypass 就好,例如 ls
==> l$3s
http://final.kaibro.tw:10002/ |
FLAG: FLAG{e4sy_w4f_byp4s5_0h_y4_XD__}