簡體   English   中英

預准備語句中的Dynamic where條件的SQL注入

[英]SQL injection for Dynamic where conditions in prepared statement

在我的應用程序中,我們從UI收集一些用戶輸入,並基於這些值生成具有不同“ Where”條件的動態SQL,以查詢數據。 發現該代碼段具有一些SQL注入缺陷。

我無法重新排列此代碼以防止出現這種情況。 任何建議都會有所幫助。

我的應用程序有四個輸入參數,

  1. 序列號-可以是一個或一個或兩個值。2.創建日期-可以是一個或一個或兩個值。
  2. ReportTypeNumbers-可以是一個或一個或兩個以上
  3. reportTitleNames-可以是一個或一個或兩個以上

基於這些輸入值,我正在為准備好的語句構建動態“哪里”條件。 此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();
}

處理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] Logic值之前先進行檢查以確保其值有效,以避免注入攻擊,但您的代碼檢查器可能仍會引發錯誤,因此最好附加字符串文字而不是變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM