前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

一、XSS

跨站脚本攻击(Cross-Site Scripting,简称 XSS)是一种常见的 Web 安全漏洞,攻击者通过向网页中注入恶意脚本,使得其他用户在浏览该页面时执行这些脚本,从而实现对用户的攻击。XSS 攻击主要发生在客户端(通常是浏览器),因此也被称为“客户端脚本攻击”。

1、XSS 基本原理

XSS 攻击的核心在于:用户输入的数据未经充分过滤或转义,就被直接嵌入到网页中,从而被浏览器当作可执行的脚本运行

例如,一个网站的搜索框如果直接将用户输入的内容显示在页面上,攻击者就可以输入类似如下的内容:

<script>alert('XSS')</script>

如果网站没有对用户输入进行过滤或转义,这段脚本就会在其他用户的浏览器中执行,从而导致攻击。

2、XSS 的三种主要类型

1)反射型 XSSReflected XSS

  • 定义:恶意脚本作为请求的一部分被发送到服务器,服务器未经过滤或转义就将脚本反射回浏览器执行。
  • 攻击方式:通常通过诱导用户点击一个包含恶意代码的链接(如邮件、即时消息、社交平台等)。
  • 特点:攻击不会存储在服务器中,是一次性的。

示例 URL

http://example.com/search?q=<script>alert('XSS')</script>

2)存储型 XSSStored XSS

  • 定义:恶意脚本被提交并存储在服务器(如数据库、评论、用户资料等),当其他用户访问该页面时,脚本被加载执行。
  • 攻击方式:攻击者将恶意脚本提交到网站中(如论坛、留言板、博客评论等),一旦其他用户访问该页面就会触发攻击。
  • 特点:攻击具有持久性,危害范围广。

示例场景: 攻击者在论坛中发表一个包含 <script> 标签的评论,所有查看该评论的用户浏览器都会执行该脚本。

3)DOMXSSDOM-based XSS

  • 定义:攻击不依赖于服务器响应,而是由于前端 JavaScript 直接操作用户输入的数据,导致恶意脚本被执行。
  • 攻击方式:攻击者通过修改页面的 DOM(文档对象模型)来触发脚本执行。
  • 特点:攻击完全发生在客户端,服务器不会处理恶意脚本。

示例

document.write(location.hash);

如果用户访问的 URL 是:

http://example.com/#<script>alert('XSS')</script>

那么 location.hash 的值将被直接写入页面,导致脚本执行。

二、XSS 攻击的危害

  1. 窃取用户敏感信息:攻击者可以通过脚本读取用户的 Cookie 并发送到自己的服务器,从而盗取用户身份。
  2. 钓鱼攻击:插入伪造的登录框、表单,诱导用户输入账号密码。
  3. 会话劫持Session Hijacking):利用获取的 CookieSession 信息冒充用户进行操作。
  4. 网页篡改:修改页面内容,误导用户或破坏用户体验。
  5. 蠕虫传播:利用 XSS 编写自动传播的脚本,感染更多用户。
  6. 拒绝服务攻击DoS):通过脚本不断刷新页面、发送请求,造成服务器压力。

三、XSS 防御方法

防御方法 技术实现 工具/库 适用场景
输入过滤 正则表达式、Bean Validation Hibernate Validator 用户输入校验
输出转义 上下文相关转义 OWASP Java Encoder 页面显示用户输入
模板引擎 自动转义机制 Thymeleaf、Freemarker 页面渲染
Cookie 安全 设置 HttpOnly、Secure 原生 Cookie API 会话管理

1、输入过滤

  • 目标:防止用户输入非法字符,从源头上减少 XSS 攻击的可能性。

  • 实现方式:

    • 使用正则表达式对输入内容进行校验。

    • 使用 javax.validation 注解对字段进行格式限制。

  • 注意

    • 不要使用黑名单,建议使用白名单。

    • 对特殊字段(如用户名、邮箱、评论)进行针对性校验。

    • 可结合 Hibernate Validator 实现自动校验。

<dependency>
    <groupId>org.owasp.encoder</groupId>
    <artifactId>encoder</artifactId>
    <version>2.6.1</version>
</dependency>
package com.example.security;

import org.owasp.encoder.Encode;

public class InputSanitizer {

    /**
     * 使用正则表达式检查输入是否仅包含字母、数字、空格以及一些常见标点符号。
     */
    public static boolean isValidInput(String input) {
        if (input == null || input.trim().isEmpty()) {
            return false;
        }
        // 允许的字符集:字母、数字、空格及.,!?
        return input.matches("[a-zA-Z0-9\\s.,!?]*");
    }

    /**
     * 对输入字符串进行 HTML 转义,防止 XSS 攻击。
     */
    public static String sanitizeForHtml(String input) {
        if (input == null) {
            return "";
        }
        return Encode.forHtml(input);
    }

    /**
     * 对输入字符串进行 JavaScript 转义。
     */
    public static String sanitizeForJavaScript(String input) {
        if (input == null) {
            return "";
        }
        return Encode.forJavaScript(input);
    }

    /**
     * 对 URL 参数进行编码。
     // 如果用户输入 <script>alert('xss')</script> 作为查询参数,经过 sanitizeForUrl 方法处理后,它将变成 %3Cscript%3Ealert%28%27xss%27%29%3C%2Fscript%3E,这是一个安全的 URL 编码形式,不会触发任何脚本执行。
     */
    public static String sanitizeForUrl(String input) {
        if (input == null) {
            return "";
        }
        return Encode.forUriComponent(input);
    }
}

2、输出转义

  • 目标:在将用户输入插入到 HTML 页面前进行转义,防止脚本执行。

  • 实现方式:使用 OWASP Java Encoder 库进行上下文相关的转义。

  • 使用场景:

    • 显示用户评论、昵称、文章内容等字段前调用 sanitizeHtml()

    • JavaScript 动态赋值时调用 sanitizeJs()

    • URL 参数拼接前调用 sanitizeUrl()

<dependency>
    <groupId>org.owasp.encoder</groupId>
    <artifactId>encoder</artifactId>
    <version>2.6.1</version>
</dependency>
import org.owasp.encoder.Encode;

public class XssUtils {
  
    //显示用户评论、昵称、文章内容等字段前调用 `sanitizeHtml()`
    public static String sanitizeHtml(String input) {
        return Encode.forHtml(input);
    }

   // `JavaScript` 动态赋值时调用 `sanitizeJs()`
    public static String sanitizeJs(String input) {
        return Encode.forJavaScript(input);
    }

   //`URL` 参数拼接前调用 `sanitizeUrl()`
    public static String sanitizeUrl(String input) {
        return Encode.forUriComponent(input, StandardCharsets.UTF_8, true);
    }
}

3、使用模板引擎自动转义(推荐)

  • 目标:通过模板引擎自动完成输出转义,减少手动处理错误。

  • 实现方式:

  • 使用 ThymeleafSpring Boot 默认模板引擎)

  • Thymeleaf 默认对 ${} 内容进行 HTML转义

  • 优势:

    • 自动处理 XSS,无需手动调用转义函数

    • 避免开发人员遗漏转义步骤

    • Spring Boot 集成良好

<!-- 自动转义,安全 -->
<p th:text="${userInput}">内容</p>

<!-- 禁用转义(慎用) -->
<p th:utext="${userInput}">内容</p>
  • 目标:防止 XSS 脚本窃取用户 Cookie,避免会话劫持。

  • 实现方式:在 Java Web 应用中设置 Cookie 属性为 HttpOnlySecure

  • 注意事项:

  • 所有敏感 Cookie 都应设置 HttpOnly

  • Secure 表示只在 HTTPS 下传输,防止中间人攻击

Cookie cookie = new Cookie("JSESSIONID", "123456");
cookie.setHttpOnly(true);   // 防止 JS 读取 Cookie
cookie.setSecure(true);     // 仅通过 HTTPS 传输
cookie.setPath("/");
response.addCookie(cookie);

ContactAuthor