防御插入 SQL 注入攻击
所以我们有一个自定义记录器(真的想使用 Log4Net,只是不适用于这种情况)。从配置文件中,您可以配置要插入的表的名称。
我正在参数化插入语句,但可配置的表名称将在插入语句中使用,这是潜在的攻击向量。下面是将要构建的语句的示例:
"insert into " + theTableName + " (static column list) values(parameterized list of values)"
因此,我插入的值是参数化的,并且非常安全,它是可能包含讨厌内容的 theTableName。
我的问题是,我可以做什么来清理表名?我认为攻击者注入的代码的性质必须与普通代码有所不同。 -- 而不是勾选,您可能会用“表名()值();做一些坏事-
(或者类似的事情,我想)来关闭语句。为此,我正在考虑检查“;”和“--”
谁能建议一个更好的方法来清理它(这将与 Oracle 和 SQL Server 一起使用)
So we have a custom logger (really wanted to use Log4Net, just wouldn't work for this case). From a config file, you can configure the name of the table that will be inserted into.
I am parameterizing the insert statement, but the configurable table name will be used in an insert statement, and it's a potential vector for attack. Here's an example of the statement that will be built:
"insert into " + theTableName + " (static column list) values(parameterized list of values)"
So my inserted values are parameterized, and pretty safe, it's theTableName that could contain nasties.
My question is, what can I do to sanitize the table name? I think the nature of the code an attacker would inject would have to be a little different from the garden-variety. -- instead of a tick, you would potentially close off the statment with "table name() values(); do something bad --
(or something like that, I suppose). To that end, I was thinking about checking for the ";", and the "--".
Can anyone suggest a better way to sanitize this? (this will be used with Oracle and SQL server)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
但这仍然不能保证您免受 UNION 攻击(以及其他几种攻击)的侵害。如果您知道允许什么,最好做一些白名单检查拉丁字母或类似的字母。
其他要检查的字符是
和 空格。
That still doesn't keep you safe from UNION-attacks (and several more). Best do some whitelist-check for latin letters or similiar if you know what's allowed.
Other characters to check for would be
and whitespace.
我认为您有一个潜在的更大问题,即用户可以指定一个语法上安全且有效的表名,而数据库中根本不存在该表名。
因此,我会这样做:
仅在加载配置文件时构建一次 INSERT 字符串(包括表名)。
通过检查系统元数据来验证当时的表名,以确保它是一个真实、有效的表。
此时,您可以警告用户日志记录已关闭,因为数据库中不存在表“theTableName”。
I think you have a potentially bigger problem, which is that the user could specify a syntactically safe and valid table name that simply doesn't exist in the database.
Therefore, I'd do this:
Build the INSERT string (including the table name) only once, when you load the config file.
Verify the table name at that time by checking the system metadata to ensure that it's a real, valid table.
At that time you can warn the user that logging is off because the table "theTableName" does not exist in the database.
为什么不对存储表名
theTableName
的行使用theTableID
数字ID 值。您可以将此数字 ID 值存储在用户 PC 上的配置文件中,并将其传递到应用程序中。然后,您可以通过参数化查询查找它,然后将实际的字符串表名称连接到查询中。这样就安全了。why not use a
theTableID
numeric ID value to a row where you store a table nametheTableName
. You can store this numeric ID value in the config file on the user's PC and pass it into the application. Then you can look it up, via a parametrized query, and then concatenate the actual string table name into the query. That will be safe.对我来说,显而易见的解决方案是首先使用静态 SQL 验证将在动态 SQL 中使用的表名:
由于此查询绑定变量而不是连接变量,因此它应该不受 SQL 注入的影响。如果查询返回一条记录则继续,否则作为错误处理。
The obvious solution to me would be to validate the table name that you're going to use in the dynamic SQL using static SQL first:
Since this query binds the variable rather than concatenating it, it should be immune to SQL injection. If the query returns a record then continue, otherwise handle it as an error.
我想主要问题是为什么 theTableName 变量甚至暴露给使用日志记录页面的人。
除此之外,白名单检查要么针对一组值数组,要么针对通过查询系统目录中的表名并将它们转储到数组中而动态创建的一组值,然后只需在数组上执行 .Contains(theTableName) 即可或任何与您选择的语言相当的内容可能是最安全的方法。
I guess the main question is why theTableName variable is even being exposed to the person using the page that the logging is for.
Barring that, a whitelist check either against a set array of values or against a set that you create on the fly by querying the system catalog for table names and dumping them into an array and thing just doing a .Contains(theTableName) on the array or whatever the equivalent for your language of choice is probably the safest way to go.