【问题标题】:System.getenv() used in spring boot is shown as a security vulnerability in sonarQubeSpring Boot 中使用的 System.getenv() 在 sonarQube 中显示为安全漏洞
【发布时间】:2020-09-09 12:08:49
【问题描述】:

我的 Spring Boot 应用程序中有方法从系统环境变量中获取数据,该方法按预期工作,但 sonarQube 说“确保在此处安全使用环境变量”, 我试图找到解决此问题的替代方法,但找不到解决方案,方法如下:

我该如何处理这个安全问题,除了从环境变量中获取值之外,我无法使用任何其他方法。

public Map<String, Object> getConfigurations() {
    Map<String, Object> result = new HashMap<>();
    HttpResponse response = null;
    try {
         String xVaultToken = System.getenv("XVaultToken");
         String cityAppConfig = System.getenv("CityApp_Config");

        @SuppressWarnings("deprecation")
        HttpClient client = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier())
                .setSslcontext(
                        new SSLContextBuilder().loadTrustMaterial(null, (x509Certificates, s) -> true).build())
                .build();
        Map<String, Object> headerDatas = new HashMap<>();
        headerDatas.put("Content-Type", "application/json");
        headerDatas.put("X-Vault-Token", xVaultToken);
        HttpGet get = new HttpGet(cityAppConfig);
        Set<String> keys = headerDatas.keySet();
        for (String key : keys) {
            get.setHeader(key, headerDatas.get(key).toString());
        }
        response = client.execute(get);
        try(BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))){
            String responseData = rd.readLine();
            result.put(Constants.RESPONSE, responseData);
        }
        int statusCode = response.getStatusLine().getStatusCode();
        result.put(Constants.STATUS, statusCode);

    } catch (Exception e) {
        logger.info("error is local settings getConfigurations" + e);
    }
    return result;
}

}

【问题讨论】:

  • Sonnar 是否提出了一些替代方案?
  • 您不需要寻找替代品,只需“确保在此处安全使用环境变量”,如声纳 qube 消息所述。您是否阅读了声纳文档,了解为什么这会被视为漏洞以及如何处理?
  • @JoãoZarate 不,它没有提供任何替代方案,它只是说“确保在此处安全使用环境变量”
  • 这不是关于sanitizing this like any other input吗?如果 OP sqays 他们被 env 变量困住了,我想这就是与那些认为将令牌存储为 env var 是一个好主意和可能的 //NOSONAR
  • 为什么不让 Spring Boot 处理这个问题。如果此类由 Spring 管理,您可以注入 Environment 并执行 getProperty 或仅在实例字段上使用 @Value("${XVaultToken}"。额外的好处,您现在还可以将此配置移动到 application.properties 或 Spring Boot 支持的任何方式(系统环境就是其中之一)。

标签: java spring-boot environment-variables


【解决方案1】:

免责声明!!!

首先,正如我在 cmets 中提到的,如果有人要求您阅读 ENV 变量,但还说您不能将 SonarQube 警告标记为误报:请(礼貌地)告诉他们他们会必须忍受 SonarQube 警告。

但是,如果出于某种原因不能这样做,我将向您展示 2 种可能不会触发 SonarQube 中的警告的方法,它们仍然比为此目的调用 cmd.exe 要简单得多。

示例 1

通过java.util.function.Function调用函数

private static String getenv(String variable) {
    return ((Function<String, String>) System::getenv).apply(variable);
}

示例 2

通过反射调用函数

    private static String getenv(String variable) {
        try {
            return (String) System.class.getMethod("getenv", String.class).invoke(null, variable);
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

【讨论】:

  • 非常感谢,它对我有用! (我知道我需要做出改变,因为 Sonar 正在帮助我,但这给了我时间,这很好)
【解决方案2】:

所有这些“安全热点”警告都只是“TODO”通知,应该分三步解决:

  1. 确保确实安全地使用了该值。
    • 在这种特殊情况下:您正在向外部提供的 URL 调用 GET 请求,然后使用响应中的值。当有人通过某种秘密方式更改环境变量值并将其指向他们自己的 Web 服务器时会发生什么?响应是否用于任何敏感的事情?有时,甚至调用 URL 的事实也可用于恶意目的(跟踪)。等等等等
  2. 添加@SuppressWarnings({"squid:S5304"}) 注释,并在注释中添加适当的描述。
  3. 确保所有内容都经过适当审查,包括第 1 步的推理。记住:两个头脑比一个头脑好(尤其是在安全方面)。

【讨论】:

    【解决方案3】:

    可以使用@SuppressWarnings({"squid:S5304"}) 抑制其低级别问题。 在类级别添加此语句。

    【讨论】:

      【解决方案4】:

      经过大量搜索后,我发现使用环境变量来存储重要信息是一个坏主意,但如果您没有像我这样的其他选择,这里是解决方法:

      不要使用 System.getenv("XVaultToken"),而是使用这样的方法

      private String cmdUrl = "cmd.exe /c echo %wfManagement_Config%";
      String cityAppConfig =  getEnvironmentVariable(cmdUrl)
      
      private String getEnvironmentVariable(String cmd){
          String environmentVar = "";
          Process p;
          try {
              p = Runtime.getRuntime().exec(cmd);
              p.waitFor(); 
              BufferedReader reader=new BufferedReader(new InputStreamReader(
               p.getInputStream())); 
              String line; 
              while((line = reader.readLine()) != null) { 
                  environmentVar = line;
              }
              return environmentVar;
          } catch (Exception e) {
              logger.info("Exception-->"+e);
          }
          return environmentVar;
          
      }
      

      该方法运行命令并为您获取环境变量,由于某些原因 sonarQube 会忽略这一点并且不会产生安全问题。

      【讨论】:

      • SonarQube 会尽力帮助您。您不应该仅仅为了 SonarQube 不会为您触发警告而构建 Code-Workarounds。如果您说您当时确实需要该环境变量并且您确定自己在做什么:将其标记为误报。但是不要为了 SonarQube 不触发而构建代码变通方法!这是一个非常糟糕的主意!
      • 我完全理解你在说什么,但我不能让它误报,而且他们也不愿意不使用环境变量,所以我必须找到一种解决方法。跨度>
      • 然后我会告诉他们,他们必须忍受安全警告。此外,您可以通过反射调用getenv 方法,SonarQube 不会触发。丑陋,但不像产生外部进程那样丑陋,它也只能在一个平台(windows)上运行
      • 所以实际上编写的代码并不能清楚地表达它在做什么,并且很难运行它是可以的。
      猜你喜欢
      • 2016-02-12
      • 1970-01-01
      • 2018-12-21
      • 2021-06-05
      • 1970-01-01
      • 2022-12-19
      • 2020-12-05
      • 1970-01-01
      • 2022-01-17
      相关资源
      最近更新 更多