ResultSet update{ColumnType} 方法容易受到 SQL 注入的攻击吗?
Are ResultSet update{ColumnType} methods vulnerable to SQL injection?
AppScan source 进行的安全扫描在以下代码的 uprs.updateString
行标记必须验证输入 (Validation.Required):
PreparedStatement statement =
conn.prepareStatement (query, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
...
ResultSet uprs = statement.executeQuery ();
...
// Update DB ColumnA with input coming from client
uprs.updateString ('ColumnA', unvalidatedUserInput);
...
// Updates the underlying database
uprs.updateRow();
我认为这背后的意图是避免 SQL 注入攻击,但我不确定在那种情况下是否可行。
问题:SQL 注入攻击是否可能通过这些 JDBC 方法进行? JDBC 是如何在幕后实现的?这会是 AppScan 报告的另一个误报吗?
我不确定 bluemix-app-scan,但我在这里提供我的解释。 (这是我根据以下测试和粘贴的代码做出的假设)
我运行一个测试代码来检查这个(在H2 DB)
testName 字符串的值:(select 'sqlInjection' from dual)
使用 createStatement
(不安全):
String query = "update TEST_TABLE set TEST_CHAR = " + testName + " where ID = 1";
Statement statement = connection.createStatement();
statement.executeUpdate(query);
输出: TEST_CHAR 在数据库中是 sqlInjection.
使用 createStatement
的 ResultSet
(在 H2 数据库中安全):
String query = "select * from TEST_TABLE where ID = 1";
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet executeQuery = statement.executeQuery(query);
executeQuery.next();
executeQuery.updateString("TEST_CHAR", testName);
executeQuery.updateRow();
输出: 令人惊讶的是 TEST_CHAR 在 DB 中是 (select 'sqlInjection' from dual) .
使用 PreparedStatement
(安全):
String query = "update TEST_TABLE set TEST_CHAR = ? where ID = 1";
PreparedStatement statement = connection.prepareStatement(query);
statement.setString(1, testName);
statement.executeUpdate();
输出: 预期 - DB 中的 TEST_CHAR 是 (select 'sqlInjection' 来自 dual).
使用 ResultSet
of prepareStatement
(在 H2 数据库中安全):
String query = "select * from TEST_TABLE where ID = 1";
PreparedStatement statement = connection.prepareStatement(query, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet uprs = statement.executeQuery();
uprs.next();
uprs.updateString("TEST_CHAR", testName);
uprs.updateRow();
输出: 预期 - DB 中的 TEST_CHAR 是 (select 'sqlInjection' 来自 dual).
返回问题:
Are SQL Injection attacks possible through these JDBC methods?
可能。 这取决于您使用的数据库驱动程序。
如何? :
我的结果集更新中 SQL 注入失败的原因是因为 H2 数据库在调用 ResultSet.updateRow()
时在内部使用 PreparedStatement
更新行。
public void updateRow(Value[] current, Value[] updateRow) throws SQLException {
StatementBuilder buff = new StatementBuilder("UPDATE ");
...
buff.append(" SET ");
appendColumnList(buff, true);
...
appendKeyCondition(buff);
PreparedStatement prep = conn.prepareStatement(buff.toString());
...
for (int i = 0; i < columnCount; i++) {
...
v.set(prep, j++);
}
setKey(prep, j, current);
int count = prep.executeUpdate();
...
}
我不确定 java 中的所有数据库驱动程序是否都使用 preparedStatement
实现了 updateRow()
方法。但是很明显,这留给了驱动程序,如果 bluemix 建议您在此处添加验证,我建议您遵循 :)
How does JDBC implements this under the scenes?
好吧,如上所示,这是特定于驱动程序的。然而,关于 PreparedStatement
如何处理它超过 here 有一个很好的解释。
Would this be another false positive reported by AppScan?
我不认为这是误报(但在像 H2 DB 这样的情况下它是)但你永远不会知道是否所有数据库驱动程序都安全地实现了这一点。
编辑-
甚至 PostgreSQL 和 MySQL 也使用 PreparedStatement 来处理这个问题。
public synchronized void updateRow() throws SQLException
{
...
updateStatement = ((java.sql.Connection) connection).prepareStatement(updateSQL.toString());
...
updateStatement.executeUpdate();
...
}
AppScan source 进行的安全扫描在以下代码的 uprs.updateString
行标记必须验证输入 (Validation.Required):
PreparedStatement statement =
conn.prepareStatement (query, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
...
ResultSet uprs = statement.executeQuery ();
...
// Update DB ColumnA with input coming from client
uprs.updateString ('ColumnA', unvalidatedUserInput);
...
// Updates the underlying database
uprs.updateRow();
我认为这背后的意图是避免 SQL 注入攻击,但我不确定在那种情况下是否可行。
问题:SQL 注入攻击是否可能通过这些 JDBC 方法进行? JDBC 是如何在幕后实现的?这会是 AppScan 报告的另一个误报吗?
我不确定 bluemix-app-scan,但我在这里提供我的解释。 (这是我根据以下测试和粘贴的代码做出的假设)
我运行一个测试代码来检查这个(在H2 DB)
testName 字符串的值:(select 'sqlInjection' from dual)
使用
createStatement
(不安全):String query = "update TEST_TABLE set TEST_CHAR = " + testName + " where ID = 1"; Statement statement = connection.createStatement(); statement.executeUpdate(query);
输出: TEST_CHAR 在数据库中是 sqlInjection.
使用
createStatement
的ResultSet
(在 H2 数据库中安全):String query = "select * from TEST_TABLE where ID = 1"; Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet executeQuery = statement.executeQuery(query); executeQuery.next(); executeQuery.updateString("TEST_CHAR", testName); executeQuery.updateRow();
输出: 令人惊讶的是 TEST_CHAR 在 DB 中是 (select 'sqlInjection' from dual) .
使用
PreparedStatement
(安全):String query = "update TEST_TABLE set TEST_CHAR = ? where ID = 1"; PreparedStatement statement = connection.prepareStatement(query); statement.setString(1, testName); statement.executeUpdate();
输出: 预期 - DB 中的 TEST_CHAR 是 (select 'sqlInjection' 来自 dual).
使用
ResultSet
ofprepareStatement
(在 H2 数据库中安全):String query = "select * from TEST_TABLE where ID = 1"; PreparedStatement statement = connection.prepareStatement(query, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet uprs = statement.executeQuery(); uprs.next(); uprs.updateString("TEST_CHAR", testName); uprs.updateRow();
输出: 预期 - DB 中的 TEST_CHAR 是 (select 'sqlInjection' 来自 dual).
返回问题:
Are SQL Injection attacks possible through these JDBC methods?
可能。 这取决于您使用的数据库驱动程序。
如何? :
我的结果集更新中 SQL 注入失败的原因是因为 H2 数据库在调用 ResultSet.updateRow()
时在内部使用 PreparedStatement
更新行。
public void updateRow(Value[] current, Value[] updateRow) throws SQLException {
StatementBuilder buff = new StatementBuilder("UPDATE ");
...
buff.append(" SET ");
appendColumnList(buff, true);
...
appendKeyCondition(buff);
PreparedStatement prep = conn.prepareStatement(buff.toString());
...
for (int i = 0; i < columnCount; i++) {
...
v.set(prep, j++);
}
setKey(prep, j, current);
int count = prep.executeUpdate();
...
}
我不确定 java 中的所有数据库驱动程序是否都使用 preparedStatement
实现了 updateRow()
方法。但是很明显,这留给了驱动程序,如果 bluemix 建议您在此处添加验证,我建议您遵循 :)
How does JDBC implements this under the scenes?
好吧,如上所示,这是特定于驱动程序的。然而,关于 PreparedStatement
如何处理它超过 here 有一个很好的解释。
Would this be another false positive reported by AppScan?
我不认为这是误报(但在像 H2 DB 这样的情况下它是)但你永远不会知道是否所有数据库驱动程序都安全地实现了这一点。
编辑-
甚至 PostgreSQL 和 MySQL 也使用 PreparedStatement 来处理这个问题。
public synchronized void updateRow() throws SQLException
{
...
updateStatement = ((java.sql.Connection) connection).prepareStatement(updateSQL.toString());
...
updateStatement.executeUpdate();
...
}