如何在 SAST Checkmarx 之后解决 API 控制器中的 XSRF 跨站请求伪造 (CSRF)

Posted

技术标签:

【中文标题】如何在 SAST Checkmarx 之后解决 API 控制器中的 XSRF 跨站请求伪造 (CSRF)【英文标题】:How to resolve XSRF Cross-Site Request Forgery (CSRF) in API controller after SAST Checkmarx 【发布时间】:2021-07-08 08:49:33 【问题描述】:

我已经使用 Checkmarx 工具扫描了我的项目 java spring boot。 该工具发现了大约 23 个中等严重性的 XSRF 事件。

发现的问题标记在@RequestBody List<String> lineups上的 Rest API 方法 POST 上

附上描述结果的截图:

    @RequestMapping(value = "/rules/lineup/ruleMode", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Object> getRulesByRuleModeAndLineup(@PathVariable Integer ruleMode,
            @RequestBody List<String> lineups) throws Exception 
        
        LOGGER.info("[getRulesByRuleModeAndLineup] ENTER type: " + ruleMode + " lineup: " + lineups);
        
        ResponseEntity<Object> output = null;
        List<Rule> rules = new ArrayList<Rule>();

        try 
            
            for (String lineup : lineups) 
                
                String lineupSanitized = htmlUtils.htmlEscape(lineup);
                rules.addAll(uiService.getRulesByRuleModeAndLineup(ruleMode, lineupSanitized));

            

            output = new ResponseEntity<>(rules, HttpStatus.OK);

         catch (Exception e) 

            LOGGER.error(e, e);
            output = new ResponseEntity<>("An error occurred: " + e.getMessage() + "'",
                    HttpStatus.INTERNAL_SERVER_ERROR);

        

        return output;

    

是否有解决问题的示例修复程序?

【问题讨论】:

该消息似乎很好地解释了这个问题:有一个用户提供的参数似乎在该方法中使用不安全。如何安全使用它或丢弃错误?只有你可以知道,因为只有你可以看到处理它的方法的源代码。如果您不向我们展示该代码,那么读者将无能为力。 【参考方案1】:

您可以选择对该字段进行验证。 在这里你有两个选择:

    使用已经内置的框架,我推荐 spring 为了这: https://docs.spring.io/spring-security/site/docs/3.2.0.CI-SNAPSHOT/reference/html/csrf.html 尝试将您希望在您的 api 上接受的字符串列入白名单,如果您 可以做到。

第二个意味着你有责任保持你的列表是最新的。

【讨论】:

【参考方案2】:

我试图实现你在回答中所说的第一点,比如后面的代码

后端端:

    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.web.csrf.CookieCsrfTokenRepository;

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter 
    
        private static final Logger LOGGER = LogManager.getLogger(SecurityConfig.class);
    
        
        @SuppressWarnings("javadoc")
        @Override
        protected void configure(HttpSecurity http) throws Exception 
            
            http.authorizeRequests().antMatchers("/**").permitAll().anyRequest().authenticated();
            
            http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
            
            http.headers().httpStrictTransportSecurity();
        
    
    

前端

我在后面的代码中实现了一个xhrRequestHandler文件名js:

XMLHttpRequest.prototype.origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function () 
    this.origOpen.apply(this, arguments);
    if (document.cookie) 
        var csrfToken = document.cookie.match(new RegExp(`XSRF-TOKEN=([^;]+)`))[1];
        if (csrfToken) 
            this.setRequestHeader("X-XSRF-TOKEN", csrfToken);
        
    
    if (arguments[1].includes("socket/info")) 
        this.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    
;

在 index.jsp 上

我用下面的代码导入了上面定义的文件js:

<script src="<c:url value="/resources/js/xhrRequestHandler.js"/>"></script>

并添加元名称行:

<meta name="_csrf" content="$_csrf.token"/>
    <meta name="_csrf_header" content="$_csrf.headerName"/>

但我没有解决问题

有什么问题吗?

【讨论】:

以上是关于如何在 SAST Checkmarx 之后解决 API 控制器中的 XSRF 跨站请求伪造 (CSRF)的主要内容,如果未能解决你的问题,请参考以下文章

Checkmarx 反射型 XSS

checkmarx下载地址

Workfusion 代码是不是有任何 SAST 工具?

第38篇:Checkmarx代码审计/代码检测工具的使用教程

checkmarx使用笔记

GitHub Marketplace SAST 工具 gitleaks