【问题标题】:Checkmarx - How to validate and sanitize HttpServletRequest .getInputStream to pass checkmarx scanCheckmarx - 如何验证和清理 HttpServletRequest .getInputStream 以通过 checkmarx 扫描
【发布时间】:2020-10-01 09:45:10
【问题描述】:

以下是 checkmarx 问题的详细信息 无限制的文件上传

源对象:req(第 39 行)

目标对象:getInputStream(第-41行)

    public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter
{

    //...
38 public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
39            throws AuthenticationException, IOException, ServletException
40    {
41        Entitlements creds = new ObjectMapper().readValue(req.getInputStream(), Entitlements.class);

        return getAuthenticationManager().authenticate(
                new UsernamePasswordAuthenticationToken(creds.getId(), "", Collections.emptyList()));
    }
    //...
}

request 对象在 checkmarx 工具中突出显示 -

如何正确验证、过滤、转义和/或编码用户可控输入以通过 Checkmarx 扫描?

【问题讨论】:

  • 您的问题有点宽泛,但我假设您具体指的是请求对象。验证或过滤或转义的内容取决于您正在使用和处理的 HttpServletRequest 的哪个属性。介意你分享更多代码吗?
  • @RomanCanlas 添加更多代码 sn-p 以供参考。
  • 关于代码的上下文,我认为这是一个误报。这里明显的来源是 request.getHeader("Authorization") ,其中 Checkmarx 怀疑它是恶意输入的入口点,但令牌似乎没有呈现在会导致 XSS 的页面上
  • 您可以在使用输入流之前尝试检查内容类型标头是否为 application/json,但如果没有有关 Checkmarx 查找内容的更多信息,很难说。
  • if (req.getHeader("Content-Type") == null || !req.getHeader("Content-Type").startsWith("application/json")} { // 返回a 400 result } 但实际上您需要确切了解 Checkmarx 的期望。

标签: java spring-boot security sonarqube checkmarx


【解决方案1】:

这对我有用 - checkmarx 通过了这个高漏洞

我使用了@reflexdemon ans 和@tgdavies 评论的组合

@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
        throws IOException
{
    int len = req.getContentLength();
    len = Integer.parseInt(Encode.forHtml(String.valueOf(len)));
    String type = req.getContentType();
    type =  Encode.forHtml(type);
    Entitlements creds;
    if(len == INPUT_LENGTH && type.equals(MIMETYPE_TEXT_PLAIN_UTF_8)) {
        creds = new ObjectMapper().readValue(req.getReader().lines().collect(Collectors.joining(System.lineSeparator())), Entitlements.class);
    }else{
        creds = new Entitlements();
    }

    return getAuthenticationManager().authenticate(
            new UsernamePasswordAuthenticationToken(creds.getId(), "", Collections.emptyList()));
}

【讨论】:

    【解决方案2】:

    有时,我们可以通过一定程度的间接来欺骗工具。您可以尝试以下方法,看看是否可以解决您的问题,

    替换:

    Entitlements creds = new ObjectMapper().readValue(req.getInputStream(), Entitlements.class);
    

    与,

    Entitlements creds = new ObjectMapper().readValue(req.getReader().lines().collect(Collectors.joining(System.lineSeparator())), Entitlements.class);
    

    【讨论】:

    • 让我试试你的解决方案。仅供参考 - checkmarx 检查函数输入参数的整个流程。在您的解决方案中未使用验证/编码/过滤
    • 您能否解释一下,间接级别将如何欺骗该工具
    • 大多数代码扫描工具依赖于标准模式并根据已知模式检测错误。在您的情况下,将原始输入流发送到方法是一个肯定的危险信号。期望是在开始解析数据之前解析输入。这些间接,将是一种非标准模式,因此允许您通过测试。只有当我们确定它是误报时,我们才会使用它。
    • 解决问题了吗?
    • 尚未应用您的代码更改。等待我之前的代码更改报告。仅供参考 - String inputStreamStr = IOUtils.toString(req.getInputStream(), StandardCharsets.UTF_8.name()); inputStreamStr = SecurityUtil.sanitizeObject(inputStreamStr, String.class); InputStream inputStream = new ByteArrayInputStream(inputStreamStr.getBytes()); Entitlements creds = new ObjectMapper().readValue(inputStream, Entitlements.class);
    【解决方案3】:

    你的代码可以重构成这样:

    // Negative
    public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
    
        public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
                throws AuthenticationException, IOException, ServletException {
    
            if (req.getContentLength() > MAX_REQUEST_SIZE) {
                throw new IOException("request body size too big!");
            }
    
            Entitlements creds = new ObjectMapper().readValue(req.getInputStream(), Entitlements.class);
    
            return getAuthenticationManager()
                    .authenticate(new UsernamePasswordAuthenticationToken(creds.getId(), "", Collections.emptyList()));
        }
    
    }
    

    您可以使用getContentLength 作为验证器。虽然默认情况下 CxSAST 9.3 无法检测到此验证器。您可以通过此文件中的内容覆盖 Java_Low_Visibility/Unrestricted_File_Upload 查询: https://github.com/checkmarx-ts/CxQL/blob/master/Java/Java_Low_Visibility/Unrestricted_File_Upload.txt

    还支持其他验证器,getSizegetFileSize。您还可以将MultipartConfig 注释与maxRequestSize 一起使用。或者在 web.xml 中使用multipart-configmax-request-size

    【讨论】:

      【解决方案4】:

      以下解决方案适用于checkmarx 扫描。 在存储 xss 的情况下,我使用了HtmlUtils.escapeHtmlContent(String)

      如果我们想清理@requestbody 中使用的 bean 类,我们必须使用

      Jsoup.clean(StringEscapeUtils.escapHtml4(objectMapper.writeValueAsString(object)), Whitelist.basic());
      

      这为我解决了 checkmarx 漏洞问题

      【讨论】:

        【解决方案5】:

        扫描器似乎在您的代码中发现了 XSS 漏洞。

        来自 OWASP 的Cross-site Scripting (XSS) page

        跨站脚本 (XSS) 攻击是一种注入,其中 恶意脚本被注入其他良性和可信的 网站。 XSS 攻击发生在攻击者使用 Web 应用程序 发送恶意代码,通常以浏览器端脚本的形式, 给不同的最终用户。允许这些攻击成功的缺陷是 相当普遍,并且出现在 Web 应用程序使用来自的输入的任何地方 它生成的输出中的用户,无需验证或编码 它。

        要深入了解如何避免跨站脚本漏洞,非常推荐阅读 OWASP 的XSS (Cross-Site Scripting) Prevention Cheat Sheet page。 那里列出了一些消毒剂选项,您可以根据具体的语言和相关用途进行选择。

        祝你好运。

        【讨论】:

          猜你喜欢
          • 2015-11-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-14
          • 2019-08-27
          • 1970-01-01
          • 2021-07-23
          相关资源
          最近更新 更多