【Java 代码审计入门-03】XSS 漏洞原理与实际案例介绍
字数 1035 2025-08-25 22:58:46
Java代码审计入门:XSS漏洞原理与实际案例详解
0x00 前言
本系列文章旨在为具备Java基本语法基础的学习者提供系统的Java代码审计教程。本文是第三篇,重点讲解XSS漏洞的原理与实际案例分析。
0x01 XSS漏洞基础
XSS漏洞定义
XSS(跨站脚本攻击)是通过对网页插入可执行代码且成功被浏览器执行,达到攻击目的的安全漏洞。XSS攻击的危害包括但不限于:
- 获取用户Cookies
- 获取用户联系人列表
- 屏幕截取
- 会话劫持等
XSS类型分类
- 反射型XSS:非持久化,需要欺骗用户点击恶意链接
- 存储型XSS:持久化,恶意代码存储在服务器端
- DOM型XSS:通过修改DOM环境在客户端直接触发
0x02 反射型XSS案例
漏洞代码示例
public void Message(HttpServletRequest req, HttpServletResponse resp) {
String message = req.getParameter("msg");
try {
resp.getWriter().print(message); // 直接输出用户输入
} catch (IOException e) {
e.printStackTrace();
}
}
攻击原理
- 攻击者构造恶意URL:
http://example.com/page?msg=<script>alert('xss')</script> - 服务器直接返回未过滤的用户输入
- 浏览器执行恶意脚本
漏洞验证
输入<script>alert('xss')</script>,浏览器会弹出警告框。
0x03 存储型XSS案例
漏洞代码分析
- 数据存储部分:
public void StoreXss(HttpServletRequest req, HttpServletResponse resp) {
String name = req.getParameter("name");
String mail = req.getParameter("mail");
String message = req.getParameter("message");
if(!name.equals(null) && !mail.equals(null) && !message.equals(null)){
MessageInfoService msginfo = new MessageInfoServiceImpl();
msginfo.MessageInfoStoreService(name, mail, message); // 存储未过滤的用户输入
}
}
- 数据展示部分:
<% List<MessageInfo> msginfo = (ArrayList<MessageInfo>)request.getAttribute("msg");
for(MessageInfo m : msginfo){ %>
<td class="hvttd"><%= m.getMessage() %></td> <!-- 直接输出数据库内容 -->
<% } %>
攻击流程
- 攻击者提交包含恶意脚本的表单数据
- 数据被存储到数据库
- 其他用户访问页面时,恶意脚本从数据库取出并执行
0x04 XSS防御方案
1. 全局过滤器方案
web.xml配置:
<filter>
<filter-name>XssSafe</filter-name>
<filter-class>XssFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>XssSafe</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
过滤器实现:
public class XssFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest)request), response);
}
}
XSS过滤逻辑:
private String xssClean(String value) {
if (value != null) {
// 过滤script标签
value = value.replaceAll("(?i)<script>(.*?)</script>", "");
// 过滤src属性
value = value.replaceAll("src[\r\n]*=[\r\n]*\\'(.*?)\\'", "");
// 过滤javascript:表达式
value = value.replaceAll("javascript:", "");
// 过滤事件处理函数
value = value.replaceAll("onload(.*?)=", "");
}
return value;
}
2. 使用xssProtect工具
protected String protectedAgainstXSS(String html) {
StringReader reader = new StringReader(html);
StringWriter writer = new StringWriter();
try {
HTMLParser.process(reader, writer, new XSSFilter(), true);
return writer.toString();
} catch (HandlingException e) {
return "";
}
}
3. 使用Apache Commons Lang
// HTML转义
String safeOutput = StringEscapeUtils.escapeHtml(input);
// JavaScript转义
String safeJS = StringEscapeUtils.escapeJavaScript(input);
0x05 实际案例:CVE-2018-19178分析
漏洞描述
JEESNS 1.3中存在XSS漏洞,攻击者可通过<embed>标签绕过过滤插入恶意代码。
漏洞代码
private String cleanXSS(String value) {
// 过滤style和script标签
value = value.replaceAll("(?i)<style>", "<style>")
.replaceAll("(?i)</style>", "</style>");
value = value.replaceAll("(?i)<script>", "<script>")
.replaceAll("(?i)</script>", "</script>");
// 过滤事件处理函数
String[] eventKeywords = {"onmouseover", "onclick", "onload", "alert"};
for (String keyword : eventKeywords) {
value = value.replaceAll(keyword, "_" + keyword);
}
return value;
}
绕过方式
- 使用
<embed>标签:
<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==">
- 使用SVG标签:
<svg/onLoad=confirm(1)>
修复建议
- 采用更全面的标签过滤策略
- 使用白名单而非黑名单方式
- 结合HTML实体编码
0x06 总结
XSS漏洞防御要点:
- 输入验证:对用户输入进行严格验证
- 输出编码:在输出到页面时进行适当的编码
- 内容安全策略(CSP):使用HTTP头限制脚本执行
- HttpOnly标志:为Cookie设置HttpOnly属性
通过本教程,您应该已经掌握了Java Web应用中XSS漏洞的原理、检测方法和防御策略。在实际审计过程中,需要特别注意所有用户输入点和数据输出点,确保数据流动过程中有适当的过滤和编码处理。