使用太阿(Tai-e)进行静态代码安全分析(Servlet容器篇-零)
字数 802 2025-08-04 22:51:28
使用太阿(Tai-e)进行静态代码安全分析(Servlet容器篇)
概述
Tai-e是一个针对Java的静态程序分析框架,支持指针分析、数据流分析、污点分析等多种静态程序分析技术。本教程将详细介绍如何使用Tai-e对Servlet容器(以Tomcat为例)进行静态代码安全分析。
Tomcat Servlet分析原理
入口点配置
Tai-e默认以main方法作为入口点,需要对Java Web程序进行特殊配置:
- Servlet注解扫描:扫描所有带有
@WebServlet注解的类 - 方法识别:识别这些类中的
doGet()、doPost()、doPut()、doDelete()等方法作为入口点 - web.xml配置:也可以扫描web.xml文件获取配置(将在后续文章中介绍)
具体实现步骤
- 获取关键类引用:
final JClass requestFacade = World.get().getClassHierarchy().getClass("org.apache.catalina.connector.RequestFacade");
final JClass responseFacade = World.get().getClassHierarchy().getClass("org.apache.catalina.connector.ResponseFacade");
- 入口点扫描逻辑:
@Override
public void onStart() {
List<JClass> list = solver.getHierarchy().applicationClasses().toList();
for (JClass jClass : list) {
jClass.getAnnotations().forEach(annotation -> {
if (annotation.getType().matches("javax.servlet.annotation.WebServlet")) {
jClass.getDeclaredMethods().forEach(jMethod -> {
if (jMethod.getName().matches("\\b(doGet|doPost|doPut|doDelete)\\b")) {
// 创建模拟对象
Type requestFacadeType = jMethod.getParamType(0);
Type responseFacadeType = jMethod.getParamType(1);
String requestFacadeAlloc = "<" + requestFacadeType.toString() + ">";
String responseFacadeAlloc = "<" + responseFacadeType.toString() + ">";
Obj mockRequest = heapModel.getMockObj(ENTRY_DESC, requestFacadeAlloc, requestFacade.getType(), jMethod);
Obj mockResponse = heapModel.getMockObj(ENTRY_DESC, responseFacadeAlloc, responseFacade.getType(), jMethod);
Obj mockServlet = heapModel.getMockObj(ENTRY_DESC, "<http-controller>", jClass.getType());
// 配置参数提供器
SpecifiedParamProvider paramProvider = new SpecifiedParamProvider.Builder(jMethod)
.addThisObj(mockServlet)
.addParamObj(0, mockRequest)
.addParamObj(1, mockResponse)
.build();
// 添加入口点
solver.addEntryPoint(new EntryPoint(jMethod, paramProvider));
}
});
}
});
}
}
污点分析配置
Source点配置
- 识别Servlet方法:
@Override
public void onNewCSMethod(CSMethod csMethod) {
JMethod method = csMethod.getMethod();
Context context = csMethod.getContext();
boolean isDoMethod = method.getName().matches("\\b(doGet|doPost|doPut|doDelete)\\b");
if (isDoMethod) {
IR ir = method.getIR();
Var param = ir.getParam(0);
SourcePoint sourcePoint = new ParamSourcePoint(method, new IndexRef(IndexRef.Kind.VAR, 0, null));
Obj taint = manager.makeTaint(sourcePoint, param.getType());
solver.addVarPointsTo(context, param, taint);
}
}
- Transfer配置示例(YAML格式):
- { method: "<org.apache.catalina.connector.RequestFacade: java.lang.String getParameter(java.lang.String)>", from: base, to: result }
Sink点配置
检测命令执行的示例配置:
- { vuln: "Remote Code Execution", level: 1, method: "<java.lang.Runtime: java.lang.Process exec(java.lang.String)>", index: 0 }
当前存在的技术挑战
- Map数据处理:在上下文敏感分析中,Tai-e的指针分析/污点分析对Map中的数据识别不够精确
- 污点中断问题:在某些情况下可能导致污点分析中断
- 其他HTTP输入点:如
getParameterValues、getParameterMap、headers、cookies等方法的处理较为复杂
后续研究方向
- 完善其他HTTP输入点的transfer配置
- 解决Map数据处理的精确性问题
- 优化上下文敏感分析中的污点传播
- 支持更多Servlet容器的适配
参考资源
通过以上配置和分析方法,可以初步建立对Servlet容器的静态代码安全分析能力。后续文章将继续深入探讨更复杂场景的分析方法和优化策略。