代码质量管理-安全问题

作者:

文章目录
  • 错误代码: try { saveGeographicInfo(geographicInfo, gisConfig); } catch (Exception e) { e.printStackTrace(); //Use a logger to log this exception. } Reason: 不应调用Throwable.printStackTrace(…) printStackTrace(…)将抛出及其堆栈跟踪打印到某个流。默认情况下,该stream System.Err可能会无意中公开敏感信息。 应该使用记录器来打印一次性文件,因为它们有许多优点: 用户可以轻松地检索日志。 日志消息的格式是统一的,允许用户轻松浏览日志。 如果使用printStackTrace时没有参数,即堆栈跟踪打印到默认流时,此规则会引发问题。 Solution: 错误案例: //Noncompliant Code Example try { /* … */ } catch(Exception e) { LOGGER.log(“context”, e); } try { /* … */ } catch(Exception e) { e.printStackTrace(); // Noncompliant } 推荐案例: //Compliant Solution try { /* … */ } catch(Exception e) { LOGGER.log(“context”, e); }
  • 错误代码: try { /* 建立连接 */ conn = DriverManager.getConnection(URL, username, password); //Add password protection to this database。 } Reason: 数据库应始终受密码保护,但使用密码为空的数据库连接清楚地表明数据库未受保护。 用空密码标记数据库连接。 Solution: 错误案例: //Noncompliant Code Example Connection conn = DriverManager.getConnection(“jdbc:derby:memory:myDB;create=true”, “AppLogin”, “”); Connection conn2 = DriverManager.getConnection(“jdbc:derby:memory:myDB;create=true?user=user&password=”); 推荐案例: //Compliant Solution DriverManager.getConnection(“jdbc:derby:memory:myDB;create=true?user=user&password=password”); DriverManager.getConnection(“jdbc:mysql://address=(host=myhost1)(port=1111)(key1=value1)(user=sandy)(password=secret),address=(host=myhost2)(port=2222)(key2=value2)(user=sandy)(password=secret)/db”); DriverManager.getConnection(“jdbc:mysql://sandy:secret@[myhost1:1111,myhost2:2222]/db”); String url = “jdbc:postgresql://localhost/test”; Properties props = new Properties(); props.setProperty(“user”, “fred”); props.setProperty(“password”, “secret”); DriverManager.getConnection(url, props);
  • 错误代码: public static Map<String, String> map; Reason: 没有充分的理由在不声明字段“final”的情况下声明字段“public”和“static”。大多数情况下,这是一个在多个对象之间共享状态的错误。但是使用这种方法,任何对象都可以对共享状态执行它想要的任何操作,例如将其设置为空。 Solution: 错误案例: //Noncompliant Code Example public class Greeter { public static Foo foo = new Foo(); … } 推荐案例: //Compliant Solution public class Greeter { public static final Foo FOO = new Foo(); … }
  • 错误代码: private static final String DBPASSWORD = “xxxxxx”;// 数据库密码 Reason: 由于从已编译的应用程序中提取字符串很容易,因此不应硬编码凭据。这样做,它们几乎肯定会落入攻击者手中。这对于分布式应用程序尤其如此。 凭据应存储在代码之外的受强保护的加密配置文件或数据库中。 建议使用其他凭据字(如“oauthToken”、“secret”、。。。 Solution: 错误案例: //Noncompliant Code Example Connection conn = null; try { conn = DriverManager.getConnection(“jdbc:mysql://localhost/test?” + “user=steve&password=blue”); // Noncompliant String uname = “steve”; String password = “blue”; conn = DriverManager.getConnection(“jdbc:mysql://localhost/test?” + “user=” + uname + “&password=” + password); // Noncompliant java.net.PasswordAuthentication pa = new java.net.PasswordAuthentication(“userName”, “1234”.toCharArray()); // Noncompliant 推荐案例: //Compliant Solution Connection conn = null; try { String uname = getEncryptedUser(); String password = getEncryptedPass(); conn = DriverManager.getConnection(“jdbc:mysql://localhost/test?” + “user=” + uname + “&password=” + password);
  • 1、Use a logger to log this exception.2、Add password protection to this database3、Make this “public static map” field finalMake map a static final constant or non-public and provide accessors if needed.4、’PASSWORD’ detected in this expression, review this potentially hard-coded credential.4.1 Remove this hard-coded password.

    自动化持续代码质量监测工具SonarQube,有关安全问题相关代码示例。

    错误代码:

    try {
         saveGeographicInfo(geographicInfo, gisConfig);
     } catch (Exception e) {
         e.printStackTrace();
         //Use a logger to log this exception.
     }
    

    Reason:

    不应调用Throwable.printStackTrace(…)
    printStackTrace(…)将抛出及其堆栈跟踪打印到某个流。默认情况下,该stream System.Err可能会无意中公开敏感信息。

    应该使用记录器来打印一次性文件,因为它们有许多优点:

    用户可以轻松地检索日志。
    日志消息的格式是统一的,允许用户轻松浏览日志。
    如果使用printStackTrace时没有参数,即堆栈跟踪打印到默认流时,此规则会引发问题。

    Solution:

    错误案例:

    //Noncompliant Code Example
    try {
      /* ... */
    } catch(Exception e) {
      LOGGER.log("context", e);
    }
    try {
      /* ... */
    } catch(Exception e) {
      e.printStackTrace();        // Noncompliant
    }
    

    推荐案例:

    //Compliant Solution
    try {
      /* ... */
    } catch(Exception e) {
      LOGGER.log("context", e);
    }
    

    错误代码:

    try {
      /* 建立连接 */
      conn = DriverManager.getConnection(URL, username, password);
      //Add password protection to this database。
      }
    

    Reason:

    数据库应始终受密码保护,但使用密码为空的数据库连接清楚地表明数据库未受保护。

    用空密码标记数据库连接。

    Solution:
    错误案例:

    //Noncompliant Code Example
    Connection conn = DriverManager.getConnection("jdbc:derby:memory:myDB;create=true", "AppLogin", "");
    Connection conn2 = DriverManager.getConnection("jdbc:derby:memory:myDB;create=true?user=user&password=");
    

    推荐案例:

    //Compliant Solution
    DriverManager.getConnection("jdbc:derby:memory:myDB;create=true?user=user&password=password");
    
    DriverManager.getConnection("jdbc:mysql://address=(host=myhost1)(port=1111)(key1=value1)(user=sandy)(password=secret),address=(host=myhost2)(port=2222)(key2=value2)(user=sandy)(password=secret)/db");
    
    DriverManager.getConnection("jdbc:mysql://sandy:secret@[myhost1:1111,myhost2:2222]/db");
    
    String url = "jdbc:postgresql://localhost/test";
    Properties props = new Properties();
    props.setProperty("user", "fred");
    props.setProperty("password", "secret");
    DriverManager.getConnection(url, props);
    

    错误代码:

    public static Map<String, String> map;
    

    Reason:
    没有充分的理由在不声明字段“final”的情况下声明字段“public”和“static”。大多数情况下,这是一个在多个对象之间共享状态的错误。但是使用这种方法,任何对象都可以对共享状态执行它想要的任何操作,例如将其设置为空。

    Solution:
    错误案例:

    //Noncompliant Code Example
    public class Greeter {
      public static Foo foo = new Foo();
      ...
    }
    

    推荐案例:

    //Compliant Solution
    public class Greeter {
      public static final Foo FOO = new Foo();
      ...
    }
    

    公共类变量字段不尊重封装原则,有三个主要缺点:

    无法添加其他行为,如验证。
    内部表示是公开的,以后不能更改。
    成员值可能会在代码中的任何地方发生变化,并且可能不符合程序员的假设。

    通过使用私有属性和访问器方法(set和get),可以防止未经授权的修改。
    Solution:
    错误案例:

    //Noncompliant Code Example
    public class MyClass {
      public static final int SOME_CONSTANT = 0;     // Compliant - constants are not checked
      public String firstName;                       // Noncompliant
    }
    

    推荐案例:

    //Compliant Solution
    public class MyClass {
    
      public static final int SOME_CONSTANT = 0;     // Compliant - constants are not checked
    
      private String firstName;                      // Compliant
    
      public String getFirstName() {
        return firstName;
      }
    
      public void setFirstName(String firstName) {
        this.firstName = firstName;
      }
    
    }
    

    例外情况:
    因为它们不可修改,所以此规则忽略公共final字段。

    错误代码:

    private static final String DBPASSWORD = "xxxxxx";// 数据库密码
    

    Reason:

    由于从已编译的应用程序中提取字符串很容易,因此不应硬编码凭据。这样做,它们几乎肯定会落入攻击者手中。这对于分布式应用程序尤其如此。

    凭据应存储在代码之外的受强保护的加密配置文件或数据库中。
    建议使用其他凭据字(如“oauthToken”、“secret”、。。。

    Solution:
    错误案例:

    //Noncompliant Code Example
    Connection conn = null;
    try {
      conn = DriverManager.getConnection("jdbc:mysql://localhost/test?" +
            "user=steve&password=blue"); // Noncompliant
      String uname = "steve";
      String password = "blue";
      conn = DriverManager.getConnection("jdbc:mysql://localhost/test?" +
            "user=" + uname + "&password=" + password); // Noncompliant
    
      java.net.PasswordAuthentication pa = new java.net.PasswordAuthentication("userName", "1234".toCharArray());  // Noncompliant
    

    推荐案例:

    //Compliant Solution
    Connection conn = null;
    try {
      String uname = getEncryptedUser();
      String password = getEncryptedPass();
      conn = DriverManager.getConnection("jdbc:mysql://localhost/test?" +
            "user=" + uname + "&password=" + password);
    

    错误代码:

    try {
        Class.forName(DBDRIVER);// 注册驱动
        conn = DriverManager.getConnection(DBURL,DBUSER, DBPASSWORD);// 获得连接对象
    

    解决方案同4。

    评论

    发表回复

    您的邮箱地址不会被公开。 必填项已用 * 标注

    站内搜索