通过遍历AST来解 SCTF 2021 FUMO_on_the_Christmas_tree
字数 1735 2025-08-29 08:30:36

SCTF 2021 FUMO_on_the_Christmas_tree 解题分析与AST遍历技术教学

1. 题目背景与概述

题目提供了一个14万行的PHP文件,主要考察通过静态分析技术(特别是AST遍历)来寻找从source(__destruct函数)到sink(readfile函数)的利用路径。

2. 关键概念解析

2.1 Source与Sink

  • Source: 漏洞利用的起点,本题中是__destruct魔术方法
  • Sink: 危险函数调用点,本题中是readfile函数

2.2 AST (抽象语法树)

AST是源代码的树状表示,便于程序分析和转换。在PHP中,AST节点类型包括:

  • FunctionCall(函数调用)
  • ClassMethod(类方法)
  • 其他表达式和语句节点

3. 静态分析技术详解

3.1 Call Graph构建

3.1.1 直接调用分析

@$this->QsIFY2PS->xly0ZQT($Q0CGxlEy);

分析步骤:

  1. 查找方法名为xly0ZQT的ClassMethod节点
  2. 从当前ClassMethod创建call边指向目标方法

3.1.2 __call魔术方法处理

当找不到直接方法时(如@$this->oS9D89Gt->Ws2xymT($NOCGzO)),需要通过__call分析:

  1. 识别__call中的extractcall_user_func调用
  2. 提取extract中的硬编码字符串作为目标方法名

3.1.3 __invoke魔术方法处理

对于@call_user_func($this->WHB5xkK7, ['LUlnpp' => $RwGAFc8G])这类调用:

  1. 检查类是否实现了__invoke方法
  2. 验证base64_decode参数是否匹配call_user_func参数的base64编码值

3.2 污点传播分析

3.2.1 变量状态跟踪

为每个方法创建变量状态Map,跟踪变量是否可控:

  • 参数传入:默认标记为可控 变量状态[参数名] = true
  • 赋值操作
    • $b = foo($a):若foo是sanitizer函数,则变量状态[b] = false
    • $b = $a:直接继承状态 变量状态[b] = 变量状态[a]

3.2.2 Sanitizer函数识别

本题中的sanitizer函数包括:

  • crypt
  • md5
  • sha1
  • base64_encode(需配合base64_decode计数器使用)

4. 解题实现步骤

4.1 工具选择

使用github.com/VKCOM/php-parser解析PHP8代码,基于Go语言编写分析工具:

  • 优势:处理大规模代码效率高
  • 替代方案:CodeQL(但原生不支持PHP)

4.2 分析流程

  1. 解析PHP生成AST
  2. 遍历AST识别所有ClassMethod节点
  3. 构建Call Graph:
    • 处理直接调用
    • 处理__call__invoke魔术方法
  4. 执行污点传播分析
  5. 查找从__destructreadfile的可达路径

4.3 关键代码逻辑

// 伪代码示例
func buildCallGraph(astNode) {
    switch node := astNode.(type) {
    case *php.FunctionCall:
        if isMethodCall(node) {
            // 处理直接方法调用
            resolveDirectCall(node)
        } else if isCallUserFunc(node) {
            // 处理call_user_func
            resolveCallUserFunc(node)
        }
    // 其他节点处理...
    }
}

func taintAnalysis(methodNode) {
    // 初始化变量状态
    state := make(map[string]bool)
    
    // 标记参数为可控
    for _, param := range methodNode.Params {
        state[param.Name] = true
    }
    
    // 遍历方法体语句
    for _, stmt := range methodNode.Stmts {
        // 处理赋值和函数调用
    }
}

5. 高级技巧与优化

5.1 动态特性处理

  • extractcall_user_func进行特殊处理
  • 跟踪变量名生成模式(如base64编码值)

5.2 路径优化

  • 优先分析短调用链
  • 对sanitizer函数进行标记,提前终止不可行路径

5.3 误报消除

  • 实现base64_encode/base64_decode计数器平衡检测
  • 添加更多sanitizer函数识别

6. 总结与扩展

6.1 技术总结

  1. AST遍历是静态分析的核心
  2. Call Graph构建需要考虑PHP特有的魔术方法
  3. 污点传播需要精确跟踪变量状态

6.2 扩展应用

  • 可应用于其他PHP代码审计场景
  • 技术可迁移至其他语言的静态分析工具开发
  • 结合动态分析提高准确性

6.3 改进方向

  • 实现更精确的字符串分析
  • 添加类型推断减少误报
  • 支持更多PHP动态特性分析

附录:参考工具与资源

  1. php-parser - PHP8解析器
  2. 解题工具源码
  3. CodeQL(虽然不支持PHP,但分析思路可借鉴)
SCTF 2021 FUMO_ on_ the_ Christmas_ tree 解题分析与AST遍历技术教学 1. 题目背景与概述 题目提供了一个14万行的PHP文件,主要考察通过静态分析技术(特别是AST遍历)来寻找从source( __destruct 函数)到sink( readfile 函数)的利用路径。 2. 关键概念解析 2.1 Source与Sink Source : 漏洞利用的起点,本题中是 __destruct 魔术方法 Sink : 危险函数调用点,本题中是 readfile 函数 2.2 AST (抽象语法树) AST是源代码的树状表示,便于程序分析和转换。在PHP中,AST节点类型包括: FunctionCall(函数调用) ClassMethod(类方法) 其他表达式和语句节点 3. 静态分析技术详解 3.1 Call Graph构建 3.1.1 直接调用分析 分析步骤: 查找方法名为 xly0ZQT 的ClassMethod节点 从当前ClassMethod创建call边指向目标方法 3.1.2 __call 魔术方法处理 当找不到直接方法时(如 @$this->oS9D89Gt->Ws2xymT($NOCGzO) ),需要通过 __call 分析: 识别 __call 中的 extract 和 call_user_func 调用 提取 extract 中的硬编码字符串作为目标方法名 3.1.3 __invoke 魔术方法处理 对于 @call_user_func($this->WHB5xkK7, ['LUlnpp' => $RwGAFc8G]) 这类调用: 检查类是否实现了 __invoke 方法 验证 base64_decode 参数是否匹配 call_user_func 参数的base64编码值 3.2 污点传播分析 3.2.1 变量状态跟踪 为每个方法创建变量状态Map,跟踪变量是否可控: 参数传入 :默认标记为可控 变量状态[参数名] = true 赋值操作 : $b = foo($a) :若 foo 是sanitizer函数,则 变量状态[b] = false $b = $a :直接继承状态 变量状态[b] = 变量状态[a] 3.2.2 Sanitizer函数识别 本题中的sanitizer函数包括: crypt md5 sha1 base64_encode (需配合 base64_decode 计数器使用) 4. 解题实现步骤 4.1 工具选择 使用 github.com/VKCOM/php-parser 解析PHP8代码,基于Go语言编写分析工具: 优势:处理大规模代码效率高 替代方案:CodeQL(但原生不支持PHP) 4.2 分析流程 解析PHP生成AST 遍历AST识别所有ClassMethod节点 构建Call Graph: 处理直接调用 处理 __call 和 __invoke 魔术方法 执行污点传播分析 查找从 __destruct 到 readfile 的可达路径 4.3 关键代码逻辑 5. 高级技巧与优化 5.1 动态特性处理 对 extract 和 call_user_func 进行特殊处理 跟踪变量名生成模式(如base64编码值) 5.2 路径优化 优先分析短调用链 对sanitizer函数进行标记,提前终止不可行路径 5.3 误报消除 实现 base64_encode / base64_decode 计数器平衡检测 添加更多sanitizer函数识别 6. 总结与扩展 6.1 技术总结 AST遍历是静态分析的核心 Call Graph构建需要考虑PHP特有的魔术方法 污点传播需要精确跟踪变量状态 6.2 扩展应用 可应用于其他PHP代码审计场景 技术可迁移至其他语言的静态分析工具开发 结合动态分析提高准确性 6.3 改进方向 实现更精确的字符串分析 添加类型推断减少误报 支持更多PHP动态特性分析 附录:参考工具与资源 php-parser - PHP8解析器 解题工具源码 CodeQL(虽然不支持PHP,但分析思路可借鉴)