XSS

反射型XSS

下面是一个简单的 Spring Boot Web 应用,其中包含了一个含有 XSS 漏洞的请求处理器。

在这个应用中,我们通过 GET 请求方式访问 /xss 接口,输入参数会被直接输出到 HTML 页面中。如果输入参数中包含了恶意脚本,那么这些脚本就会被执行,从而导致 XSS 攻击。

package com.example.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class XssController {
    @GetMapping("/xss")
    public String XssTest(@RequestParam String name) {
        return "<h1>Hello, " + name + "!</h1>";
    }
}

触发漏洞结果

image-20230307163354591

存储型XSS

数据库插入一条XSS记录

image-20230307175101983

Thymeleaf 是一款常用的模板引擎,它可以将 HTML 页面与 Java 代码进行结合,实现动态渲染 HTML 页面的功能。在 Spring Boot 项目中使用 Thymeleaf,需要在项目的 pom.xml 文件中添加以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

该依赖会自动引入 Thymeleaf 模板引擎及其依赖的其他库,因此不需要额外添加其他依赖。在添加了该依赖后,Spring Boot 会自动配置 Thymeleaf 模板引擎,无需手动进行配置。

image-20230307175514851

dom xss

package com.example.controller;

import com.example.model.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import java.util.List;

@RestController
public class XssController {

    @GetMapping("/xss/index")
    public ModelAndView index() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");

        return modelAndView;
    }

    @PostMapping("/xss/dom")
    public ModelAndView xss(@RequestParam("name") String name) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("name", name);
        modelAndView.setViewName("xss");
        return modelAndView;
    }
}
image-20230308100631966

查看页面源代码,可以看到插入到JS里面

image-20230308100604669

修复代码

HtmlUtils类

使用Spring框架提供的HtmlUtils类对用户输入进行转义

package com.example.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.HtmlUtils;

@RestController
public class XssController {
    @GetMapping("/xss")
    public String XssTest(@RequestParam String name) {
        String escapedName = HtmlUtils.htmlEscape(name);
        return "<h1>Hello, " + escapedName + "!</h1>";
    }
}

查看页面源代码,可以看到已经转义

image-20230308100939780

escapeHtml4类

import static org.unbescape.html.HtmlEscape.escapeHtml4;

@RestController
public class XssController {
    @GetMapping("/xss")
    public String XssTest(@RequestParam String name) {
        String escapedName = escapeHtml4(name);
        return "<h1>Hello, " + escapedName + "!</h1>";
    }
}

HTML编码

public class XssController {

    public static String escapeHtml(String str) {
        if (str == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        for (char c : str.toCharArray()) {
            switch (c) {
                case '<':
                    sb.append("&lt;");
                    break;
                case '>':
                    sb.append("&gt;");
                    break;
                case '"':
                    sb.append("&quot;");
                    break;
                case '\'':
                    sb.append("&#x27;");
                    break;
                case '&':
                    sb.append("&amp;");
                    break;
                default:
                    sb.append(c);
            }
        }
        return sb.toString();
    }


    @GetMapping("/xss")
    public String XssTest(@RequestParam String name) {
        return "<h1>Hello, " + escapeHtml(name) + "!</h1>";
    }
}

thymeleaf模板过滤

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>User List</title>
</head>
<body>
<h1>User List</h1>
<table>
    <tr>
        <th>ID</th>
        <th>Name</th>
    </tr>
    <tr th:each="user : ${users}">
        <td th:text="${user.id}"></td>
        <td th:text="${user.name}"></td>
    </tr>
</table>
</body>
</html>

最后更新于