如何将代码审计变成CTF---面向github代码审计
字数 1420 2025-08-26 22:11:57

如何将代码审计变成CTF——面向GitHub代码审计的教学文档

前言

代码审计是安全研究中的重要技能,但对于初学者来说,面对大型项目的代码审计往往无从下手。本文通过将代码审计转化为类似CTF挑战的方式,降低入门门槛,帮助初学者快速找到漏洞。

核心思路

将大型CMS的代码审计降维为CTF题目,重点关注:

  1. 曾经出过漏洞的功能点
  2. 开发者多次修复但仍可能绕过的漏洞
  3. 使用GitHub的issue和commit历史作为审计线索

实战案例:iCMS的SSRF漏洞审计

目标选择

  • 项目:iCMS (GitHub百星项目)
  • 漏洞类型:SSRF (Server Side Request Forgery)
  • 审计方法:通过GitHub issue和commit历史追踪漏洞演变

漏洞演变过程

初始漏洞 (CVE-2018-14514)

漏洞点

  1. postUrl函数:直接使用用户可控的URL参数进行curl请求
  2. 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)

修复措施

  1. 禁用curl的自动跳转(CURLOPT_FOLLOWLOCATION)
  2. 添加DNS解析检查
  3. 限制端口(仅允许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式的挑战,可以:

  1. 降低大型项目审计的复杂度
  2. 提高漏洞发现的效率
  3. 深入理解漏洞修复与绕过的对抗过程

关键点

  • 历史漏洞点是审计的黄金位置
  • 开发者的修复往往不彻底
  • 系统组件(如curl)的解析差异可能成为突破口
  • GitHub的issue和commit是宝贵的审计资源

扩展学习

  1. 其他常见审计目标:

    • 曾经出现过XSS的功能点
    • 多次修复的SQL注入点
    • 文件上传功能的多次修改
  2. 推荐资源:

    • Orange的"A New Era of SSRF"演讲
    • PHP官方文档中的URL解析部分
    • 各版本curl的更新日志
如何将代码审计变成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请求 漏洞代码 : 利用方式 : 使用 dict:// 、 gopher:// 等危险协议 访问内网服务如Redis、MySQL等 第一次修复 修复措施 : 添加URL格式检查,只允许 http:// 和 https:// 开头的URL 修复代码 : 问题 : 仅限制了协议类型,SSRF漏洞依然存在 仍可通过HTTP协议访问内网服务 第二次修复 (CVE-2018-14858) 修复措施 : 添加IP地址格式检查 过滤内网IP地址 修复代码 : 问题 : 未考虑302重定向和DNS重绑定攻击 第三次修复 (CVE-2018-15895) 修复措施 : 禁用curl的自动跳转( CURLOPT_FOLLOWLOCATION ) 添加DNS解析检查 限制端口(仅允许80和443) 修复代码 : 最终绕过方法 利用点 :PHP的 parse_url 与libcurl解析URL的差异 原理 : PHP的 parse_url 将最后一个 @ 后的内容作为host libcurl将第二个 @ 后的内容作为host Payload : 影响版本 : 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的更新日志