尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Web安全实战:从.git泄露到PHP弱类型比较漏洞的完整利用链

Web安全实战:从.git泄露到PHP弱类型比较漏洞的完整利用链 1. 项目概述一次典型的Web安全实战演练Lottery这个靶场在攻防世界的Web进阶区里算是一个“经典中的经典”。我第一次接触它的时候感觉就像拿到了一份结构清晰的“漏洞利用说明书”它把Web安全中两个非常核心且常见的漏洞类型——信息泄露和业务逻辑漏洞——巧妙地串联在了一起。对于刚入门CTF Web方向的新手来说这个靶场价值极高因为它不像一些脑洞大开的题目那样需要天马行空的想象力而是非常贴近真实的渗透测试流程先通过信息泄露拿到“地图”源码再仔细审计代码找到逻辑上的薄弱点最后构造攻击链拿到Flag。整个过程逻辑清晰步骤明确能让你建立起一个完整的“发现-分析-利用”的思维闭环。简单来说这个靶场模拟了一个在线彩票购买与开奖系统。你的目标就是作为一名“安全研究员”找出系统中的漏洞最终获取到代表胜利的Flag。它主要考察两个点一是对.git目录泄露这一常见配置错误的利用能力二是对PHP弱类型比较Weak Comparison这一经典逻辑漏洞的理解和利用。很多新手在解题时往往只关注其中一个点或者知道了漏洞类型却不知道如何串联起来形成有效攻击这篇指南就是带你一步步拆解避开那些我当年踩过的坑稳稳拿下这道题。2. 核心漏洞原理深度拆解为什么是它们在动手之前我们必须把靶场背后的“原理”吃透。知其然更要知其所以然这样以后遇到变种题目才能举一反三。Lottery靶场的核心就在于.git泄露与逻辑漏洞的“梦幻联动”。2.1 .git泄露不只是源代码更是攻击者的“导航图”.git目录是Git版本控制系统的核心它记录了项目的所有版本历史、分支、提交信息等。在开发环境中这无比重要但在生产环境如果运维人员疏忽将.git目录随代码一起部署到了Web服务器上那就相当于把项目的“设计图纸”和“施工日志”直接公开了。为什么这会成为严重漏洞源码暴露攻击者可以通过访问/.git/目录利用一些工具如githack,GitHacker还原出网站的完整源代码。没有源码黑盒测试如同盲人摸象有了源码就变成了白盒审计难度直线下降。敏感信息泄露源码中可能硬编码数据库密码、API密钥、后台路径等敏感信息。目录结构清晰化通过源码可以清晰了解网站的文件结构、入口点、包含关系为后续的漏洞挖掘铺平道路。在Lottery靶场中.git泄露就是我们整个攻击链的起点。没有它我们可能需要在黑暗中摸索api.php的接口参数和逻辑有了它我们就能像开发者一样审视buy()函数的具体实现。2.2 逻辑漏洞弱类型比较业务安全的“阿喀琉斯之踵”逻辑漏洞不同于SQL注入、XSS这类技术型漏洞它源于程序业务流程设计或实现上的缺陷。攻击者通过输入非预期数据干扰程序正常逻辑达到越权、篡改、欺骗等目的。Lottery靶场利用的是一个非常典型的PHP特性引发的逻辑漏洞松散比较Loose Comparison。PHP中有两种比较运算符或!松散比较。在比较前会尝试进行类型转换。或!严格比较。同时比较值和类型。漏洞产生的核心场景 假设源码中有这样一段校验彩票号码的逻辑if ($_POST[winning_numbers] $winning_numbers) { // 中奖逻辑 $money $big_price; }这里的$winning_numbers是从数据库或文件中读取的正确开奖号码是一个字符串比如123456。 而$_POST[winning_numbers]是用户提交的数据。危险就隐藏在类型转换里 如果用户提交的winning_numbers参数不是字符串而是一个数字比如123456PHP在进行比较时会尝试将两者转换为同一类型再比较。字符串123456在比较时会被转换成数字123456于是123456 123456成立用户中奖。但更经典、更隐蔽的利用方式是科学计数法字符串。 如果用户提交winning_numbers1e6字符串。$winning_numbers1000000(字符串)$_POST[winning_numbers]1e6(字符串)在进行比较时PHP看到两个字符串但其中1e6看起来像科学计数法PHP会将其转换为数字1000000。同时字符串1000000也会被转换为数字1000000。于是1e6 1000000结果为true。这意味着什么这意味着攻击者不需要知道确切的中奖号码1000000只需要提交一个在数值上与其相等的科学计数法字符串1e6就能绕过校验这就是Lottery靶场buy接口漏洞的精髓所在。审计源码时找到哪里使用了来比较用户可控输入和关键数据哪里就可能是突破口。3. 靶场实战步步为营的渗透流程理论清楚了我们开始实战。假设靶场地址是http://xxx.xxx.xxx.xxx:port/。3.1 第一步信息收集与.git泄露利用首先用浏览器访问目标地址看到一个彩票购买页面。常规操作是用目录扫描工具如dirsearch,gobuster扫一下。dirsearch -u http://xxx.xxx.xxx.xxx:port/ -e *或者简单点直接浏览器访问http://xxx.xxx.xxx.xxx:port/.git/如果返回403 Forbidden说明目录存在但禁止列表或者有特定响应就基本可以确认存在.git泄露。利用工具还原源码这里推荐使用GitHacker它比早期的githack更强大稳定。python3 GitHacker.py http://xxx.xxx.xxx.xxx:port/.git/ --output-folder ./lottery_source执行后当前目录下的lottery_source文件夹里就是完整的网站源码了。避坑提示1有些题目可能对.git目录做了部分删除比如删除了index文件。这时GitHacker这类工具的优势就体现出来了它能通过分析其他对象文件尽力还原。如果工具报错或还原不全可以尝试手动访问.git/objects/下的文件但过程繁琐。优先信任成熟工具的输出。3.2 第二步源码审计与漏洞定位拿到源码后开始白盒审计。主要关注几个文件index.php前端页面。api.php通常处理所有后端API请求是重点审计对象。其他配置文件或功能文件。打开api.php寻找buy函数或处理购买逻辑的代码段。经过审计你会发现关键代码类似如下此为还原后的逻辑非原题一字不差// api.php 中处理购买彩票的部分 function buy($lottery) { $winning_numbers //...从某个地方如文件读取本次开奖号码假设是1000000 $user_numbers $_POST[numbers]; // 用户提交的号码 if ($user_numbers $winning_numbers) { // 中奖用户余额增加一大笔钱远大于彩票价格 add_money($user, $big_price); return json_encode([statusok, msgCongratulations!]); } else { // 未中奖扣取彩票费用 deduct_money($user, $cost); return json_encode([statusfail, msgTry again.]); } }漏洞点清晰可见if ($user_numbers $winning_numbers)使用了松散比较。并且$winning_numbers是固定的或者可预测的例如从../config/winning_numbers.txt读取。下一步我们需要知道$winning_numbers到底是什么继续审计源码查找设置或读取中奖号码的地方。可能会发现一个admin功能或文件比如../config/winning_numbers.txt里面写着本次的中奖号码1000000。避坑提示2审计时不要只看一个文件。关注include、require语句跟着文件包含关系走。有时中奖号码可能存储在数据库但题目为了方便常放在文件里。找到这个文件路径就是成功的一半。3.3 第三步构造攻击请求与利用现在我们掌握了漏洞位置api.php的buy接口使用进行号码比对。关键数据本次中奖号码为字符串1000000。攻击思路我们不需要提交1000000只需要提交一个在松散比较下等于1000000的值即可。科学计数法1e6是完美选择。如何利用首先我们需要知道调用buy接口的完整方式。查看前端页面index.php的JavaScript或者审计api.php开头的路由逻辑。通常格式是POST /api.php?actionbuy 参数: numbersYOUR_NUMBER也可能需要额外的Cookie或Token来维持会话题目一般会提供初始的Cookie。使用Burp Suite或直接curl构造请求curl -X POST http://xxx.xxx.xxx.xxx:port/api.php?actionbuy \ -H Cookie: PHPSESSID你的sessionid \ -d numbers1e6预期结果服务器返回中奖成功的信息并且你的账户余额如果题目有余额显示会暴涨。3.4 第四步获取Flag中奖之后呢通常Flag不会直接因为中奖就给你。常见的设定是你需要用中奖获得的大量“金钱”去购买一个昂贵的“Flag”商品。或者余额达到某个阈值后在某个页面如/flag.php,/profile.php会自动显示Flag。需要你去触发另一个兑换或查看的功能。继续审计源码寻找与Flag相关的逻辑。例如可能有一个get_flag接口或者在前端页面当余额money 1000000时会显示一段隐藏的Flag信息。用你暴涨后的余额去访问用户中心、商店页面或者直接调用api.php?actionget_flag最终就能拿到Flag。避坑提示3不要中奖后就觉得结束了。仔细阅读题目描述和前端页面的所有文字提示结合源码找到Flag的最终产出点。有时候Flag可能编码了拿到后还需要进行一次简单的解码如Base64。4. 漏洞利用的精细化与常见问题排查在实际操作中事情未必总是一帆风顺。下面是一些你可能遇到的问题及解决方案。4.1 问题1.git目录访问返回403或404可能原因1目录存在但服务器配置了禁止访问。这反而是强提示。使用GitHacker等工具依然可以尝试利用因为它们是通过构造请求访问.git/objects下的特定文件来还原的不一定要直接列出目录。可能原因2题目路径不是根目录。比如靶场实际路径是http://xxx.xxx.xxx.xxx:port/lottery/那么.git目录就在/lottery/.git/。仔细查看网站所有链接的路径。排查命令# 尝试直接访问一个已知的git对象文件验证是否存在 curl -I http://xxx.xxx.xxx.xxx:port/.git/HEAD # 如果返回200 OK说明泄露存在4.2 问题2利用工具还原源码失败或不全可能原因.git目录不完整或者工具版本问题。解决方案尝试使用其他工具如dvcs-ripper(rip-git.pl) 或githack。手动利用先下载.git/index文件如果存在解析出文件列表然后根据列表去objects目录下载对应的文件最后用Git命令还原。这个过程复杂仅作为最后手段。更重要的思路也许你不需要完整的源码。只需要关键文件如api.php。你可以尝试直接猜测或通过常见路径爆破访问api.php本身。有时题目.git泄露是幌子或者只需要你意识到漏洞类型直接攻击即可。4.3 问题3提交“1e6”后并未中奖可能原因1中奖号码不是1000000。你需要确认源码中读取的准确号码。重新审计api.php找到它包含哪个文件或者查询哪个数据库字段。号码可能是随机的但通常在这种题目里是固定的。可能原因2请求格式错误。用Burp Suite拦截浏览器正常购买一次的请求观察完整的请求方法、URL、参数名、Cookie、可能的Token。然后在其基础上修改numbers参数。可能原因3存在其他校验。例如可能先检查numbers是否为纯数字字符串is_numeric而1e6可以通过is_numeric检查。但也可能检查长度如果中奖号码是8位你提交1e8可能不行需要提交1e710000000这里需要灵活变通。1e6、1.0e6、1000000、0.1e7都可以尝试。排查步骤本地测试将关键PHP代码复制到本地环境用不同输入测试比较的结果。模糊测试写一个简单的Python脚本批量提交一些科学计数法变种。import requests url http://target/api.php?actionbuy cookies {PHPSESSID: yoursession} for i in range(5, 9): # 尝试1e5到1e8 payload {numbers: f1e{i}} r requests.post(url, datapayload, cookiescookies) if Congratulations in r.text: print(fSuccess with payload: 1e{i}) break4.4 问题4中奖后不知道如何获取Flag系统化搜索在还原的源码中全局搜索关键词flag,getflag,win,success,money,balance。查看所有PHP文件特别是那些看起来像admin.php,profile.php,flag.php,redeem.php的文件。分析前端JavaScript看中奖成功后是否有跳转或异步请求。用Burp Suite的Proxy历史记录或Repeater模块重放中奖后的请求观察响应里是否有隐藏链接或提示。常见位置api.php?actionflagindex.php?pageflag余额足够后刷新index.phpFlag直接显示在页面上。需要POST到某个接口用钱“购买”Flag。5. 防御方案与安全编程思考作为攻击者我们利用漏洞作为开发者我们必须避免制造漏洞。通过这道题我们可以总结出至关重要的安全开发经验。5.1 杜绝信息泄露生产环境配置清单代码仓库确保.git,.svn,.hg等版本控制目录不在Web根目录下或通过Web服务器如Nginx, Apache配置禁止访问这些目录。Apache: 在.htaccess中添加RedirectMatch 404 /\.gitNginx: 在配置中添加location ~ /\.git { deny all; return 404; }备份文件删除或移走.bak,.swp,.old等备份文件。错误信息关闭PHP的display_errors将error_reporting设置为生产环境级别避免SQL错误、路径信息等泄露。目录列表关闭Web服务器的目录浏览功能。5.2 根治逻辑漏洞安全的比较与校验使用严格比较在PHP中永远使用和!进行比较尤其是涉及用户输入、密码哈希、敏感标识时。// 错误 if ($input $secret) { ... } // 正确 if ($input $secret) { ... }类型意识明确变量应有的类型。对于期望是字符串的用is_string()检查期望是整数的用intval()转换后再用比较或者用filter_var($input, FILTER_VALIDATE_INT)。$user_numbers (string)$_POST[numbers]; // 强制转为字符串 if ($user_numbers $winning_numbers) { ... } // 字符串严格比较业务逻辑自洽像“彩票中奖”这样的核心业务逻辑校验应该放在服务端并且要多重校验。例如除了比较号码还应校验购买期数、用户身份、时间有效性等。避免“一步校验定乾坤”。关键操作幂等与验证购买、兑奖等操作应加入随机TokenCSRF Token、验证码或二次确认防止重放攻击和自动化脚本利用。5.3 安全开发流程建议代码审计将安全作为代码审查的一部分。重点关注用户输入点、数据库操作、文件操作、命令执行、比较运算。黑白盒测试定期进行安全测试。白盒结合源码审计黑盒模拟攻击者行为。依赖更新保持框架、库的更新已知漏洞及时修补。最小权限原则Web应用程序运行账户应具有最小必要权限数据库连接使用低权限用户。回过头看Lottery这道题它就像一把精巧的钥匙为你打开了Web安全中“信息泄露”和“逻辑漏洞”这两扇大门。掌握它你学会的不仅仅是两个漏洞的利用更是一种“由外到内、由浅入深”的渗透测试思维。下次再遇到类似的靶场或真实场景你会自然而然地先去摸摸有没有.git看看接口参数有没有用这种条件反射式的思考才是练习CTF带来的最宝贵的财富。记住工具和技巧是招式而渗透思维才是内功。多练、多思考、多总结你的“漏洞嗅觉”会越来越敏锐。
返回列表