代码质量检查规则中的 is provided externally to the method and not sanitized b.

今天在解决小组内代码质量检查严重级别问题时遇到一条规则错误'"count"is provided externally to the method and not sanitized before use'(“count”在方法外部提供,在使用前未经消毒--谷歌翻译)本来感觉是挺容易解决的一个问题,却让我很是郁闷了一下,在这里跟大家共享一下!

接下来我们可以看一下SQ给出来的示例

Noncompliant Code Example

public User getUser(Connection con, String user) throws SQLException {

  Statement stmt1 = null;
  Statement stmt2 = null;
  PreparedStatement pstmt;
  try {
    stmt1 = con.createStatement();
    ResultSet rs1 = stmt1.executeQuery("GETDATE()"); // Compliant; parameters not used here

    stmt2 = con.createStatement();
    ResultSet rs2 = stmt2.executeQuery("select FNAME, LNAME, SSN " +
                 "from USERS where UNAME=" + user);  // Noncompliant; parameter concatenated directly into query

    pstmt = con.prepareStatement("select FNAME, LNAME, SSN " +
                 "from USERS where UNAME=" + user);  // Noncompliant; parameter concatenated directly into query
    ResultSet rs3 = pstmt.executeQuery();

    //...
}

public User getUserHibernate(org.hibernate.Session session, String userInput) {

  org.hibernate.Query query = session.createQuery(  // Compliant
            "FROM students where fname = " + userInput);  // Noncompliant; parameter binding should be used instead
  // ...
}
Compliant Solution

public User getUser(Connection con, String user) throws SQLException {

  Statement stmt1 = null;
  PreparedStatement pstmt = null;
  String query = "select FNAME, LNAME, SSN " +
                 "from USERS where UNAME=?"
  try {
    stmt1 = con.createStatement();
    ResultSet rs1 = stmt1.executeQuery("GETDATE()");

    pstmt = con.prepareStatement(query);
    pstmt.setString(1, user);  // Compliant; PreparedStatements escape their inputs.
    ResultSet rs2 = pstmt.executeQuery();

    //...
  }
}

public User getUserHibernate(org.hibernate.Session session, String userInput) {

  org.hibernate.Query query =  session.createQuery("FROM students where fname = ?");
  query = query.setParameter(0,userInput);  // Parameter binding escapes all input
  // ...

原始版本代码

String sqlSear = "";
            if(status == 1){
                sqlSear = "select C_ID, C_ZIP from DB_SJB.T_SJB where N_ZT = ? and N_RECEIVEID = " + this.receiveId + " order by D_DCSJ";
            }else{
                sqlSear = "select C_ID, C_ZIP from DB_SJB.T_SJB where N_ZT = ? and N_RECEIVEID = " + this.receiveId + " order by D_DCSJ limit "+ count;
            }
            queryPs = conn.prepareStatement(sqlSear);
            queryPs.setInt(1, status);
            rs = queryPs.executeQuery();

结合SQ给出的示例代码我们猜测:因为count是外部传递的,他可能认为这个值不可控,有可能造成注入漏洞,所以提示错误。

修正版本代码 1

String sqlSear = "";
            if(status == 1){
                sqlSear = "select C_ID, C_ZIP from DB_SJB.T_SJB where N_ZT = ? and N_RECEIVEID = " + this.receiveId + " order by D_DCSJ";
            }else{
                sqlSear = "select C_ID, C_ZIP from DB_SJB.T_SJB where N_ZT = ? and N_RECEIVEID = " + this.receiveId + " order by D_DCSJ limit ?";
            }
            queryPs = conn.prepareStatement(sqlSear);
            queryPs.setInt(1, status);
            // 代码质量检查规则不允许外部参数直接与执行语句相加,使用占位符
            if(status != 1){
                    queryPs.setInt(2, count);
            }
            rs = queryPs.executeQuery();

重新校验后发现错误依旧,只是去掉了count变量名 '""is provided externally to the method and not sanitized before use'

那么继续分析,思路依旧是注入漏洞。只剩下 this.receiveId 没有使用占位符了,有可能他导致的?

 

修正版本代码 2

String sqlSear = null;
            if(status == 1){
                sqlSear = "select C_ID, C_ZIP from DB_SJB.T_SJB where N_ZT = ? and N_RECEIVEID = ? order by D_DCSJ";
            }else{
                sqlSear = "select C_ID, C_ZIP from DB_SJB.T_SJB where N_ZT = ? and N_RECEIVEID = ? order by D_DCSJ limit ?";
            }
            queryPs = conn.prepareStatement(sqlSear);
            queryPs.setInt(1, status);
            queryPs.setInt(2, this.receiveId);
            // 代码质量检查规则不允许外部参数直接与执行语句相加,使用占位符
            if(status != 1){
                    queryPs.setInt(3, count);
            }
            rs = queryPs.executeQuery();

再次校验,错误提示没有任何改变,始终指向 queryPs = conn.prepareStatement(sqlSear) 这一行
这就不科学了呀,示例里面也是使用占位符规避这个问题的呀!代码中现在已经全部使用占位符了,你还要怎样?
但问题依然需要解决呀,那就求助谷歌大神吧!
网上针对这个问题的方案跟SQ自己的示例都差不多,都是改用占位符解决问题,但我的还是没解决啊(摔)!!!


在下面这个网址的代码示例中定义了四个字符串变量query,query2,query3,s(着重关注这四个,其他的略过)
对比后发现query定义时直接使用+字符串类型的参数,这样有注入漏洞的危险我们都知道,果然下面使用该变量时,后面都使用了Noncompliant关键字标注,代表不合格
但是使用query2和query3的地方都没有提示不合格。为什么呢?query2虽然有拼接,但是都是固定的值,不会存在注入漏洞;query3直接是没有任何变动的字符串,所以也不会出现注入漏洞。但是我们的修正代码版本2也不会有注入漏洞呀!!!(╯‵□′)╯︵┻━┻
修正代码版本2中的代码与query2和query3的区别是什么呢?最后发现示例中的query2和query3都是在定义时给了一个不为空的值,而我们的代码中给了一个null,所以猜测可能是初始值不能为空(空值或null),而他不知道你在初始化到执行conn.prepareStatement(sqlSear)之间对这个变量做了什么操作(或者他判断逻辑有误),执行时他的结果是什么(本质是因为他得到的变量结果和实际得到的结果不一致),导致后面的规则校验没有通过导致。
参考解决方案地址 https://github.com/SonarSource/sonar-java/blob/master/java-checks/src/test/files/checks/SQLInjection.java
PS:可以看到后面的变量s是直接定义的变量,没有给任何默认值,这样他也是认为合法。

 

修正版本代码 3

private static final String sqlSear = "select C_ID, C_ZIP from DB_SJB.T_SJB where N_ZT = ? and N_RECEIVEID = ? order by D_DCSJ ?";  //定义为类常量

问题解决!!!
可能本人level不够,感觉这是规则校验不完全合理,修正代码2从逻辑上来说我认为是合法的。请大神们指点!!!
PS:脚本中两个参数都是int类型的,所以不存在注入漏洞,如果这个规则是为了防止注入漏洞的话,不修改任何代码都算逻辑上的合法!如果从代码规范化上来说,修正版本2也应该是最终版本,不应该继续提示错误才对!!!


规则源码地址 https://github.com/SonarSource/sonar-java/blob/master/java-checks/src/main/java/org/sonar/java/checks/SQLInjectionCheck.javahttp://www.atetric.com/atetric/javadoc/org.codehaus.sonar-plugins.java/java-checks/2.7/src-html/org/sonar/java/checks/SQLInjectionCheck.html

翻译Device configuration register The device has various configuration settings that are global in nature. The configuration settings are as follows: • When the 33978 is in the overvoltage region, a Logic [0] on the VBATP OV bit limits the wetting current on all input channels to 2 mA and the 33978 will not be able to enter into the Low-power mode. A Logic [1] allows the device to operate normally even in the overvoltage region. The OV flag will be set when the device enters in the OV region, regardless the value of the VBATP OV bit. • WAKE_B can be used to enable an external power supply regulator to supply the VDDQ voltage rail. When the WAKE_B VDDQ check bit is a Logic [0], the WAKE_B pin is expected to be pulled-up internally or externally to VDDQ and VDDQ is expected to go low, therefore the 33978 does not wake-up on the falling edge of WAKE_B. A Logic [1], assumes the user is using an external pull-up to VBATP or VDDQ (when VDDQ is not expected to be off) and the IC wakes up on a falling edge of WAKE_B. • INT_B out is used to select how the INT_B pin operates when an interrupt occurs. The IC is able to pulse low [1] or latch low [0]. • Aconfig[1-0] is used to determine the method of selecting the AMUX output, either a SPI command or using a hardwired setup using SG[3-1]. • Inputs SP0-7 may be programmable for switch-to-battery or switch-to-ground. These inputs types are defined using the settings command. To set a SPn input for switch-to-battery, a logic [1] for the appropriate bit must be set. To set a SPn input for switch-toground, a logic [0] for the appropriate bit must be set. The MCU may change or update the programmable switch register via software at any time in Normal mode. Regardless of the setting, when the SPn input switch is closed a logic [1] is placed in the serial output response register.
07-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值