当前位置: 首页 > 知识库问答 >
问题:

prepared语句中动态where条件的SQL注入

夏侯玄天
2023-03-14

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

  1. 序列号-可以是一个值、一个值、一个值或两个值。2.创建日期-可以是一个值、一个值、一个值或两个值
  2. ReportTypeNumbers-可以是一个或一个或两个以上
  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个答案

汪兴旺
2023-03-14

处理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[SerialNumberCreationDate]逻辑的值在追加之前有效,以避免注入攻击,但代码检查器仍然可能引发错误,因此最好追加字符串文本而不是变量

 类似资料:
  • 我正试图为我的mysqli连接编写一个非常小的抽象层,但遇到了一个问题。由于我维护的是较旧的代码,我需要从我的查询中获得一个关联数组,因为这是代码设置的方式,因此一旦这样做了,我的工作就少了...这个函数可以处理各种查询(不仅仅是选择)... 我写的函数是这样的: 添加的问题 仅仅为了保留关联数组返回,这样的开销是不是太大了?是否应该改用?

  • 问题内容: 我有以下查询: 这返回 我将如何使它工作?说参数是否为“有效”,则返回具有以下条件的记录? 问题答案: 您可以使用另一种方法:

  • 问题内容: 我有一个执行查询的SQL Server 2005存储过程。该存储过程采用三个参数。参数如下: @StateID为int, @ CountyID为int, @ CityID为int 这些参数用于查询客户列表。如果参数值不为null,我基本上想做一个“ AND”。但是,我目前无法执行if- else。如果参数值不为null,如何添加这些子句。换一种说法: 问题答案: 加上一些OR语句: 对

  • 问题内容: 我正在创建一个需要条件子句的SQL查询。 应该是这样的: 上面的查询不起作用。这是不正确的语法,还是我不知道的另一种方式来做到这一点? 我不想使用动态SQL,是否还有其他方法,还是必须使用类似的解决方法,例如对不同的子句使用和使用相同的查询? 问题答案: 试试这个 您可以在此处阅读有关条件WHERE的更多信息。

  • 根据给定的表数据,第三行中的非空字段是“field1”和“field3”。因此WHERE子句将是: 我如何编写一个具有动态WHERE子句的通用SQL来满足这个需求?

  • 我对where条件、order by和limit有一个查询。我使用准备好的语句来设置where条件和限制。当前,我使用字符串append作为order,从而导致SQL注入漏洞。