java代码审计之smbms
字数 1477 2025-08-24 20:49:22
Java代码审计实战:SMBMS项目漏洞分析与修复指南
1. 项目概述
SMBMS是一个Java Web项目,采用Servlet+JSP架构,主要用于学习Java和代码审计。项目虽然使用了SQL预编译防止SQL注入,但仍存在多处安全漏洞,特别是XSS和逻辑缺陷。
2. 反射型XSS漏洞分析
2.1 Referer头XSS漏洞
漏洞位置: head.jsp文件
漏洞代码:
<%= request.getHeader("Referer") %>
漏洞分析:
- 直接输出HTTP Referer头内容到页面,未做任何过滤或编码
- 攻击者可构造恶意Referer头触发XSS
复现步骤:
- 构造恶意请求,在Referer头中包含XSS payload:
Referer: "><ScRiPt>alert(1)</sCrIpT> - 访问任何包含
head.jsp的页面
2.2 账单查询XSS漏洞
漏洞位置: BillServlet和billlist.jsp
漏洞代码:
String queryProductName = request.getParameter("queryProductName");
漏洞分析:
- 直接获取
queryProductName参数并输出到页面 - 未进行输出编码或过滤
复现URL:
http://localhost:8080/jsp/bill.do?method=query&queryProductName=%22%3E%3CScRiPt%3Ealert%281%29%3C%2FsCrIpT%3E&queryProviderId=0&queryIsPayment=0
2.3 供应商查询XSS漏洞
漏洞位置: ProviderServlet和providerlist.jsp
漏洞参数:
queryProCodequeryProName
复现URL:
http://localhost:8080/jsp/provider.do?method=query&queryProCode=%22%3E%3CScRiPt%3Ealert%281%29%3C%2FsCrIpT%3E&queryProName=
2.4 用户查询XSS漏洞
漏洞位置: UserServlet和userlist.jsp
漏洞参数:
queryname
复现URL:
http://localhost:8080/jsp/user.do?method=query&queryname=%22%3E%3CScRiPt%3Ealert%281%29%3C%2FsCrIpT%3E&queryUserRole=0&pageIndex=1
3. 存储型XSS漏洞分析
3.1 常规存储型XSS
漏洞成因:
- 从
getParameter()获取用户输入 - 直接存入数据库
- 从数据库读取后直接输出到页面
审计方法:
- 全局搜索数据库操作关键词(
insert,save,update) - 跟踪参数传递路径,确认是否有过滤
3.2 长度限制绕过技巧
特殊场景:
- 数据库字段长度限制(如20字符)
- 常规XSS payload过长无法使用
绕过方案:
使用特殊字符缩短payload长度:
<script/src=//⑭⑭.₨₨>
- 总长度: 18字符
- 特殊字符说明:
⑭⑭: 特殊数字符号,计为1字符₨₨: 印度卢比符号,计为1字符
4. 任意密码修改漏洞
漏洞位置: 密码修改功能
漏洞分析:
- 前端JS验证旧密码、新密码和确认密码
- 后端仅依赖前端验证结果
- 攻击者可绕过前端验证直接构造请求
漏洞复现:
- 直接发送修改密码请求,不提供旧密码:
POST /jsp/user.do?method=savepwd HTTP/1.1 Content-Type: application/x-www-form-urlencoded newpassword=attacker123&rnewpassword=attacker123 - 密码修改成功
5. 漏洞修复方案
5.1 XSS漏洞修复
方案1: 输出编码
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<c:out value="${param.queryProductName}" />
方案2: 使用ESAPI编码
import org.owasp.esapi.ESAPI;
String safeOutput = ESAPI.encoder().encodeForHTML(input);
方案3: 输入过滤
import org.apache.commons.lang3.StringEscapeUtils;
String safeInput = StringEscapeUtils.escapeHtml4(input);
5.2 密码修改漏洞修复
修复方案:
- 后端必须验证旧密码
- 增加CSRF防护
- 强制密码复杂度要求
示例代码:
// 验证旧密码
String oldPassword = request.getParameter("oldpassword");
String newPassword = request.getParameter("newpassword");
String rnewPassword = request.getParameter("rnewpassword");
User user = userService.getUserById(currentUserId);
if(!user.getUserPassword().equals(oldPassword)) {
// 返回错误
return;
}
// 验证新密码复杂度
if(!isPasswordStrong(newPassword)) {
// 返回错误
return;
}
// 更新密码
userService.updatePassword(currentUserId, newPassword);
6. 代码审计方法论总结
-
入口点识别:
- 搜索
getParameter()、getHeader()等方法 - 检查Servlet映射(
@WebServlet或web.xml)
- 搜索
-
数据流跟踪:
- 从输入点到输出点/数据库操作点
- 确认中间是否有过滤或编码
-
特殊场景检查:
- 数据库字段类型和长度限制
- 前端验证与后端验证一致性
-
修复验证:
- 确认修复后漏洞是否真正消除
- 避免引入新的安全问题
7. 附录:常用审计工具
-
静态分析工具:
- FindBugs/SpotBugs
- SonarQube
- Fortify SCA
-
动态测试工具:
- Burp Suite
- OWASP ZAP
-
辅助工具:
- JD-GUI (反编译)
- ByteCode Viewer
通过本案例学习,可以掌握基本的Java Web应用安全审计方法和常见漏洞修复技巧。