JAVA代码审计-StudentManager
字数 1301 2025-08-22 12:23:06
Java代码审计实战:StudentManager系统漏洞分析与修复指南
一、系统概述
StudentManager是一个基于Java Web的学生管理系统,使用Servlet+JSP架构,存在多处严重安全漏洞。本指南将详细分析这些漏洞的原理、危害及修复方案。
二、SQL注入漏洞
1. 漏洞位置与原理
系统在多个DAO类中直接拼接SQL语句,未使用预编译:
StudentD.java
public Student checkAccount(String user, String password) throws Exception {
initConnection();
Statement stat = conn.createStatement();
String sql = "select * from student where id = '" + user + "' and password = '" + password + "'";
ResultSet rs = stat.executeQuery(sql);
Student stu = getStudent(rs);
closeConnection();
return stu;
}
TeacherD.java
public Teacher checkAccount(String id, String password) throws Exception {
initConnection();
Statement stat = conn.createStatement();
String sql = "select * from teacher where id = '" + id + "' and password = '" + password + "'";
ResultSet rs = stat.executeQuery(sql);
Teacher tea = getTeacher(rs);
closeConnection();
return tea;
}
2. 漏洞利用方式
登录处注入Payload:
用户名:admin'or 1=1#
密码:任意值
3. 影响范围
-
StudentD类中的方法:
- checkAccount
- findWithId
- findWithName
- deleteStudent
-
TeacherD类中的方法:
- checkAccount
- findWithId
4. 修复方案
使用PreparedStatement进行参数化查询:
public Student checkAccount(String user, String password) throws Exception {
initConnection();
String sql = "select * from student where id = ? and password = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, user);
ps.setString(2, password);
ResultSet rs = ps.executeQuery();
Student stu = getStudent(rs);
closeConnection();
return stu;
}
三、越权访问漏洞
1. 漏洞位置
在main.jsp页面中仅简单获取session信息,未进行权限验证:
student/main.jsp
<% Student student = (Student) session.getAttribute("info");%>
teacher/main.jsp
<% Teacher teacher = (Teacher) session.getAttribute("info");
ArrayList<Student> stus = (ArrayList<Student>) session.getAttribute("onePageStudent");
int sumIndex = (int) session.getAttribute("sumIndex");%>
2. 漏洞危害
攻击者无需登录即可直接访问敏感页面,虽然会报500错误,但仍暴露系统结构信息。
3. 修复方案
添加权限验证过滤器:
public class AuthFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
HttpSession session = req.getSession(false);
if (session == null || session.getAttribute("info") == null) {
res.sendRedirect(req.getContextPath() + "/login.jsp");
return;
}
chain.doFilter(request, response);
}
}
在web.xml中配置过滤器:
<filter>
<filter-name>AuthFilter</filter-name>
<filter-class>com.example.AuthFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthFilter</filter-name>
<url-pattern>/student/*</url-pattern>
<url-pattern>/teacher/*</url-pattern>
</filter-mapping>
四、密码重置漏洞
1. 漏洞位置
update_student_security servlet
String id = request.getParameter("id");
String email = request.getParameter("email");
String password = request.getParameter("password");
try {
studentD.updateStudentSecurity(id, email, password);
2. 漏洞利用
直接访问URL修改任意用户密码:
http://localhost:8081/web/update_student_security?id=20162430646&email=&password=123456
3. 修复方案
- 检查当前用户是否有权修改目标账号
- 强制验证原密码
修改后的代码:
String currentId = ((Student)session.getAttribute("info")).getId();
String id = request.getParameter("id");
if(!currentId.equals(id)) {
throw new SecurityException("无权修改其他用户密码");
}
// 继续执行修改逻辑
五、验证码重用漏洞
1. 漏洞位置
check_register servlet
String randStr = (String) session.getAttribute("randStr");
if (!code.equals(randStr)) {
out.print("<script>alert(\"验证码错误!\");location.href = \"register.jsp\";</script>");
} else {
// 验证通过后未清除验证码
}
2. 漏洞危害
攻击者可重复使用同一验证码进行注册。
3. 修复方案
验证通过后立即清除session中的验证码:
if (!code.equals(randStr)) {
// 错误处理
} else {
session.removeAttribute("randStr"); // 清除验证码
// 继续注册流程
}
六、目录穿越漏洞
1. 漏洞位置
upload_studentImg servlet
String id = rq.getParameter("id");
File smartFile = smartUpload.getFiles().getFile(0);
smartFile.saveAs("/userImg/"+id+".jpeg");
2. 漏洞利用
通过构造恶意id参数实现目录穿越:
id=../../../path/to/sensitive/file
3. 修复方案
- 校验id参数格式
- 规范化路径
// 校验id是否为数字
if(!id.matches("\\d+")) {
throw new IllegalArgumentException("非法ID格式");
}
// 使用Paths规范化路径
Path destination = Paths.get("/userImg").resolve(id + ".jpeg").normalize();
// 确保路径仍在允许的目录内
if(!destination.startsWith("/userImg")) {
throw new SecurityException("非法文件路径");
}
smartFile.saveAs(destination.toString());
七、XSS漏洞
1. 漏洞位置
多处JSP页面直接输出用户输入:
<td><%=stu.getId()%></td>
<input value="<%=stu.getDatabase()%>" name="database">
2. 漏洞危害
攻击者可注入恶意脚本:
"><script>alert(1)</script><"
3. 修复方案
- 使用JSTL的c:out标签
- 或使用HTML编码函数
方案一:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<td><c:out value="${stu.id}"/></td>
方案二:
<td><%=HtmlEncoder.encode(stu.getId())%></td>
其中HtmlEncoder实现:
public class HtmlEncoder {
public static String encode(String input) {
if(input == null) return "";
return input.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace("\"", """)
.replace("'", "'");
}
}
八、安全开发建议
- 输入验证:对所有用户输入进行严格验证
- 参数化查询:始终使用PreparedStatement
- 最小权限原则:数据库连接使用最低必要权限
- 输出编码:所有动态内容输出前进行编码
- 会话管理:合理设置session超时时间
- 错误处理:避免暴露系统敏感信息的错误消息
- 安全框架:考虑使用Spring Security等安全框架
- 定期审计:建立代码审计机制,定期检查安全漏洞
九、总结
StudentManager系统存在SQL注入、越权访问、密码重置、验证码重用、目录穿越和XSS等多类漏洞,主要原因是缺乏对用户输入的有效验证和不安全的编码实践。通过实施参数化查询、输入验证、输出编码和权限控制等措施,可显著提升系统安全性。