java代码审计之xss
字数 1361 2025-08-09 13:33:52
Java代码审计之XSS漏洞分析与修复
反射型XSS漏洞分析
漏洞发现
- 漏洞URL路径:
/front/showcoulist - 漏洞参数:
queryCourse.courseName - 漏洞表现:反射型XSS
漏洞定位流程
- 根据URL路径定位到
CourseController.java - 发现搜索课程列表以集合形式传递数据
- 向上追踪到
courseService中定义的查询课程接口 - 在接口实现类中找到具体实现方法(49行)
- 最终定位到
CourseMapper中进行数据库查询
漏洞代码分析
// CourseMapper中的SQL查询语句
SELECT * FROM course WHERE courseName LIKE '%${queryCourse.courseName}%'
${queryCourse.courseName}是EL表达式,代表queryCourse实体类下的courseName值- 查询结果直接返回到前台页面,未做任何过滤处理
存储型XSS漏洞分析
漏洞发现
- 漏洞URL路径:
/admin/article/updatearticle - 漏洞参数:
article.title - 漏洞表现:存储型XSS
漏洞定位流程
- 根据URL路径定位到
AdminArticleController.java - 控制器中新建对象并获取参数
- 参数直接用于修改数据库数据
- 数据存储后返回到原页面
漏洞代码分析
// 控制层代码
Article article = new Article();
// 获取参数并设置到article对象
article.setTitle(request.getParameter("title"));
// 调用服务层方法更新数据
articleService.updateArticle(article);
${article.title}是EL表达式,直接输出到前台页面- 整个存储过程没有任何过滤处理
数据流分析
AdminArticleController.java调用服务层方法ArticleService.java和ArticleDao.java定义修改方法ArticleDaoImpl.java实现接口方法ArticleMapper.xml执行更新SQL语句- 整个过程直接操作
Article实体类字段,无任何过滤
漏洞修复方案
反射型XSS修复建议
- 在
CourseController中对输入参数进行HTML编码 - 使用OWASP ESAPI或Spring HTMLUtils进行编码
- 示例代码:
String safeCourseName = HtmlUtils.htmlEscape(queryCourse.getCourseName());
queryCourse.setCourseName(safeCourseName);
存储型XSS修复建议
- 在
AdminArticleController中对输入进行净化 - 使用白名单过滤HTML标签
- 示例代码:
import org.apache.commons.text.StringEscapeUtils;
// ...
String safeTitle = StringEscapeUtils.escapeHtml4(article.getTitle());
article.setTitle(safeTitle);
通用修复措施
- 在视图层使用JSTL的
<c:out>标签自动转义 - 配置Content Security Policy (CSP)头
- 对所有用户输入实施严格的输入验证
- 对输出到页面的数据实施编码
审计要点总结
- EL表达式使用检查:查找
${}表达式直接输出用户输入的情况 - 数据流追踪:从控制器→服务层→DAO层→SQL语句完整追踪
- 输入输出点:重点关注用户输入点和页面输出点
- 过滤缺失检查:检查是否有输入验证或输出编码环节
- ORM框架使用:检查是否直接使用实体类字段而不经处理
参考资源
- 修复后的源码可查看官网:https://www.inxedu.com/
- OWASP XSS防护指南:https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
- ESAPI文档:https://owasp.org/www-project-enterprise-security-api/