SQL-инъекция для Dynamic, где условия в подготовленном выражении - PullRequest
0 голосов
/ 27 ноября 2018

В моем приложении мы собираем некоторые пользовательские входные данные из пользовательского интерфейса и на основе этих значений мы генерируем динамические 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();
}

1 Ответ

0 голосов
/ 28 ноября 2018

То, как вы обрабатываете strSerialNumberLogic и strCreationDateLogic, допускает атаку 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]Логика действительна перед ее добавлением, чтобы избежать атак внедрения, ваша программа проверки кода, скорее всего, все равно выдаст ошибку, поэтому лучше добавлять строковые литералы вместо переменных.

...