从AST到100个某知名OA前台注入
字数 1811 2025-08-15 21:30:49
基于AST的Java代码审计技术详解
一、背景与概述
本文详细介绍了如何通过分析Java抽象语法树(AST)来自动化挖掘某知名OA系统中的SQL注入漏洞。该方法参考了Cobra工具的PHP解析器实现思路,通过遍历Java AST进行漏洞挖掘,成功筛选出160个前台注入点,并手工编写了约50个前台注入EXP。
二、预备知识
1. 目标系统介绍
- 某知名OA系统使用Java编写,代码相对古老
- SQL查询语句多采用拼接方式,缺乏参数化处理
- 过滤机制通过统一的Filter实现,存在绕过可能
- 主要功能通过JSP实现,可编译为Java Servlet
2. 编译原理基础
- 词法分析:将源代码分解为标记(token)
- 语法分析:根据语法规则构建AST
- AST包含程序源文件的所有结构化信息
3. 数据流分析关键概念
- Sink(污点函数):敏感函数如
executeSql、Runtime.exec() - Source(输入来源):用户可控输入如
request.getParameter() - Repair/Sanitizer(修复函数):过滤函数如
null2int、getIntValue - DataFlow(数据流):变量在代码中的传递路径
三、环境准备
1. 搭建测试环境
- 下载并安装某知名OA 8 (Ecology8.100.0531)
- 默认配置安装即可
2. 获取JSP文件路径
import os
def get_files(path=r"D:\WEAVER\ecology\"):
g = os.walk(path)
result = []
for path, d, file_list in g:
for filename in file_list:
full_path = os.path.join(path, filename)
result.append([full_path, filename])
return result
3. 获取可访问JSP列表
- 使用Burp Intruder或Python脚本遍历JSP文件
- 筛选HTTP响应码为200的JSP文件
4. 获取Servlet.java文件
- 从
D:\WEAVER\ecology\WEB-INF\work\_jsp目录复制生成的Servlet文件
四、技术实现
1. Java AST解析器选择
- 使用Python的
javalang库解析Java代码为AST - 安装:
pip install javalang
2. PHP与Java AST节点对照表
| PHP节点 | Java节点 | 描述 |
|---|---|---|
| php.Variable | MemberReference | 变量引用 |
| php.FunctionCall | MethodInvocation | 函数调用 |
| php.BinaryOp | BinaryOperation | 二元操作 |
| php.ArrayOffset | ArraySelector | 数组操作 |
| php.Block | BlockStatement | 语句块 |
| php.Assignment | Assignment | 赋值语句 |
3. 核心组件实现
(1) 主分析函数analysis
def analysis(self, nodes, vul_function, back_node, vul_lineo, function_params=None):
for node in nodes:
if isinstance(node, MethodInvocation):
self.anlysis_function(node, back_node, vul_function, function_params, vul_lineo)
elif isinstance(node, StatementExpression):
if isinstance(node.expression, MethodInvocation):
self.anlysis_function(node.expression, back_node, vul_function, function_params, vul_lineo)
# 其他节点类型处理...
(2) 污点回溯parameters_back
def parameters_back(self, param, nodes, function_params=None, node_lineno=-1):
is_co, cp = self.is_controllable(param)
if len(nodes) != 0 and is_co == -1:
node = nodes[len(nodes) - 1]
if isinstance(node, LocalVariableDeclaration):
# 处理变量声明和赋值
# 递归查找变量来源
_is_co, _cp, expr_lineno = self.parameters_back(param, nodes[:-1], function_params, node_lineno)
return is_co, cp, expr_lineno
(3) 敏感函数检测is_controllable
def is_controllable(self, expr):
controlled_params = ['getParameter']
if expr in controlled_params:
return 1, expr
return -1, None
4. 完整工作流程
- 定义sink函数列表(如
executeSql) - 定义修复函数列表(如
null2int) - 解析Java代码生成AST
- 遍历AST查找sink函数调用
- 对每个sink函数的参数进行污点回溯
- 判断参数是否来自用户可控输入(source)
- 判断传递过程中是否经过修复函数处理
- 输出漏洞结果
五、测试与结果
1. 测试代码示例
// _workflowcentertreedata__jsp.java片段
String scope = Util.null2String(request.getParameter("scope"));
String formids = Util.null2String(request.getParameter("formids"));
rs.executeSql("select * from mobileconfig where mc_type=5 and mc_scope=" + scope + "...");
2. 分析结果输出
executeSql in java_src/_workflowcentertreedata__jsp.java:66
[{'code': 1, 'source': 'getParameter', 'source_lineno': 62,
'sink': 'executeSql', 'sink_param:': 'scope', 'sink_lineno': 66}]
注入参数: 62 | String scope = Util.null2String(request.getParameter("scope"))
注入点: 66 | rs.executeSql("select * from mobileconfig where mc_type=5 and mc_scope=" + scope + "...")
3. 总体分析结果
- 结合前台可访问的JSP文件列表
- 过滤后共发现160处注入点
- 手工验证48个有效EXP
六、优缺点分析
优点
- 相比正则匹配,AST分析能获取代码上下文关系,定位更准确
- 操作AST语法树更灵活,便于扩展其他分析手段
- 结构化分析可发现深层漏洞
缺点
- 性能消耗较大
- 目前仅支持单文件分析
- 未覆盖所有Java Token类型
- AST信息维度有限,编写复杂分析逻辑难度大
七、改进方向
- 实现跨文件分析能力
- 完善Java Token覆盖范围
- 结合控制流分析(CFG)提高准确性
- 引入中间表示(IR)使分析更通用
- 结合机器学习技术提升分析能力
八、总结
本文详细介绍了一种基于AST的Java代码静态分析方法,通过构建AST并分析数据流,有效发现了某知名OA系统中的SQL注入漏洞。该方法相比传统正则匹配更具准确性和扩展性,但仍存在性能和分析深度方面的局限。未来可结合更多静态分析技术进一步提升效果。