PHP中一個有趣的preg_replace函數(shù)詳解
0x01 起因
事情的起因是下午遇到了 preg_replace 函數(shù),我們都知道 preg_replace 函數(shù)可能會導致命令執(zhí)行?,F(xiàn)在我們來一些情況。
0x02 經(jīng)過
踩坑1:
測試代碼大概是這樣的:
foreach ($_GET as $regex => $value) {
preg_replace('/(' . $regex . ')/ei','strtolower("\\1")',$value);
}
測試過程中發(fā)現(xiàn)通過瀏覽器的方式傳入數(shù)據(jù)的時候,會將 . + 等特殊字符轉(zhuǎn)換為 _ 。


這里涉及到了php的一個特性
php自身在解析請求的時候,如果參數(shù)名字中包含空格、.、[等字符,會將他們轉(zhuǎn)換成_。
<?php $a = $_GET; var_dump($a); ?>

經(jīng)過我的fuzz,結果如下圖:

踩坑2:
那我們知道 preg_replace 的 /e 修正符會將 replacement 參數(shù)當作 php 代碼,并且以 eval 函數(shù)的方式執(zhí)行,前提是 subject 中有 pattern 的匹配。既然是這樣我們看一張圖。

圖中實際上通過 eval 執(zhí)行的是 strtolower 函數(shù)。分別實際執(zhí)行的是:
strtolower("JUST TEST");
strtolower("PHPINFO()");
strtolower("{${PHPINFO()}}");
第三個之所以可以執(zhí)行代碼,是因為我們通過復雜(花括號)語法的方式來讓其代碼執(zhí)行。
踩坑3:
回到源代碼中,我們再理解一下:
foreach ($_GET as $regex => $value) {
preg_replace('/(' . $regex . ')/ei','strtolower("\\1")',$value);
}
這里的 replacement 是 strtolower(“\\1”) ,著重理解一下 \\1 。
每個這樣的引用將被匹配到的第n個捕獲子組捕獲到的文本替換。 n可以是0-99,\0和\$0代表完整的模式匹配文本。
假設一個正則表達式是這樣的:
preg_replace('/(.*)(\?|&)' . $key . '=[^&]+?(&)(.*)/i', '$1$2$4', $url . '&');
這里的 \$1\$2\$4 等同于上面的 \1\2\4 的作用,因此我們看一下是怎么選擇匹配的。
$1 $2 $3 $4 '/(.*)(\?|&)' . $key . '=[^&]+?(&)(.*)/i'
0x03 解決
好了上面都已經(jīng)鋪墊完坑了,這里要開始解決了。
foreach ($_GET as $regex => $value) {
preg_replace('/(' . $regex . ')/ei','strtolower("\\1")',$value);
}
我們想要讓這部分代碼達到代碼執(zhí)行的效果需要達到幾個條件:
- pattern 部分的表達式需要命中 \$value 中的數(shù)據(jù)
- \1 中取出的數(shù)據(jù)復雜(花括號)語法的特征,來保證在雙引號的包含下達到代碼執(zhí)行的效果
- 由于php的特性url會將 . 、 [ 、 + 等特殊字符轉(zhuǎn)換為 _ 。
我們知道這里是通過 get 方式獲取到 \$regex 和 \$value 的,要想在 replacement 部分通過 \1 截取到 pattern 正則匹配命中 \$value 中的數(shù)據(jù),并且攜帶 \$ 、 { 、 ( 這里就涉及到正則表達式的使用了。
這里我選擇了 \S ,也就是匹配任意的非空白字符,那么最后的payload長這樣
\S*()={${phpinfo()}}


0x04 后記
其實還有點小問題,我這邊沒有寫,不過大家可以看看這個深入研究preg_replace與代碼執(zhí)行。
總結
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關文章
PHP中error_reporting()函數(shù)的用法(修改PHP屏蔽錯誤)
一般在默認的普通PHP文件中輸出一個未定義聲明的變量是不會報錯誤的,但在codeigniter框架下卻要報錯誤,這對于想集成 添加 和 修改 頁面于一體的”懶人”很不方便,由于是初學者開始還想怎么在代碼中屏蔽這一錯誤提示呢.甚至用到了@,但聽很多人都說@會大大降低性能.2011-07-07
PHP編程實現(xiàn)微信企業(yè)向用戶付款的方法示例
這篇文章主要介紹了PHP編程實現(xiàn)微信企業(yè)向用戶付款的方法,涉及php針對微信接口調(diào)用、配置及交互操作相關技巧,需要的朋友可以參考下2017-07-07

