主頁 > 知識庫 > 深入研究PHP中的preg_replace和代碼執(zhí)行

深入研究PHP中的preg_replace和代碼執(zhí)行

熱門標(biāo)簽:企業(yè)400電話辦理多少費(fèi)用 萍鄉(xiāng)商鋪地圖標(biāo)注 太原400電話申請流程 代理打電話機(jī)器人 桂陽公司如何做地圖標(biāo)注 宿州正規(guī)外呼系統(tǒng)軟件 神龍斗士電話機(jī)器人 合肥企業(yè)外呼系統(tǒng)線路 電信外呼系統(tǒng)多少錢一個月

前言

本文將深入研究 preg_replace /e 模式下的代碼執(zhí)行問題,其中包括 preg_replace 函數(shù)的執(zhí)行過程分析、正則表達(dá)式分析、漏洞觸發(fā)分析,當(dāng)中的坑非常多,相信看完本文,你一定會有所收獲。下面是 七月火 和 l1nk3r 的分析結(jié)果。

案例

下面先看一個案例,思考如何利用此處的 preg_replace /e 模式,執(zhí)行代碼(可以先不看下文分析,自己思考出 payload 試試)。

這個案例實(shí)際上很簡單,就是 preg_replace 使用了 /e 模式,導(dǎo)致可以代碼執(zhí)行,而且該函數(shù)的第一個和第三個參數(shù)都是我們可以控制的。我們都知道, preg_replace 函數(shù)在匹配到符號正則的字符串時,會將替換字符串(也就是上圖 preg_replace 函數(shù)的第二個參數(shù))當(dāng)做代碼來執(zhí)行,然而這里的第二個參數(shù)卻固定為 'strtolower("\\1")' 字符串,那這樣要如何執(zhí)行代碼呢?

爬坑1

上面的命令執(zhí)行,相當(dāng)于 eval('strtolower("\\1");') 結(jié)果,當(dāng)中的 \\1 實(shí)際上就是 \1 ,而 \1 在正則表達(dá)式中有自己的含義。我們來看看 W3Cschool 中對其的描述:

反向引用

對一個正則表達(dá)式模式或部分模式 兩邊添加圓括號 將導(dǎo)致相關(guān) 匹配存儲到一個臨時緩沖區(qū) 中,所捕獲的每個子匹配都按照在正則表達(dá)式模式中從左到右出現(xiàn)的順序存儲。緩沖區(qū)編號從 1 開始,最多可存儲 99 個捕獲的子表達(dá)式。每個緩沖區(qū)都可以使用 '\n' 訪問,其中 n 為一個標(biāo)識特定緩沖區(qū)的一位或兩位十進(jìn)制數(shù)。

所以這里的 \1 實(shí)際上指定的是第一個子匹配項(xiàng),我們拿 ripstech 官方給的 payload 進(jìn)行分析,方便大家理解。官方 payload 為: /?.*={${phpinfo()}} ,即 GET 方式傳入的參數(shù)名為 /?.* ,值為 {${phpinfo()}}  。

原先的語句: preg_replace('/(' . $regex . ')/ei', 'strtolower("\\1")', $value);
變成了語句: preg_replace('/(.*)/ei', 'strtolower("\\1")', {${phpinfo()}});


爬坑2

上面的 preg_replace 語句如果直接寫在程序里面,當(dāng)然可以成功執(zhí)行 phpinfo() ,然而我們的 .* 是通過 GET 方式傳入,你會發(fā)現(xiàn)無法執(zhí)行 phpinfo 函數(shù),如下圖:

我們 var_dump 一下 $_GET 數(shù)組,會發(fā)現(xiàn)我們傳上去的 .* 變成了 _* ,如下圖所示:

這是由于在PHP中,對于傳入的非法的 $_GET 數(shù)組參數(shù)名,會將其轉(zhuǎn)換成下劃線,這就導(dǎo)致我們正則匹配失效。我們可以 fuzz 一下PHP會將哪些符號替換成下劃線,發(fā)現(xiàn)有:(這是非法字符不為首字母的情況)

當(dāng)非法字符為首字母時,只有點(diǎn)號會被替換成下劃線:

所以我們要做的就是換一個正則表達(dá)式,讓其匹配到 {${phpinfo()}} 即可執(zhí)行 phpinfo 函數(shù)。這里我提供一個 payload : \S*=${phpinfo()} 執(zhí)行結(jié)果如下:

爬坑3

下面再說說我們?yōu)槭裁匆ヅ涞?{${phpinfo()}} 或者 ${phpinfo()} ,才能執(zhí)行 phpinfo 函數(shù),這是一個小坑。這實(shí)際上是PHP可變變量 的原因。在PHP中雙引號包裹的字符串中可以解析變量,而單引號則不行。 ${phpinfo()} 中的 phpinfo() 會被當(dāng)做變量先執(zhí)行,執(zhí)行后,即變成 ${1} (phpinfo()成功執(zhí)行返回true)。如果這個理解了,你就能明白下面這個問題:

var_dump(phpinfo()); // 結(jié)果:布爾 true
var_dump(strtolower(phpinfo()));// 結(jié)果:字符串 '1'
var_dump(preg_replace('/(.*)/ie','1','{${phpinfo()}}'));// 結(jié)果:字符串'11'

var_dump(preg_replace('/(.*)/ie','strtolower("\\1")','{${phpinfo()}}'));// 結(jié)果:空字符串''
var_dump(preg_replace('/(.*)/ie','strtolower("{${phpinfo()}}")','{${phpinfo()}}'));// 結(jié)果:空字符串''
這里的'strtolower("{${phpinfo()}}")'執(zhí)行后相當(dāng)于 strtolower("{${1}}") 又相當(dāng)于 strtolower("{null}") 又相當(dāng)于 '' 空字符串

總結(jié)

這個問題是我們在做 PHP-Audit-Labs 項(xiàng)目的時候發(fā)現(xiàn)的,我們盡可能地將每一篇文章的漏洞理解透徹,分析清楚,這對自身也是一種提高。

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

您可能感興趣的文章:
  • PHP preg_replace() 正則替換所有符合條件的字符串
  • PHP 字符串正則替換函數(shù)preg_replace使用說明
  • PHP正則替換函數(shù)preg_replace和preg_replace_callback使用總結(jié)
  • php正則之函數(shù) preg_replace()參數(shù)說明
  • 詳解PHP正則表達(dá)式替換實(shí)現(xiàn)(PHP preg_replace,PHP preg_replace)
  • php中preg_replace正則替換用法分析【一次替換多個值】
  • php preg_replace替換實(shí)例講解
  • PHP 正則表達(dá)式之正則處理函數(shù)小結(jié)(preg_match,preg_match_all,preg_replace,preg_split)
  • php中preg_replace_callback函數(shù)簡單用法示例
  • php中使用preg_replace函數(shù)匹配圖片并加上鏈接的方法

標(biāo)簽:衡陽 鄂州 崇左 白銀 辛集 綏化 廊坊 太原

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《深入研究PHP中的preg_replace和代碼執(zhí)行》,本文關(guān)鍵詞  深入研究,PHP,中的,preg,replace,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《深入研究PHP中的preg_replace和代碼執(zhí)行》相關(guān)的同類信息!
  • 本頁收集關(guān)于深入研究PHP中的preg_replace和代碼執(zhí)行的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章