首页 > 解决方案 > 这种使用 PreparedStatement;易受 SQL 注入攻击(使用 JDBC)

问题描述

我的 sql 查询如下所示:

String sqlAlloc = " select %1$s from %2$s "
  + "where plot_fk in (%3$s) and plot_fk between ? and ? "
  + "and f001=? "
  + "and repdate=TO_CHAR(TO_DATE(?,'YYYYMMDD'), 'DD-Mon-YY') "
  + "and reportname = ? and change_status in (0,2,6,8,9)";
if (!cond.isEmpty()) {
                sqlAlloc += " and C007=?";
            }
if (tableName.getKey().equals(ALLOC_PENSIONFUNDS)) {
  sqlAlloc += " group by REPDATE, F001, C007, REPORTNAME, COLNAME, ROWNAME";
            }
List<String> values = Arrays.asList(tableName.getValue().split(","));
String sqlAllocFormatted = String.format(sqlAlloc,
  values.stream().collect(Collectors.joining(",")),
  jdbcUsernameMaster + "." + key,
  plotFkMasterPublicList.stream()
    .collect(Collectors.joining(",")));
try (final Connection conn = ds.getConnection();
     final PreparedStatement stmtAlloc =
       conn.prepareStatement(sqlAllocFormatted);) {
  ...

当我用 sonarqube 扫描我的代码时,我得到以下消息:PreparedStatement 的使用;易受 SQL 注入攻击(使用 JDBC)

我真的不明白 sql 查询有什么问题以及如何解决这个问题?

标签: javamysqlsqloracleprepared-statement

解决方案


该漏洞在于您正在使用String.format将内容注入查询字符串的事实。如果values/tableNamejdbcUsernameMaster,key的值plotFkMasterPublicList来自不受信任的来源,那么这可能是 SQL 注入的潜在来源。

要解决这个问题,您要么不需要使用String.format, 而是使用静态查询字符串,或者您需要确保您的值不是来自不受信任的来源(例如用户输入、外部服务等),然后有意识地将警告抑制为 false -积极的。


推荐阅读