JSON API 响应被漏洞扫描器标记为 XSS。这是误报吗?

信息安全 xss 漏洞扫描器 json
2021-08-29 18:53:34

当用户尝试访问任何未经身份验证的 URL(包括不存在的 URL)时,我的 Web 服务会返回 HTTP 401 响应。此响应是 JSON 编码的,并且此响应的正文包含用户请求的路径,可能是出于诊断目的。响应还包括www-authenticate标头。如果用户在浏览器中访问此 URL,则会触发他们的浏览器要求提供凭据。

但是,自动扫描工具报告这是一个 XSS 漏洞。这似乎是因为包含了请求的路径,并且如果请求的路径也恰好是有效的 JavaScript,则此路径与响应一起返回。请参阅下面的 cURL 输出:

curl -i  'https://myservice.example.com/<script>alert(1)</script>'
HTTP/2 401
server: nginx
date: Tue, 19 May 2020 15:02:20 GMT
content-type: application/json;charset=UTF-8
content-length: 167
strict-transport-security: max-age=31536000 ; includeSubDomains
www-authenticate: Basic realm="Spring"

{"timestamp":1589900540080,"status":401,"error":"Unauthorized","message":"Full authentication is required to access this resource","path":"/<script>alert(1)</script>"}%

我认为这是一个误报,因为 API 响应是 JSON 编码的,根据这个问题:Reflected XSS via JSON execute with Burp, but how to do it in real conditions?

我对么?

4个回答

XSS 漏洞通常由两部分组成:一个后端,它反映用户提供的字符串而不过滤它们;一个前端,它将该输入放入一个 HTML 文档而不过滤它。

因此,您不仅需要查看服务器的功能,还需要查看使用该 JSON 响应的应用程序。

是否有可能将其path原样注入 HTML 文档而不首先转义其中的任何 HTML 标记?或者它不是用它来处理那个 JSON 文档,JSON.parse而是用eval它来允许服务器将可执行代码传递给它?

如果是这种情况,那么首要任务是修复消费应用程序。但是,作为纵深防御策略的一部分,您最好不要阻止服务器将包含有效 HTML 的字符串传递给客户端。<一个好的方法是将and编码>&lt;and &gt;

如果用户提供的字符串包含". 这可能不仅令人讨厌,而且在某些情况下还可能被滥用来混淆使用响应的工具。

这不容易受到 XSS 的攻击,因为它Content-Type被设置为application/json,因此所有主要的现代浏览器都不会执行 Javascript。如果你用 JSON 响应做一些花哨的 Javascript 东西,它可能会变成一个DOM XSS(但从你分享的内容来看,情况似乎并非如此)。

更详细的答案可以在这里找到。

这看起来像是许多自动扫描器会发现的一个发现:他们在 URL 中放了一些东西,然后看到它反映在响应正文中。

在您的情况下,这会以有效的 JSON 报告回来,因此这不是问题。虽然不像口哨那样干净,但您很难找到一个浏览器或 API 使用者在其中的文本上失败。如您所知,那个看起来很危险的 HTML 可能是有效的,并且由客户端来处理它。

在 text/html 上下文中没有那么多,在那种情况下有这种情况。

就目前而言,没有。所发生的只是客户端在 JSON 响应中放置了一个定制的字符串。要发生 XSS,必须将定制字符串写入不安全的资源(HTML 文件)。

如果您的网页出于某种原因打印了此请求的路径(可能是请求记录页面),那么您可能会遇到一些讨厌的事情。例如,此代码易受攻击:

.
.
.
output.Append($"<tr><td>{request.path}</td></tr>\n");
.
.
return Ok(output.ToString());

现在这是一个不切实际的示例,因为通常如果您像本示例中那样使用 C#,则不会像这样生成标记,您将使用 Razor,或者在前端使用 AJAX 生成它。我选择这个例子是因为如果你自己不是一个 .NET 程序员,它更简洁并且更容易被理解。

可以通过两种方式防止 XSS 和大多数注入。您可以转义(又名清理)每个字符串。对你来说,这意味着用<and>替换&lt;and &gt;或者您可以确保不安全的字符串永远不会被视为代码(或在本例中为标记)。许多前端,例如 React 都是第二种选择。

如果你使用 React 并且有这样的 JSX:

.
.
.
return <h1>{foo}</h1>

无论变量的内容如何foo,除非您这样做,否则它永远不会被视为标记/代码:

.
.
.
return <h1 dangerouslySetInnerHTML={{_html : foo}}/>

你必须选择一个选项,除非你已经在使用 React 或类似的东西,否则清理字符串可能更容易。在 API 中清理字符串更容易,因为这样您就知道使用它的所有内容都是安全的,但是,这可能不一定是最合适的风格:您可能会觉得字符串的清理不是 API 问题,而是一个问题对于任何使用 API 来解决的问题。