之情况:
每次用户点击Java“全部更新”按钮时,我有大约50个表,我希望能够从中提取数据并刷新本地数据库。 我无法写入远程数据库,或者我只是使用预准备语句或存储过程创建视图。
为每个表创建自定义预准备语句似乎很难维护,但我也不想让我的代码容易受到SQLInjection的攻击。
为了降低风险,我有一个表名称的白名单(从本地数据库派生),有限的字符串长度,指定的表(数据和日期),并将标记table_name添加到字符串连接中。
我希望通过添加标记字段,大多数SQLinjections都会因语法错误而失败。这些将通过尝试捕获处理并且伤害不能造成伤害(可能是错误的)。
虽然可以更改表名,但我不太关心,因为它必须是具有适当结构的合法表,并且我仍然抓住所有表。
问题:
使用下面编写的声明时,我应该考虑哪些其他SQL注入问题?
List<String> tableNamesWhiteList;
...
for (String t:tableNamesWhiteList)
{
if(t.length < 30)
{
try{
String stm = "select '"+t+"' as table_name, data, date from " + t +" where data = ?";
pst = con.prepareStatement(stm);
pst.setInt(1, 100);
rs = pst.executeQuery();
....
希望这是有道理的
答案 0 :(得分:0)
我将通过指出我不是安全分析师来说明我要说的话。
我不认为你在这里所做的有效或必要。首先,SQL注入依赖于解析器读取到第一个有效SQL语句的末尾并在继续之前执行它。因此,如果上述代码完全容易受到的影响,(我不会认为它是,但我会在一瞬间覆盖它),您的查询
select '"+t+"' as table_name, data, date from " + t +" where data = ?
可以通过将t
设置为等于
1' from pg_users; drop table pg_users;
并且解析器将执行SELECT
,然后执行DROP
,然后阻塞AS
,但到那时为时已晚。这就是SQL注入的工作原理。
但是,您使用预准备语句这一事实意味着整个查询字符串必须在执行任何操作之前从一端解析到另一端,并且任何尝试通过{{1几乎肯定会在查询结束时留下无效语法,这会在执行任何解析之前阻塞解析器。即使不是这种情况,您的表名也来自您自己的代码,从预设列表中挑选出来,如果这些代码遭到入侵,您担心的问题比SQL注入要大。
编写安全代码是好的,但是对代码进行装饰会使代码变得缓慢且难以维护,并且很少被证明是合理的。
但是,您可能会考虑使用的一种替代方案,用于几年前我工作的商业产品。另一种方法是将50个表的查询存储在另一个表中,可能由表名索引。代码可能如下所示:
t