一、跨站脚本攻击 (XSS) 基础概念
1.1 XSS 攻击的定义
跨站脚本攻击 (Cross-Site Scripting,简称 XSS) 是一种常见的 Web 安全漏洞,攻击者通过在网页中注入恶意脚本 (通常是 JavaScript),当用户浏览该网页时,恶意脚本会在用户浏览器中执行,从而窃取用户数据、会话信息或实施其他恶意行为。
1.2 XSS 攻击的三大类型
- 反射型 XSS (非持久化):攻击代码嵌入在 URL 或表单中,服务器直接将攻击代码返回给浏览器执行,常见于搜索框、URL 参数等场景
- 存储型 XSS (持久化):攻击代码被存储在服务器数据库中 (如评论、留言板),用户访问页面时自动加载执行
- DOM 型 XSS:攻击代码通过修改页面 DOM 结构执行,漏洞存在于前端 JavaScript 代码中
1.3 XSS 攻击的危害
- 窃取用户 Cookie 和会话令牌,实现会话劫持
- 篡改网页内容,展示恶意广告或钓鱼信息
- 监听用户键盘输入,窃取账号密码等敏感信息
- 利用浏览器漏洞执行远程代码,控制用户设备
二、Java Web 应用中的 XSS 漏洞代码示例
2.1 存在反射型 XSS 漏洞的 Java Servlet 代码
java
@WebServlet("/vulnerable")
public class VulnerableServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 漏洞点:直接获取参数并输出,未进行任何安全处理
String name = request.getParameter("name");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE html>");
out.println("<html><head><title>漏洞页面</title></head>");
out.println("<body>");
out.println("<h1>欢迎访问," + name + "!</h1>");
// 恶意用户输入:<script>alert('XSS攻击')</script>
// 浏览器会执行alert代码
out.println("</body></html>");
}
}
2.2 存在存储型 XSS 漏洞的评论功能代码
java
@WebServlet("/postComment")
public class CommentServlet extends HttpServlet {
private CommentDAO commentDAO = new CommentDAO(); // 假设存在评论数据访问对象
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
String comment = request.getParameter("comment");
// 漏洞点:未对评论内容进行安全过滤直接存入数据库
Comment newComment = new Comment();
newComment.setUsername(username);
newComment.setContent(comment);
commentDAO.saveComment(newComment);
response.sendRedirect("comments.jsp");
}
}
// 评论展示页面代码片段
<%
for (Comment comment : commentService.getAllComments()) {
%>
<div class="comment">
<div class="user"><%= comment.getUsername() %></div>
<div class="content"><%= comment.getContent() %></div>
</div>
<%
}
%>
2.3 DOM 型 XSS 漏洞的前端代码示例
javascript
// 假设在Java Web应用中包含此前端脚本
function updatePage() {
// 漏洞点:直接使用URL参数并修改DOM
const name = window.location.search.split('name=')[1];
document.getElementById("greeting").innerHTML = "欢迎, " + name;
}
三、Java Web 应用中 XSS 攻击的防御方案
3.1 输出编码防御反射型 XSS
java
@WebServlet("/safeservlet")
public class SafeServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("name");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
// 使用Java EE的Encoder进行HTML编码
out.println("<!DOCTYPE html>");
out.println("<html><head><title>安全页面</title></head>");
out.println("<body>");
out.println("<h1>欢迎访问,");
// 关键防护:对用户输入进行HTML编码
out.println(Encoder.encode(name, "HTML"));
out.println("!</h1>");
out.println("</body></html>");
}
}
3.2 输入验证与输出编码结合防御存储型 XSS
java
@WebServlet("/safepostcomment")
public class SafeCommentServlet extends HttpServlet {
private CommentDAO commentDAO = new CommentDAO();
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
String comment = request.getParameter("comment");
// 输入验证:过滤危险字符
username = sanitizeInput(username);
comment = sanitizeInput(comment);
// 双重防护:同时进行输出编码
Comment newComment = new Comment();
newComment.setUsername(Encoder.encode(username, "HTML"));
newComment.setContent(Encoder.encode(comment, "HTML"));
commentDAO.saveComment(newComment);
response.sendRedirect("safeprofile.jsp");
}
// 自定义输入净化方法
private String sanitizeInput(String input) {
if (input == null) return "";
// 使用正则表达式过滤恶意脚本标签
return input.replaceAll("<script.*?>.*?</script>", "");
// 实际项目中建议使用专业库如OWASP ESAPI
}
}
3.3 使用 HttpOnly Cookie 防止会话劫持
java
// 在Servlet中设置HttpOnly Cookie
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 创建Cookie
Cookie sessionCookie = new Cookie("JSESSIONID", "123456789");
// 关键防护:设置HttpOnly属性
sessionCookie.setHttpOnly(true);
// 建议同时设置Secure属性(HTTPS环境)
sessionCookie.setSecure(request.isSecure());
response.addCookie(sessionCookie);
// 其他业务逻辑...
}
3.4 实现内容安全策略 (CSP)
java
@WebServlet("/cspenabled")
public class CspServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置CSP头部,限制可执行脚本的来源
response.setHeader("Content-Security-Policy",
"default-src 'self'; " +
"script-src 'self' https://trusted-scripts.com; " +
"style-src 'self' https://trusted-styles.com; " +
"img-src *; " + // 允许所有图片来源
"object-src 'none'; " + // 禁止Flash等插件
"base-uri 'self'; " + // 限制base标签
"frame-ancestors 'self'" // 限制iframe嵌入
);
// 其他响应内容...
}
}
3.5 使用 Spring Security 框架的 XSS 防护
java
// Spring Security配置类
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
// 启用Spring Security的XSS防护
.xssProtection()
.block(false) // 检测到XSS时不阻止页面加载
.and()
.headers()
.contentSecurityPolicy("default-src 'self'; script-src 'self'");
}
}
四、企业级 XSS 防御最佳实践
4.1 分层防御体系建设
防御层 | 具体措施 |
---|---|
前端防御 | - 表单输入实时验证 - 敏感区域 DOM 操作安全限制 - 前端框架安全配置 (Vue/XSS, React/JSX 转义) |
应用层防御 | - 全面输入验证与输出编码 - 采用安全编码规范 - 引入专业安全库 (OWASP ESAPI) |
服务层防御 | - 部署 WAF (Web 应用防火墙) - 实现请求频率限制 - 异常输入日志记录与分析 |
数据层防御 | - 敏感数据加密存储 - 建立安全的数据访问接口 - 实施最小权限原则 |
4.2 安全编码规范
- 永远不要信任用户输入,对所有用户输入进行验证和净化
- 遵循 "输出编码" 原则,根据输出上下文选择合适的编码方式
- HTML 上下文:使用 HTML 编码 (<> & 等)
- JavaScript 上下文:使用 JS 编码 (\u003C \u003E 等)
- URL 参数:使用 URL 编码 (%3C %3E 等)
- 避免使用危险 API:
- 禁用
eval()
、with()
等危险 JavaScript 函数 - 避免使用
Document.write()
直接输出用户内容 - 谨慎使用
innerHTML
,优先使用textContent
- 禁用
4.3 安全测试与漏洞管理
- 定期进行静态代码分析:使用 FindBugs、SonarQube 等工具扫描 XSS 漏洞
- 实施动态安全测试:通过 OWASP ZAP、Burp Suite 等工具进行自动化渗透测试
- 建立漏洞响应流程:
- 漏洞发现与确认
- 风险评估与优先级划分
- 补丁开发与测试
- 漏洞修复与验证
- 根本原因分析与预防措施
五、总结与趋势展望
XSS 攻击作为 Web 应用最古老的安全漏洞之一,至今仍在 OWASP TOP 10 漏洞榜单中占据重要位置。随着单页应用 (SPA) 和前端框架的普及,DOM 型 XSS 的防御变得更加复杂,需要前后端协同防御。
在 Java 生态中,开发者应充分利用 Java EE 提供的安全 API、Spring Security 框架的防护能力,结合 OWASP 等安全组织提供的最佳实践,构建多层次的 XSS 防御体系。同时,安全编码意识的培养和持续的安全培训,是企业降低 XSS 风险的基础保障。
未来,随着内容安全策略 (CSP) 的广泛应用和浏览器安全机制的不断增强,XSS 攻击的难度将逐渐增加,但攻击者也会不断寻找新的攻击向量,安全防护工作需要持续迭代升级。