将 HttpServletRequest.getQueryString() 用于易受响应拆分的响应标头?

信息安全 Web应用程序 爪哇 响应分裂
2021-09-04 07:43:18

有人告诉我,HttpServletRequest.getQueryString()在响应标头中使用会使我的应用程序容易受到 HTTP 响应拆分攻击,但我只是不知道如何。

在 的情况下很清楚getParameter(String),它解码百分比编码的值,但getQueryString()不这样做。从文档中:

该值不被容器解码。

说明我在做什么的源代码片段:

String path = "some_url";

String qs = req.getQueryString();
if (qs != null)
    path += "?" + qs;

// response instanceof HttpServletResponse
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
response.setHeader("Location", path);

我试图重现这个问题,我只是得到百分比编码的换行符在响应中回显给我。当我将代码更改为 时getParameter(…),它按预期工作(除了我的容器足以从标头值中删除换行符,但理论上至少它可以工作)。Stack Overflow 上的这个类似问题提出了同样的问题,并且对答案的评论指出getQueryString()不解码没有得到回应。

我在这里错过了什么吗?还是我的建议错了?

1个回答

使用来自用户的数据而不对其进行清理的一般模式是漏洞的来源。典型的东西,比如 XSS 和 SQLi。在这种情况下,您从用户那里获取输入并直接将其作为标题。这可能会导致响应拆分、标头注入,并且可能会导致另一个或两个问题(例如:如果您可以注入 Javascript,CSRF 可能是可能的)。但是你说:

我的容器足够好,可以从标题值中删除换行符

所以这阻止了实际的利用。

我怀疑即使您要过滤输入,例如:

path += "?" + sanitize(qs);

对于适当的sanitize功能(例如来自OWASP 的 AntiSamy 项目),您的静态分析器将继续为您提供此发现。因此,最后,您将将此发现标记为误报(Not an issue如果您使用的是 Fortify)。唯一的问题是您是否应该在将发现标记为误报之前包含代码更改。

我的看法是,如果 API 明确表示它负责安全处理换行符和其他特殊字符,那么您无需采取任何行动。当我查看HttpServletResponse.setHeader的 Javadoc 时,我看不到如何处理特殊字符。因此,除非规范明确声明对此进行安全处理(我认为没有,但我没有在 Servlet 规范中查找),否则我建议清理输入并重新运行静态扫描程序。如果如我所料,它继续报告此问题,则将其标记为误报并放心,一切都很好。

我觉得你应该只信任规范中指定的这种行为的原因是,这是唯一可以保证的行为。您的 Servlet 容器或另一个容器的新版本可能会改变这种行为。尽管它会导致您的网站易受攻击,但您不太可能检测到此类更改。