PreparedStatement的使用;可能容易受到 SQL 注入(使用 JDBC)
This use of PreparedStatement; can be vulnerable to SQL injection (with 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 查询有什么问题以及如何解决这个问题?
漏洞在于您使用 String.format
将内容注入查询字符串。如果 values
/tableName
和 jdbcUsernameMaster
、key
和 plotFkMasterPublicList
的值来自不受信任的来源,那么这可能是 [=21 的潜在来源=]注入.
要解决此问题,您需要不使用 String.format
,而是使用静态查询字符串,或者您需要确保您的值不是来自不受信任的来源(例如用户输入、外部服务等) ,然后有意识地将警告抑制为误报。
SQL 注入在这种特殊情况下确实很难利用,但如果您知道执行的查询并且 plotFKMAsterPublicList 可以被操纵,您可以创建一个“错误的查询”。
以下是基于您的原始代码的示例:
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)";
List<String> values = Arrays.asList("col1,col2".split(","));
List plotFkMasterPublicList= new ArrayList<>();
plotFkMasterPublicList.add("plot1");
plotFkMasterPublicList.add("plot2");
plotFkMasterPublicList.add("plot3) union all select col1,col2 from user.table union all select col1,col2 from user.table where (1=1 ");
String sqlAllocFormatted = String.format(sqlAlloc,
values.stream().collect(Collectors.joining(",")),
"user" + "." + "table",
plotFkMasterPublicList.stream()
.collect(Collectors.joining(",")));
System.out.println(sqlAllocFormatted);
感谢@MarkRotteveel 的建议,你可以查询任何你想要的,看这些例子:
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)";
List<String> values = Arrays.asList("* from any_table -- col1,col2".split(","));
List plotFkMasterPublicList= new ArrayList<>();
plotFkMasterPublicList.add("plot1");
plotFkMasterPublicList.add("plot2");
String sqlAllocFormatted = String.format(sqlAlloc,
values.stream().collect(Collectors.joining(",")),
"user" + "." + "table",
plotFkMasterPublicList.stream()
.collect(Collectors.joining(",")));
System.out.println(sqlAllocFormatted);
我的 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 查询有什么问题以及如何解决这个问题?
漏洞在于您使用 String.format
将内容注入查询字符串。如果 values
/tableName
和 jdbcUsernameMaster
、key
和 plotFkMasterPublicList
的值来自不受信任的来源,那么这可能是 [=21 的潜在来源=]注入.
要解决此问题,您需要不使用 String.format
,而是使用静态查询字符串,或者您需要确保您的值不是来自不受信任的来源(例如用户输入、外部服务等) ,然后有意识地将警告抑制为误报。
SQL 注入在这种特殊情况下确实很难利用,但如果您知道执行的查询并且 plotFKMAsterPublicList 可以被操纵,您可以创建一个“错误的查询”。 以下是基于您的原始代码的示例:
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)";
List<String> values = Arrays.asList("col1,col2".split(","));
List plotFkMasterPublicList= new ArrayList<>();
plotFkMasterPublicList.add("plot1");
plotFkMasterPublicList.add("plot2");
plotFkMasterPublicList.add("plot3) union all select col1,col2 from user.table union all select col1,col2 from user.table where (1=1 ");
String sqlAllocFormatted = String.format(sqlAlloc,
values.stream().collect(Collectors.joining(",")),
"user" + "." + "table",
plotFkMasterPublicList.stream()
.collect(Collectors.joining(",")));
System.out.println(sqlAllocFormatted);
感谢@MarkRotteveel 的建议,你可以查询任何你想要的,看这些例子:
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)";
List<String> values = Arrays.asList("* from any_table -- col1,col2".split(","));
List plotFkMasterPublicList= new ArrayList<>();
plotFkMasterPublicList.add("plot1");
plotFkMasterPublicList.add("plot2");
String sqlAllocFormatted = String.format(sqlAlloc,
values.stream().collect(Collectors.joining(",")),
"user" + "." + "table",
plotFkMasterPublicList.stream()
.collect(Collectors.joining(",")));
System.out.println(sqlAllocFormatted);