提问人:rz nihar 提问时间:11/27/2018 最后编辑:Scary Wombatrz nihar 更新时间:11/28/2018 访问量:931
预准备语句中动态 where 条件的 SQL 注入
SQL injection for Dynamic where conditions in prepared statement
问:
在我的应用程序中,我们正在从 UI 收集一些用户输入,并基于这些值生成具有不同“Where”条件的动态 SQL 来查询数据。发现该段代码存在一些 SQL 注入缺陷。
我无法重新排列此代码以防止该 flaq。任何建议都会有所帮助。
My Application 接受四个输入参数,
- 序列号 - 可以是一个或无,也可以是两个值 2.创建日期 - 可以是一个或没有,或两个值
- ReportTypeNumbers- 这可以是 1 个或 none,也可以是两个以上
- reportTitleNames - 这可以是 one 或 none,也可以是 two 以上
基于这些输入值,我正在为准备好的语句构建动态“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赞
Sentinel
11/28/2018
#1
您处理并允许 SQL 注入攻击的方式。与其直接将其值附加到 where 子句,不如使用条件逻辑来确定要使用的正确条件:strSerialNumberLogic
strCreationDateLogic
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]逻辑在附加之前是有效的 为了避免注入攻击,代码检查器可能仍会抛出错误,因此最好附加字符串文字而不是变量。
评论