有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

准备语句中动态where条件的java SQL注入

在我的应用程序中,我们从UI收集一些用户输入,并根据这些值生成具有不同“Where”条件的动态SQL来查询数据。我们发现这段代码有一些SQL注入缺陷

我无法重新安排此代码以防止该漏洞。任何建议都会有帮助

我的应用程序需要四个输入参数

  1. 序列号-可以是一个或无,也可以是两个值 2.创建日期-可以是,一个或无,或两个值
  2. ReportTypeNumber-可以是一个、一个或多个
  3. reportTitleNames可以是一个、一个或多个

基于这些输入值,我正在为准备好的语句构造动态“Where”条件。此SQL存在问题。请帮我重写它以修复SQL注入缺陷

下面是构造动态SQL的方法

public void filter(String strSerialNumberLogic, String strSerialNumber1,
        String strSerialNumber2, String strCreationDateLogic,
        long lngCreationDate1, long lngCreationDate2,
        String strTypeNumbers, String strTitles, long lngLoc)
        throws SQLException, ClassNotFoundException {

    StringBuffer strWhere = new StringBuffer();
    List paramList = new ArrayList();
    String arrTypeNumbers[];
    String arrTitles[];
    int i;
    boolean bolHit;

    if (!strTypeNumbers.equals("") || !strTitles.equals("")) {
        arrTypeNumbers = strTypeNumbers.split(",");
        arrTitles = strTitles.split(",");

        bolHit = false;
        strWhere.append("(");

        for (i = 0; i < arrTypeNumbers.length; i++) {
            if (arrTypeNumbers[i].length() > 0) {
                if (bolHit) {
                    strWhere.append(" OR ");
                } else {
                    bolHit = true;
                }

                strWhere.append(" REPORT_NUMBER = ?");
                paramList.add(arrTypeNumbers[i]);
            }
        }

        for (i = 0; i < arrTitles.length; i++) {
            if (arrTitles[i].length() > 0) {
                if (bolHit) {
                    strWhere.append(" OR ");
                } else {
                    bolHit = true;
                }

                strWhere.append(" REPORT_NAME = ?");
                paramList.add(arrTitles[i]);
            }
        }

        strWhere.append(") ");
    }

    if (!strSerialNumber1.equals("")) {

        if (!strWhere.equals("")) {
            strWhere.append(" AND ");
        }
        strWhere.append(" REPORT_FILE_NO " + strSerialNumberLogic + " ? ");
        paramList.add(strSerialNumber1);

        if (strSerialNumberLogic.equals("between")) {
            strWhere.append(" AND ? ");
            paramList.add(strSerialNumber2);
        }
    }

    if (lngCreationDate1 != 0) {


        if (!strWhere.equals("")) {
            strWhere.append(" AND ");
        }

        strWhere.append(" REPORT_CREATION_DATE " + strCreationDateLogic + " ? ");
        paramList.add(Long.toString(lngCreationDate1));

        if (strCreationDateLogic.equals("between")) {
            strWhere.append(" AND ? ");
            paramList.add(Long.toString(lngCreationDate2));
        }
    }

    if (lngLoc != 0) {

        if (!strWhere.equals("")) {
            strWhere.append(" AND ");
        }
        strWhere.append(" REPORT_FILE_LOCATION = ? ");
        paramList.add(Long.toString(lngLoc));
    }
    String finalQuery = "";
    if (!strWhere.equals("")) {
        finalQuery = "WHERE " + strWhere.toString();
    }

    String strSQL = "SELECT * " + "FROM D990800 "
            + "LEFT JOIN D990400 ON REPORT_SYSTEM_ID ||" + " REPORT_NO = REPORT_NUMBER " + finalQuery
            + "ORDER BY REPORT_FILE_NO ASC";


    System.out.println("strSQL:" + strSQL );
    System.out.println("paramList:" + paramList );

    Connection conn = ConnectionFactory.instance().getConnection();
    PreparedStatement preparedStatement = null;
    preparedStatement = conn.prepareStatement(strSQL);

    for (int index = 0; index < paramList.size(); index++) {
        String param = (String) paramList.get(index);

        if (isParsableInt(param)) {
            preparedStatement.setInt(index+1, Integer.parseInt(param));
        } else {
            preparedStatement.setString(index+1, param);
        }
    }

    ResultSet rsReports = preparedStatement.executeQuery();

    buildCollection(rsReports);
    rsReports.close();
    preparedStatement.close();
    conn.close();
}

共 (1) 个答案

  1. # 1 楼答案

    处理strSerialNumberLogicstrCreationDateLogic的方式允许SQL注入攻击。与其直接将它们的值附加到where子句,不如使用条件逻辑来确定要使用的正确条件:

    strWhere.append(" REPORT_FILE_NO ");
    
    switch (strSerialNumberLogic) {
      case "=":
        strWhere.append("= ? ");
        paramList.add(strSerialNumber1);
        break;
      case "!=":
      case "<>":
        strWhere.append("!= ? ");
        paramList.add(strSerialNumber1);
        break;
      case "<":
        strWhere.append("< ? ");
        paramList.add(strSerialNumber1);
        break;
      case "<=":
        strWhere.append("<= ? ");
        paramList.add(strSerialNumber1);
        break;
      case ">":
        strWhere.append("> ? ");
        paramList.add(strSerialNumber1);
        break;
      case ">=":
        strWhere.append(">= ? ");
        paramList.add(strSerialNumber1);
        break;
      case "between":
        strWhere.append("between ? and ? ");
        paramList.add(strSerialNumber1);
        paramList.add(strSerialNumber2);
        break;
      case "not between":
        strWhere.append("not between ? and ? ");
        paramList.add(strSerialNumber1);
        paramList.add(strSerialNumber2);
        break;
      case "is null":
        strWhere.append("is null ");
        break;
      case "is not null":
        strWhere.append("is not null ");
        break;
    }
    

    虽然在附加str[SerialNumber | CreationDate]逻辑以避免注入攻击之前,您可以简单地检查以确保其值有效,但您的代码检查器可能仍会抛出错误,因此最好附加字符串文字而不是变量