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


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

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

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

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


0x04 后記
其實(shí)還有點(diǎn)小問(wèn)題,我這邊沒(méi)有寫(xiě),不過(guò)大家可以看看這個(gè)深入研究preg_replace與代碼執(zhí)行。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
php實(shí)現(xiàn)無(wú)限級(jí)分類(遞歸方法)
當(dāng)你學(xué)習(xí)php無(wú)限極分類的時(shí)候,大家都覺(jué)得一個(gè)字“難”我也覺(jué)得很難,所以,現(xiàn)在都還在看,因?yàn)楣ぷ饕玫剑?,就必須得研究研究?/div> 2015-08-08
深入探討:PHP使用數(shù)據(jù)庫(kù)永久連接方式操作MySQL的是與非
本篇文章是對(duì)PHP使用數(shù)據(jù)庫(kù)永久連接方式操作MySQL的是與非進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
php下載文件超時(shí)時(shí)間的設(shè)置方法
這篇文章W主要介紹了php下載文件超時(shí)時(shí)間的設(shè)置方法2016-10-10
javascript,php獲取函數(shù)參數(shù)對(duì)象的代碼
javascript,php獲取函數(shù)參數(shù)對(duì)象的代碼,需要的朋友可以參考下。2011-02-02
PHPExcel導(dǎo)出2003和2007的excel文檔功能示例
這篇文章主要介紹了PHPExcel導(dǎo)出2003和2007的excel文檔功能,結(jié)合實(shí)例形式分析了PHPExcel屬性設(shè)置及文檔導(dǎo)出操作相關(guān)技巧,需要的朋友可以參考下2017-01-01
php自動(dòng)獲取字符串編碼函數(shù)mb_detect_encoding
使用 mb_detect_encoding() 函數(shù)來(lái)判斷字符串是什么編碼的。2011-05-05
PHP使用PHPexcel導(dǎo)入導(dǎo)出數(shù)據(jù)的方法
這篇文章主要介紹了PHP使用PHPexcel導(dǎo)入導(dǎo)出數(shù)據(jù)的方法,以實(shí)例形式較為詳細(xì)的分析了PHP使用PHPexcel實(shí)現(xiàn)數(shù)據(jù)的導(dǎo)入與導(dǎo)出操作相關(guān)技巧,需要的朋友可以參考下2015-11-11最新評(píng)論

