防御与插入 SQL 注入攻击
Posted
技术标签:
【中文标题】防御与插入 SQL 注入攻击【英文标题】:Defending vs an Insert SQL Injection attack 【发布时间】:2011-10-25 20:43:26 【问题描述】:所以我们有一个自定义记录器(真的很想使用 Log4Net,只是不适用于这种情况)。从配置文件中,您可以配置要插入的表的名称。
我正在参数化插入语句,但可配置的表名将用于插入语句,它是潜在的攻击媒介。这是将要构建的语句的示例:
"insert into " + theTableName + " (static column list) values(parameterized list of values)"
所以我插入的值是参数化的,而且非常安全,它是 theTableName 可能包含讨厌的东西。
我的问题是,我能做些什么来清理表名?我认为攻击者注入的代码的性质必须与普通代码略有不同。 -- 你可能会用 "table name() values(); 做坏事来关闭语句,而不是打勾 --
(或者类似的东西,我想)。为此,我正在考虑检查“;”和“--”。
谁能建议一个更好的方法来清理这个? (这将与 Oracle 和 SQL 服务器一起使用)
【问题讨论】:
表名从何而来?如果它是只有你自己定义的东西,那么它就像你想要的一样安全。 值theTableName
是全部还是部分源自您的应用程序代码之外?
@Marc B tableName 可以在 app.config 中指定,因此如果它安装在用户的桌面上,他们可以对其进行操作。 (对于非 .net 的人——想想 .ini 文件)
然后将theTableName
与预定义的字符串进行比较
【参考方案1】:
这仍然不能保护您免受 UNION 攻击(以及更多攻击)。如果你知道什么是允许的,最好做一些白名单检查拉丁字母或类似的。
要检查的其他字符是
()`"'
和空格。
【讨论】:
【参考方案2】:我认为您可能有一个更大的问题,即用户可以指定一个在数据库中根本不存在的语法安全且有效的表名。
因此,我会这样做:
仅在加载配置文件时构建一次 INSERT 字符串(包括表名)。
通过检查系统元数据来验证当时的表名,以确保它是真实有效的表。
此时您可以警告用户日志记录已关闭,因为数据库中不存在表“theTableName”。
【讨论】:
【参考方案3】:为什么不对存储表名theTableName
的行使用theTableID
数字ID 值。您可以将此数字 ID 值存储在用户 PC 上的配置文件中,并将其传递给应用程序。然后您可以通过参数化查询进行查找,然后将实际的字符串表名连接到查询中。这样就安全了。
【讨论】:
【参考方案4】:对我来说显而易见的解决方案是首先使用静态 SQL 验证您将在动态 SQL 中使用的表名:
select * from sys.tables where name = @thetablename
由于此查询绑定变量而不是连接变量,因此它应该不受 SQL 注入的影响。如果查询返回一条记录则继续,否则作为错误处理。
【讨论】:
【参考方案5】:我想主要问题是为什么 TableName 变量甚至会暴露给使用日志记录所针对的页面的人。
除此之外,白名单检查要么针对一组值,要么针对您通过查询系统目录中的表名并将它们转储到一个数组中动态创建的集合,然后执行 .Contains(theTableName)在数组上或任何与您选择的语言等效的东西可能是最安全的方法。
【讨论】:
以上是关于防御与插入 SQL 注入攻击的主要内容,如果未能解决你的问题,请参考以下文章