如何解决通过替换子字符串形成查询部分时的SQL注入问题?

How to solve SQL injection issue when the part of query is formed by replacing substring?

提问人:Shankar 提问时间:4/26/2023 最后编辑:Shankar 更新时间:4/26/2023 访问量:115

问:

在我的 Java 类中,我有这样的方法。当我运行静态代码分析时,我在 sql.replaceAll 行中获得 sql 注入。 值如下所示。如何解决此问题?在我看来,我们不能在这里使用 PreparedStatement。studentFilterschoolName = 'ABCD' AND state = 'TEXAS'

private Long getStudentCount(String studentFilter) {
private final NamedParameterJdbcTemplate template; //This is declared at class level
private static final String sql = "select count(name) from student 
                                   wheree marks > 90 AND
                                   dateOfBirth = :dob AND
                                   ( --STUDENT_CONFIG--)";
MapSqlParameterSource sqlParams= new MapSqlParameterSource ();
sqlParams.addValue("dob", "19900101");

return template.queryForObject(sql.replaceAll("--STUDENT_CONFIG--", studentFilter, sqlParams, Long.class)

}
java sql 注入

评论

0赞 Federico klez Culloca 4/26/2023
请编辑您的问题,以包括包含的内容以及您期望生成的查询的内容。studentFilter

答:

0赞 Creed21 4/26/2023 #1

我没有使用过NamedParameterJdbcTemplate,但逻辑应该没问题。

与其用替换方法替换学生配置,不如尝试使用 PreparedStatement / PreparedStatementCreator(在您的例子中)进行参数化查询,这可以防止 SQL 注入

有关该主题的更多信息:https://www.baeldung.com/sql-injection

有关 NamedParameterJdbcTemplate 中的 PreparedStatment 的详细信息: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.html

评论

0赞 Noel Murphy 4/26/2023
不允许他使用 PreparedStatement。
0赞 Noel Murphy 4/26/2023 #2

只需像对 DOB、IE 所做的那样参数化你的学生配置

   sqlParams.addValue("studentConfig", studentFilter);

   return template.queryForObject(sql, sqlParams, Long.class);

评论

2赞 Federico klez Culloca 4/26/2023
当不是一个值而是一个完整的子句时,这是否有效?studentFilterschoolName = 'ABCD' AND state = 'TEXAS'
0赞 Noel Murphy 4/26/2023
@FedericoklezCulloca非常有道理的观点,我从来没有真正考虑过。
1赞 ursa 4/26/2023 #3

你不应该使用type for,这将解决你的问题:StringstudentFilter

interface Condition {
    String propertyName();  // Could be checked against explicit list of allowed names
    String operation();     // Could be checked against explicit list of operations
    String expectedValue(); // Could be injected through placeholder
}

List<Condition> studentFilter = ...

for (int i = 0; i < studentFilter.size(); i++) {
    Condition c = studentFilter.get(i);
    sql += " AND " + c.propertyName() + " " + c.operation() + " :placeHolder" + i;
    sqlParams.addValue("placeHolder" + i, c.expectedValue());
}