靶场实战 · 12
PHP 反序列化(1 关)
Pikachu 靶场 · 1 关 · 难度 ★★★ · 预计 40 分钟
入口:http://127.0.0.1/pikachu/vul/unserilization/unser.php
过关标准:构造序列化字符串,触发弹窗
💡 类比故事序列化=把物体打包成"规格说明书"(字符串,方便运输/存储);反序列化=按说明书把物体重新组装。问题在于:组装的过程中(构造方法)会执行代码。如果攻击者能控制说明书内容,就能在"组装"时夹带自己的指令。
原理白话:序列化=把对象存成字符串,反序列化=把字符串变回对象。如果对象创建时(构造方法)会执行代码,而攻击者能控制序列化字符串,就能触发代码执行。
看源码:
class S {
var $test = "pikachu";
function __construct() {
echo $this->test; // 对象创建即输出
}
}
$s = unserialize($_GET['s']); // 直接反序列化用户输入
📋 详细步骤
- 访问:
http://127.0.0.1/pikachu/vul/unserilization/unser.php?s=O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";} - 弹窗即通关
- 解释字符串格式(重点):
O:1:"S" = 对象(Object),类名长度 1 的字符串 "S"1:{...} = 1 个属性s:4:"test" = 字符串(string),长度 4,内容是 "test"(属性名)s:29:"<script>..." = 字符串,长度 29,内容是属性值
- 反序列化时
__construct 被触发 → 输出我们伪造的 test → XSS 弹窗
过关标准达成:弹窗。学习要点:长度必须数对,差一个字符就失败——体会"构造 payload 要严谨"。深入一步:真实世界的反序列化 RCE 靠"魔术方法链"(gadget chain),入门阶段了解即可,进阶可深入研究。
🧯 卡住了?对号入座
- 现象:没弹窗 → 原因:长度数错了。
s:29 里的 29 必须等于引号内字符串的实际字符数(<script>alert('xss')</script> 正好 29 个字符)。逐字符数一遍
🛡 防御视角不反序列化用户输入;必须反序列化时用白名单类 + 校验签名。
🤔 想一想:为什么这一关的 payload 长度错了就失败?
答:序列化格式用长度定位字段,长度错位整个结构解析失败
入口:http://127.0.0.1/pikachu/vul/xxe/xxe_1.php
过关标准:提交恶意 XML 后,页面回显系统文件内容
💡 类比故事XML 是种数据格式(和 HTML 长得像)。应用解析你提交的 XML 时,如果允许"外部实体",你可以在 XML 里声明"这里的内容,去读 C 盘那个文件"——解析器会乖乖去读并回显。XML 不只传数据,还能"指使"解析器干活。
原理白话:应用解析用户提交的 XML 时,如果允许"外部实体",攻击者可以用 <!ENTITY> 声明实体引用任意文件/URL,XML 解析器会乖乖去读取并回显。
📋 详细步骤
- 页面表单输入恶意 XML:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<foo>&xxe;</foo>
(解释:<!ENTITY xxe SYSTEM "file:///etc/passwd"> 声明了一个叫 xxe 的实体,指向系统文件;<foo>&xxe;</foo> 引用它 → 解析器读文件并放进来)
- 提交 → 解析结果里出现
/etc/passwd 内容(macOS) - Windows 版本把实体改为:
SYSTEM "file:///c:/windows/win.ini" - 进阶:读靶场配置
file:///D:/phpstudy_pro/WWW/pikachu/inc/config.inc.php(按实际路径)
过关标准达成:任意本地文件被读出。
🧯 卡住了?对号入座
- 现象:实体没回显 → 原因:①DOCTYPE 声明位置和格式要对(在根元素前);②看响应里实体被展开的位置
- 现象:报"外部实体加载失败" → 原因:若 PHP/libxml 已禁用外部实体则本关打不出(PHPStudy 的 PHP 5.6 默认可);先排除 XML 语法错误
- 现象:file:// 读不到文件 → 原因:Windows 下路径写
file:///C:/Windows/win.ini(三个斜杠);Linux 用 /etc/passwd
🛡 防御视角禁止外部实体加载(libxml 中 libxml_disable_entity_loader(true),或用 JSON 替代 XML)。
🤔 想一想:XXE 和 SSRF 有什么联系?
答:外部实体可以指向内网 URL,让服务器代理访问内网——XXE 常作为 SSRF 的载体
入口:http://127.0.0.1/pikachu/vul/urlredirect/urlredirect.php
过关标准:改 url 参数实现任意跳转
💡 类比故事网站有个"中转站":点链接先到官网的跳转接口,再被送到目标页。这个接口不检查目标地址——攻击者把目标改成钓鱼站,用户看到链接开头是官网域名就放松了警惕,点进去却是假网站。"官方域名 + 跳转参数 = 看起来可信的钓鱼链接",是钓鱼的核心帮凶。
原理白话:跳转接口信任用户传的目标地址,跳转到钓鱼站点时用户毫无防备(地址栏一开始是可信域名)。
📋 详细步骤
- 页面上点链接 → 跳转目标由
?url= 参数控制(先正常点一次看流程) - 改成:
?url=https://www.baidu.com → 跳到百度(证明任意跳转成立) - 危险演示:
?url=javascript:alert(document.cookie) → 部分浏览器直接执行 JS
过关标准达成:任意跳转成立。
🧯 卡住了?对号入座
- 现象:改了 url 参数没跳转 → 原因:①确认参数名是 url;②改完要点页面上的"跳转"按钮/链接才会触发
- 现象:跳转被浏览器拦 → 原因:用完整 URL(http://www.baidu.com);本地靶场跳外网属正常,浏览器一般不会拦
- 现象:跳转后不知道算不算通关 → 原因:跳到目标网站即通关,重点是理解"站点做了跳转但没校验目标"的风险
🛡 防御视角跳转目标白名单(只允许本站 URL)+ 拒绝 javascript: 等协议。
🤔 想一想:为什么攻击者不直接发钓鱼链接,要借跳转?
答:借用可信域名增加可信度,绕过邮件/社交平台对陌生域名的告警
SSRF=让服务器替攻击者发请求。类比:攻击者打不进"内网"(比如公司内部系统),但内网里的服务器能访问内网。如果网站的某个功能允许"填一个 URL,我替你访问并显示结果",攻击者就把 URL 填成内网地址——服务器成了攻击者的"内应"。防火墙防外网,SSRF 从内网打内网。

第 1 关SSRF(curl)
入口:http://127.0.0.1/pikachu/vul/ssrf/ssrf_curl.php
过关标准:回显靶场"内网信息页"内容
💡 类比故事网站有个"URL 查看"工具:你给个网址,服务器用 curl 访问并把内容回显给你。你填自己电脑的网址 127.0.0.1——注意,这是服务器自己访问自己(服务器和你同一台机器)。填靶场内网信息页,就能看到"只有内网才能看"的内容。
原理白话:页面提供一个"URL 查看"工具,服务器用 curl 请求用户给的 URL 并回显——无任何目标校验。
看源码:
$url = $_GET['url'];
echo curl_exec($ch); // curl 用户可控的 URL
📋 详细步骤
- 输入
http://127.0.0.1/pikachu/ → 正常回显(注意:这是服务器自己访问自己,体会"服务器替你发请求") - 读靶场内网信息页:
http://127.0.0.1/pikachu/vul/ssrf/ssrf_info/info.php → 回显内部信息
📷 练习截图:SSRF 回显内网信息页内容
- macOS:
file:///etc/passwd 直接读本地文件(curl 支持 file 协议) - 了解内网探测思路:把 127.0.0.1 换成内网 IP 段(如 192.168.1.1)逐个探测端口——这就是打内网的入口(真实环境中这才是 SSRF 的完整用法,靶场里了解思路即可)
过关标准达成:内网资源被"借"服务器之手访问。
🧯 卡住了?对号入座
- 现象:请求没回显 → 原因:url 参数要传完整地址(含 http://);先试
http://127.0.0.1/pikachu 这种靶场自身地址 - 现象:返回错误/超时 → 原因:目标端口没开服务属正常;本关重点在"服务器替你去访问了内网地址"
- 现象:读不到内网其他机器 → 原因:靶场在你电脑上,"内网"就是本机各端口;换 127.0.0.1 的其他端口试
🤔 想一想:curl 这关能直接读服务器本机文件吗?
答:curl 默认打 http 协议;要读文件得配合 file:// 或靠下一关 file_get_contents,这正是两关能力的区别
🛡 防御视角URL 白名单 + 禁止内网地址段(127.0.0.0/8、10.0.0.0/8、192.168.0.0/16、169.254.0.0/16)+ 禁止 file/dict/gopher 等协议。
第 2 关SSRF(file_get_contents)
入口:http://127.0.0.1/pikachu/vul/ssrf/ssrf_fgc.php
过关标准:回显内网信息页内容
💡 类比故事同上,只是服务器"替你访问"用的函数换了一个(PHP 的 file_get_contents() 同样支持 URL 和 file 协议)。理解:危险的不是函数,而是"未校验的用户可控 URL"。
原理白话:同上,只是读取函数换成 PHP 的 file_get_contents(),它同样支持 URL 和 file 协议。
📋 详细步骤
?file=http://127.0.0.1/pikachu/vul/ssrf/ssrf_info/info.php → 内网信息回显- macOS:
?file=file:///etc/passwd → 本地文件读取 - 与 curl 版对照,理解"危险的不是函数,而是未校验的用户可控 URL"
过关标准达成:内网访问成立。
🧯 卡住了?对号入座
- 现象:file:// 协议失败 → 原因:确认 allow_url_fopen 开启;Windows 用
file:///C:/Windows/win.ini,Linux 用 file:///etc/passwd - 现象:返回空白 → 原因:文件不存在或路径错;先读一个确定存在的文本文件
- 现象:http 也不行 → 原因:与 3.15.1 相同,确认 url 参数完整(含协议头)
🛡 防御视角同 3.15.1。
🤔 想一想:SSRF 探测内网端口时,怎么判断端口是否开放?
答:看响应差异——返回内容/响应时间/错误信息不同
每通一关,在 □ 里打钩。建议配合"过关标准"自查,全部打钩后你就是这套靶场的全通选手了。
暴力破解(4 关)
- 3.1.1 表单暴力破解:Intruder 爆破出 123456
- 3.1.2 验证码绕过(on client):不理验证码爆破成功
- 3.1.3 验证码绕过(on server):复用验证码爆破成功
- 3.1.4 token 防爆破:脚本输出"密码是: 123456"
XSS(10 关)
- 3.2.1 反射型(get):F12 改 maxlength 或 Burp 改参数后弹窗
- 3.2.2 反射型(post):登录后提交 payload 弹窗
- 3.2.3 存储型:换浏览器访问同样弹窗
- 3.2.4 DOM 型:URL 构造 payload 弹窗
- 3.2.5 DOM 型-X:表单提交闭合 payload 弹窗
- 3.2.6 盲打:管理员后台中招,Cookie 被收走
- 3.2.7 过滤:img onerror 绕过弹窗
- 3.2.8 htmlspecialchars:javascript: 协议点链接弹窗
- 3.2.9 href 输出:javascript: 协议弹窗
- 3.2.10 js 输出:闭合引号弹窗
CSRF(3 关)
- 3.3.1 CSRF(get):点恶意链接资料被改
- 3.3.2 CSRF(post):本地钓鱼页自动提交成功
- 3.3.3 CSRF Token:错误 token 被服务器拒绝
SQL 注入(10 关)
- 3.4.1 数字型:or 1=1 查全表
- 3.4.2 字符型:引号闭合查全表
- 3.4.3 搜索型:%' or 1=1# 查全表
- 3.4.4 xx 型:') or 1=1# 查全表
- 3.4.5 insert/update:updatexml 报错带出库名
- 3.4.6 delete:报错带出库名
- 3.4.7 http header:改 User-Agent 报错带出库名
- 3.4.8 布尔盲注:真假差异猜出数据
- 3.4.9 时间盲注:sleep 延迟差异
- 3.4.10 宽字节:%df 吃掉反斜杠
RCE(2 关)
- 3.5.1 exec "ping":命令拼接执行 ipconfig/whoami
- 3.5.2 exec "eval":phpinfo() 页面出现
文件包含(2 关)
- 3.6.1 LFI:读出 win.ini / etc/passwd
- 3.6.2 RFI:远程 txt 代码被执行
文件上传(3 关)
- 3.7.1 client check:改包上传,蚁剑连上
- 3.7.2 MIME:改 Content-Type 上传,蚁剑连上
- 3.7.3 图片马:配合 LFI 执行代码
文件下载(1 关)
- 3.8 文件下载:下载到 config.inc.php
越权(2 关)
- 3.9.1 水平越权:lucy 看到 vince 信息
- 3.9.2 垂直越权:普通用户自封管理员
目录遍历(1 关)
敏感信息泄露(1 关)
PHP 反序列化(1 关)
XXE(1 关)
URL 跳转(1 关)
SSRF(2 关)
- 3.15.1 SSRF(curl):回显内网信息页
- 3.15.2 SSRF(file_get_contents):回显内网信息页
| 漏洞类型 | 一句话成因 | 一句话防御 |
|---|
| 暴力破解 | 无次数限制、验证码失效 | 失败锁定 + 服务端一次性验证码 + token |
| XSS | 用户输入进 HTML 未编码 | 输出按上下文编码(htmlspecialchars/JS转义/URL协议白名单) |
| CSRF | 浏览器自动带 Cookie + 无来源校验 | CSRF Token + SameSite + 关键操作二次确认 |
| SQL 注入 | 输入拼进 SQL 语句 | 参数化查询(一切注入的正解) |
| RCE | 输入拼进命令/eval | 白名单 + 禁危险函数 + 最小权限 |
| 文件包含 | 文件名参数可控 | 白名单 + 关闭 allow_url_include |
| 文件上传 | 校验可绕过、脚本可执行 | 服务端内容校验 + 上传目录禁执行 + 重命名 |
| 文件下载/目录遍历 | 路径参数可控 | id 映射 + 拒绝 ../ |
| 越权 | 只验登录不验归属/角色 | 对象级授权(用 session 身份取数)+ 接口级 RBAC |
| 信息泄露 | 注释/备份/报错藏敏感信息 | 上线前敏感扫描 + 统一错误页 |
| 反序列化 | 反序列化用户输入 | 不反序列化不可信输入 / 白名单类 |
| XXE | XML 外部实体未禁用 | 禁用 DTD/外部实体 |
| URL 跳转 | 跳转目标未校验 | 域名白名单 + 协议白名单 |
| SSRF | 服务器代发请求目标未校验 | URL 白名单 + 禁内网地址/危险协议 |
暴力破解
- 简述验证码绕过(on server)关卡为什么同一个验证码能反复用?(要点:session 未销毁,一次性机制缺失)
- token 防爆破关卡的 token 从哪来?为什么爆破工具不能直接重用?(要点:服务端生成、每次刷新、攻击者拿不到新值)
- 设计一个登录接口的三个防爆破措施。(要点:锁定/限流/验证码/token 任选三)
XSS
- 反射型、存储型、DOM 型三种 XSS 的区别?(要点:是否入库、是否经服务器、危害范围)
- 为什么过滤
<script> 关键字防不住 XSS?举两个绕过例子。(要点:img onerror、svg onload、大小写等) htmlspecialchars 使用正确(ENT_QUOTES)但输出在 href 里,还有风险吗?(要点:javascript: 协议,需协议白名单)- 盲打 XSS 的目标是谁?为什么选择打后台?(要点:管理员权限高、后台防护常被忽视)
CSRF
- 用一句话解释 CSRF 为什么能成立?(要点:浏览器自动携带 Cookie,服务器无法区分"本人操作"与"被伪造请求")
- GET 改 POST 能防 CSRF 吗?为什么?(要点:不能,POST 也能被自动提交表单伪造)
- CSRF Token 为什么攻击者拿不到?(要点:随机生成、同源策略保护、不在攻击者可读处)
SQL 注入
- 字符型注入 payload
1' or '1'='1 中每个部分的作用?(要点:闭合、恒真、语法补全) - 报错注入利用了什么机制把数据带出来?(要点:updatexml 等函数参数不合法→报错信息包含数据)
- 布尔盲注和时间盲注分别靠什么"信使"传数据?(要点:页面真假差异 / 响应时间)
- 宽字节注入为什么能绕过 addslashes?(要点:GBK 多字节吞掉反斜杠)
- 为什么参数化查询能防所有 SQL 注入?(要点:语句结构与数据分离,数据不再被解析为代码)
RCE / 文件包含 / 文件上传
- 命令注入里
; & && | 分别是什么作用?(要点:顺序/后台/与/管道) - 图片马为什么直接访问不执行、配合文件包含就执行?(要点:后缀不交 PHP 解释器 vs include 强制解析)
- 文件上传的三道正确防线?(要点:服务端内容校验、目录禁执行、重命名存储)
越权 / 信息泄露
- 水平越权和垂直越权的区别?(要点:同级别横向 vs 低权限上探高权限)
- "前端隐藏按钮"为什么不算权限控制?(要点:前端内容攻击者全可见,必须后端校验)
进阶漏洞
- XXE 中的 DTD 和实体是什么?(要点:DTD 定义结构、ENTITY 声明引用,外部实体可指向文件/URL)
- SSRF 为什么能突破防火墙?(要点:请求由内网服务器发出,防火墙放行)
- PHP 反序列化漏洞的根源是什么?(要点:unserialize 执行魔术方法,数据可控即代码可控)
期末实操考核说明(供参考):随机抽 3 关独立通关(不允许看手册),提交通关报告(截图 + 原理 + 修复建议)。
- 只能在本地靶场练习。对任何非授权系统(包括学校官网、同学电脑、云主机)测试漏洞,均可能触犯《刑法》第 285 条(非法侵入计算机信息系统罪)、第 286 条(破坏计算机信息系统罪)和《网络安全法》第 27 条
- 练习限
127.0.0.1 和本机局域网靶场;不得把攻击流量发到互联网真实网站 - 不传播、不出售攻击工具与手册给非课程同学;通关报告不公开发布
- 将来参与 SRC(漏洞赏金)平台时,须遵守平台授权范围,越界即违法
- 强调:学习攻击技术是为了防御,安全从业者的第一素质是底线意识
- Pikachu 源码仓库:https://github.com/zhuifengshaonianhanlu/pikachu
- PHPStudy 官网:https://www.xp.cn
- Burp Suite 社区版:https://portswigger.net/burp/communitydownload
- 中国蚁剑:https://github.com/AntSwordProject/antSword
- OWASP Top 10:https://owasp.org/www-project-top-ten/
本手册全部 payload 均针对本地 Pikachu 靶场环境,仅用于学习练习。使用时请按实际部署路径/端口微调。