PHP中preg_replace函式解析

落叶知枫眠發表於2024-08-03
preg_replace — 執行一個正規表示式的搜尋和替換
mixed preg_replace( mixed $pattern, mixed $replacement, mixed $subject)
搜尋subject中匹配pattern的部分,以replacement進行替換。 

常見於CTF競賽中web題目中

1、/g 表示該表示式將用來在輸入字串中查詢所有可能的匹配,返回的結果可以是多個。如果不加/g最多隻會匹配一個
2、/i 表示匹配的時候不區分大小寫,這個跟其它語言的正則用法相同
3、/m 表示多行匹配。什麼是多行匹配呢?就是匹配換行符兩端的潛在匹配。影響正則中的^$符號
4、/s 與/m相對,單行模式匹配。
5、/e 可執行模式,此為PHP專有引數,例如preg_replace函式。
6、/x 忽略空白模式。

對一個正規表示式模式或部分模式 兩邊新增圓括號 將導致相關 匹配儲存到一個臨時緩衝區 中
,所捕獲的每個子匹配都按照在正規表示式模式中從左到右出現的順序儲存。緩衝區編號從 1 開始,
最多可儲存 99 個捕獲的子表示式。每個緩衝區都可以使用 '\n' 訪問,其中 n 為一個標識特定緩衝區的
一位或兩位十進位制數。

<?php
$id = $_GET['id'];
$_SESSION['id'] = $id;

function complex($re, $str) {
   preg_replace( '/(' . $re . ')/ei','strtolower("\\1")', $str);
}


foreach($_GET as $re => $str) {
    echo complex($re, $str). "\n";
}

function getFlag(){
    @eval($_GET['cmd']);
}

#程式碼源於CTF題目“[BJDCTF2020]ZJCTF,不過如此”,部分解題過程。

其大致含義就是匹配出的任意內容,都用()包含起來,作為子字串,存在緩衝區,\1是訪問括號內的內容

對於該題可構造的部分payload:\S*=${phpinfo()}用來測試

實際為\S*=${getFlag()},其實為了利用/e來利用漏洞,使函式執行

對於payload中${}的解釋,它這裡其實是一個可變變數
我們輸入了${phpinfo()},那麼它呢因為被括號包裹了,就會存進緩衝區,而這裡用到了/e,就相當於將第二個語句給執行了,就相當於eval(xx),第二個語句也就是\1,而\1的含義是${phpinfo()},他這個時候總的語句呢就是eval(${phpinfo()}),這玩意就相當於變數裡面套變數,所以我們需要先執行裡面的,也就是${phpinfo()} 中的 phpinfo() 會被當做變數先執行,執行後,即變成 ${1} (phpinfo()成功執行返回true)

相關文章