java代码审计
字数 1608 2025-08-20 18:18:23
Java代码审计全面指南
1. Java编译与反编译
1.1 Java编译过程
- Java源代码 → (编译) → Java字节码 → (解释器) → 机器码
- 字节码优势:高效、可移植性高
1.2 反编译工具
- Fernflower
- JAD
- JD-GUI
- IDEA自带插件
2. Servlet与JSP
2.1 Servlet
- 处理复杂服务端业务逻辑
- 含有HttpServlet类,可进行重写
- Servlet 3.0后使用注解方式描述Servlet
- 3.0前必须在web.xml中配置
2.2 JSP
- 会被编译成Java类文件
- 是特殊的Servlet
- 在Tomcat中Jasper编译后生成
_jsp.java和_jsp.class文件
3. 全局控制器与过滤器
3.1 全局控制器搜索
find ~/cms/ -type f -name "*.class" | xargs grep -E "Controller|@RestController|RepositoryRestController"
find ~/cms/ -type f -name "*.class" | xargs grep -E "RequestMapping|GetMapping|PostMapping|PutMapping|DeleteMapping|PatchMapping|RepositoryRestResource"
3.2 全局过滤器
- 审计时先检查是否存在全局过滤器
- 常见写法:
<filter>
<filter-name>SecurityFilter</filter-name>
<filter-class>com.example.SecurityFilter</filter-class>
<init-param>
<param-name>sqlInjIgnoreUrls</param-name>
<param-value>.*/api/.*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
4. 常见漏洞类型
4.1 代码实现安全问题
- 任意文件操作(上传/下载/遍历/删除/重命名)
- SQL注入
- XXE(XML实体注入)
- 表达式执行(SpEL/OGNL/MVEL2/EL)
- 系统命令执行(ProcessBuilder)
- 反序列化攻击
- Java反射攻击
- SSRF
- XSS
4.2 业务安全问题
- 认证/授权缺陷
- 验证码缺陷
- 密码找回逻辑问题
- 支付逻辑缺陷
- ORM框架误用
- CSRF漏洞
- 前端信任问题
- 敏感信息泄露
- 条件竞争
- 请求频率限制缺失
- 弱加密算法
5. SQL注入审计
5.1 直接拼接风险
String sql = "SELECT * FROM users WHERE username = '" + request.getParameter("name") + "'";
5.2 预编译使用错误
// 错误示例:占位符但未使用set方法
PreparedStatement st = conn.prepareStatement("SELECT * FROM users WHERE username = ?");
st.setString(1, request.getParameter("name")); // 必须使用set方法
5.3 MyBatis框架审计
- 搜索
$符号 #{}安全,${}存在风险- 模糊查询风险:
like '%${xxx}%' - 无需引号处风险:
in(${xxx})或order by ${xxx}
6. 表达式注入(SpEL/OGNL)
6.1 SpEL注入示例
String el = "T(java.lang.Runtime).getRuntime().exec(\"open /tmp\")";
ExpressionParser PARSER = new SpelExpressionParser();
Expression exp = PARSER.parseExpression(el);
exp.getValue(); // 执行命令
6.2 审计要点
- 检查
SpelExpressionParser使用处 - 检查表达式是否用户可控
7. XSS漏洞
7.1 示例代码
@RequestMapping("/xss")
public ModelAndView xss(HttpServletRequest request) {
String name = request.getParameter("name");
ModelAndView mav = new ModelAndView("page");
mav.getModel().put("uname", name); // 未转义直接输出
return mav;
}
8. SSRF漏洞
8.1 风险代码
String url = request.getParameter("picurl");
URL pic = new URL(url);
HttpURLConnection con = (HttpURLConnection) pic.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
8.2 审计要点
- 检查支持的协议:
file/ftp/http/https等 - 检查相关函数:
HttpClient.executeHttpURLConnection.connectURL.openStream
9. XXE漏洞
9.1 风险代码
SAXReader sax = new SAXReader();
Document document = sax.read(new ByteArrayInputStream(xmldata.getBytes()));
9.2 修复方案
saxReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
saxReader.setFeature("http://xml.org/sax/features/external-general-entities", false);
saxReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
10. 反序列化漏洞
10.1 风险点
InputStream in = request.getInputStream();
ObjectInputStream ois = new ObjectInputStream(in);
ois.readObject(); // 反序列化用户可控数据
10.2 审计要点
检查以下方法:
ObjectInputStream.readObjectXMLDecoder.readObjectYaml.loadXStream.fromXMLObjectMapper.readValueJSON.parseObject
10.3 修复方案
- 白名单校验
- 使用
ValidatingObjectInputStream
ValidatingObjectInputStream ois = new ValidatingObjectInputStream(bais);
ois.accept(SafeClass.class); // 只允许反序列化指定类
11. 文件操作漏洞
11.1 路径遍历
File file = new File(request.getParameter("path"));
// 应使用getCanonicalPath()而非getAbsolutePath()
11.2 ZIP文件提取风险
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
FileOutputStream fos = new FileOutputStream(entry.getName()); // 未校验路径
// ...
}
11.3 修复方案
File f = new File(intendedDir, entryName);
String canonicalPath = f.getCanonicalPath();
if (!canonicalPath.startsWith(intendedDirCanonicalPath)) {
throw new IllegalStateException("非法路径");
}
12. 第三方组件安全
12.1 常见风险组件
- Struts2
- Fastjson
- 不安全的编辑控件
12.2 审计方法
- 检查组件版本
- 检查已知漏洞
13. 其他重要漏洞
13.1 URL重定向
String site = request.getParameter("url");
response.sendRedirect(site); // 未校验URL
13.2 Autobinding
@RequestMapping("/reset")
public String resetHandler(@ModelAttribute User user) {
// 可能绑定不需要的字段
}
13.3 WebService
- 检查
?wsdl接口 - 使用BurpSuite WSDL插件测试
14. 审计工具与方法
14.1 代码搜索技巧
- 全局搜索关键字符串:
sql/xml/Runtime.exec等 - 使用IDE的全局搜索功能
14.2 重点关注点
- 用户输入点
- 外部数据解析
- 敏感操作
- 权限校验
15. 总结
Java代码审计需要全面考虑代码实现和业务逻辑两方面的安全问题,重点关注用户输入处理、数据解析、权限控制等关键环节,结合框架特性和业务场景进行深入分析。