如何将代码审计变成CTF---面向github代码审计
字数 1420 2025-08-26 22:11:57
如何将代码审计变成CTF——面向GitHub代码审计的教学文档
前言
代码审计是安全研究中的重要技能,但对于初学者来说,面对大型项目的代码审计往往无从下手。本文通过将代码审计转化为类似CTF挑战的方式,降低入门门槛,帮助初学者快速找到漏洞。
核心思路
将大型CMS的代码审计降维为CTF题目,重点关注:
- 曾经出过漏洞的功能点
- 开发者多次修复但仍可能绕过的漏洞
- 使用GitHub的issue和commit历史作为审计线索
实战案例:iCMS的SSRF漏洞审计
目标选择
- 项目:iCMS (GitHub百星项目)
- 漏洞类型:SSRF (Server Side Request Forgery)
- 审计方法:通过GitHub issue和commit历史追踪漏洞演变
漏洞演变过程
初始漏洞 (CVE-2018-14514)
漏洞点:
postUrl函数:直接使用用户可控的URL参数进行curl请求remote函数:同样存在无限制的curl请求
漏洞代码:
public static function postUrl($url, $data) {
is_array($data) && $data = http_build_query($data);
$options = array(
CURLOPT_URL => $url,
// 其他curl选项...
);
$ch = curl_init();
curl_setopt_array($ch,$options);
$responses = curl_exec($ch);
curl_close ($ch);
return $responses;
}
利用方式:
- 使用
dict://、gopher://等危险协议 - 访问内网服务如Redis、MySQL等
第一次修复
修复措施:
- 添加URL格式检查,只允许
http://和https://开头的URL
修复代码:
public static function is_url($url,$strict=false) {
$url = trim($url);
if($strict){
return (stripos($url, 'http://') === 0 || stripos($url, 'https://') === 0);
}
// ...
}
问题:
- 仅限制了协议类型,SSRF漏洞依然存在
- 仍可通过HTTP协议访问内网服务
第二次修复 (CVE-2018-14858)
修复措施:
- 添加IP地址格式检查
- 过滤内网IP地址
修复代码:
preg_match('/\d+\.\d+\.\d+\.\d+/', $parsed['host']) &&
$validate_ip = filter_var($parsed['host'], FILTER_VALIDATE_IP,
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE);
问题:
- 未考虑302重定向和DNS重绑定攻击
第三次修复 (CVE-2018-15895)
修复措施:
- 禁用curl的自动跳转(
CURLOPT_FOLLOWLOCATION) - 添加DNS解析检查
- 限制端口(仅允许80和443)
修复代码:
// 禁用自动跳转
// CURLOPT_FOLLOWLOCATION => 1,
// DNS解析检查
@putenv('RES_OPTIONS=retrans:1 retry:1 timeout:1 attempts:1');
$ip = gethostbyname($parsed['host']);
$long = ip2long($ip);
@putenv('RES_OPTIONS');
最终绕过方法
利用点:PHP的parse_url与libcurl解析URL的差异
原理:
- PHP的
parse_url将最后一个@后的内容作为host - libcurl将第二个
@后的内容作为host
Payload:
http://m09ic@127.0.0.1:81@baidu.com/
影响版本:
- Ubuntu 16.04及以下(Curl 7.47.0)
- Ubuntu 18.04及以上已修复
代码审计方法论
1. 信息收集阶段
- 搜索项目issue中的漏洞报告
- 查找CVE记录
- 分析commit历史中的安全修复
2. 漏洞定位技巧
- 关注多次修复的功能点
- 检查开发者对漏洞的理解是否全面
- 寻找"哪里有问题就修哪里"的补丁模式
3. 绕过思路
- 分析补丁的过滤逻辑
- 寻找过滤逻辑中的盲点
- 尝试不同协议、编码和解析差异
4. 验证方法
- 搭建目标环境
- 使用简单payload测试基本功能
- 逐步构造复杂payload验证绕过
总结
通过将代码审计转化为CTF式的挑战,可以:
- 降低大型项目审计的复杂度
- 提高漏洞发现的效率
- 深入理解漏洞修复与绕过的对抗过程
关键点:
- 历史漏洞点是审计的黄金位置
- 开发者的修复往往不彻底
- 系统组件(如curl)的解析差异可能成为突破口
- GitHub的issue和commit是宝贵的审计资源
扩展学习
-
其他常见审计目标:
- 曾经出现过XSS的功能点
- 多次修复的SQL注入点
- 文件上传功能的多次修改
-
推荐资源:
- Orange的"A New Era of SSRF"演讲
- PHP官方文档中的URL解析部分
- 各版本curl的更新日志