OAuth2 授权页面因客户端应用名称包含恶意脚本导致跨站脚本攻击
OAuth2 consent page XSS via client application name containing malicious script
ID: security/oauth2-consent-page-xss-via-client-name
版本兼容性
| 版本 | 状态 | 引入 | 弃用 | 备注 |
|---|---|---|---|---|
| OAuth2 2.0 | active | — | — | — |
| Spring Security 5.7.10 | active | — | — | — |
| Keycloak 21.0.0 | active | — | — | — |
| Auth0 Node.js SDK 2.42.0 | active | — | — | — |
根因分析
OAuth2 授权服务器在授权页面上渲染客户端应用名称时未进行正确的 HTML 转义,允许攻击者注册一个包含 JavaScript 的客户端名称,从而在用户浏览器中执行恶意脚本。
English
The OAuth2 authorization server renders the client application name without proper HTML escaping on the consent page, allowing an attacker to register a client with a name containing JavaScript that executes in the user's browser.
官方文档
https://datatracker.ietf.org/doc/html/rfc6749#section-3.1解决方案
-
在授权页面上渲染客户端应用名称之前,应用 HTML 实体编码。在 Java 与 Spring Security 中,在模板中使用 `HtmlUtils.htmlEscape(clientName)`。对于 Keycloak,覆盖授权表单模板 (consent.ftl) 并使用 `<#escape x as x?html>${client.clientName}</#escape>` 转义 `${client.clientName}`。 -
在注册时验证客户端名称,拒绝任何包含 HTML 标签或脚本字符的名称。使用白名单方法:仅允许字母数字字符、空格和基本标点符号。示例正则表达式:`^[a-zA-Z0-9\s\-_\.]+$`。
-
如果客户端名称用于动态属性,特别针对 JavaScript 上下文实现输出编码。使用 OWASP Java Encoder 等库:`Encoder.forJavaScript(clientName)`。
无效尝试
常见但无效的做法:
-
Add Content-Security-Policy header to block inline scripts
40% 失败
CSP does not prevent the injection itself; if the client name is rendered in a href attribute or event handler, CSP may not block it, and the script still executes in some contexts.
-
Sanitize client name by removing all HTML tags with a simple regex
35% 失败
Attackers can bypass regex-based sanitization with obfuscated payloads (e.g., using Unicode characters or event handlers like onerror).
-
Use a WAF to filter malicious client names during registration
50% 失败
WAF rules are often bypassed by encoding the payload (e.g., base64 or URL encoding), and the consent page still renders the name unsafely.