CodeQL 文档

客户端请求伪造

ID: js/client-side-request-forgery
Kind: path-problem
Security severity: 5.0
Severity: error
Precision: medium
Tags:
   - security
   - external/cwe/cwe-918
Query suites:
   - javascript-security-extended.qls
   - javascript-security-and-quality.qls

单击以在 CodeQL 存储库中查看查询

在传出 HTTP 请求的 URL 中直接包含用户输入,可能会导致请求伪造攻击,攻击者会修改请求以针对非预期的 API 端点或资源。客户端伪造的请求可能会执行影响受害者帐户的不希望的操作,或者如果请求响应以不安全的方式处理,可能会导致跨站点脚本。这与 CSRF(跨站点请求伪造)不同,并且通常会绕过 CSRF 防护。这通常不像 SSRF(服务器端请求伪造)那样严重,因为它不会暴露内部服务。

建议

限制传出请求 URL 中的用户输入,尤其是

  • 避免在 URL 的主机名中使用用户输入。从允许列表中选择主机名,而不是直接从用户输入构建它。

  • 在用户输入是 URL 路径名的一部分时要小心。限制输入,以防止路径遍历(“../”)被用来将请求重定向到非预期的端点。

示例

以下示例显示了一个用于获取消息预渲染的 HTML 主体的 HTTP 请求。它使用端点 /api/messages/ID,该端点被认为会响应安全 HTML 字符串,以便嵌入到页面中

async function loadMessage() {
    const query = new URLSearchParams(location.search);
    const url = '/api/messages/' + query.get('message_id');
    const data = await (await fetch(url)).json();
    document.getElementById('message').innerHTML = data.html;
}

但是,消息 ID 的格式没有经过检查,攻击者可以利用这一点来更改请求所针对的端点。如果他们可以将其重定向到返回不受信任值的端点,则会导致跨站点脚本。

例如,给定查询字符串 message_id=../pastebin/123,请求最终会针对 /api/pastebin 端点。或者,如果登录页面上存在开放式重定向,则类似 message_id=../../login?redirect_url=https://evil.com 的查询字符串可能会使攻击者完全控制响应。

在下面的示例中,输入被限制为数字,因此无法更改端点

async function loadMessage() {
    const query = new URLSearchParams(location.search);
    const url = '/api/messages/' + Number(query.get('message_id'));
    const data = await (await fetch(url)).json();
    document.getElementById('message').innerHTML = data.html;
}

参考

  • ©GitHub, Inc.
  • 条款
  • 隐私