对于ASP.NET(针对SQL Server)应用程序内部的一些功能,我们允许员工用户指定WHERE子句。然后将此WHERE子句在代码中附加到系统生成的SELECT语句以检索某些数据。
所以从本质上讲,我们最终得到:
SELECT SomeFields FROM SomeTable WHERE UserEnteredWhere
粗体是系统,斜体是用户。这已经工作了很长时间,并给了我们一些很好的灵活性。
然而,如果用户输入以下内容,显然存在一个很大的问题:
SomeField = 1; DROP TABLE SomeTable;
目前唯一的验证是语句是否以SELECT语言开头,因为我们最终会得到:
SELECT SomeFields FROM SomeTable WHERE SomeField = 1; DROP TABLE SomeTable;
长期解决方案是不允许用户将SQL输入到文本框中,但在短期内我想要支持它。
我能想到的唯一解决方案是在交易中运行每个请求,以确保不会造成长期损害。
有没有人有任何关于如何验证用户输入“where子句”的建议,以确保它在执行之前没有任何DDL内容?
PS。我确实意识到上述情况很糟糕,不应该这样做,但这是我在遗留系统中所拥有的(我没有写),所以请尽量帮助我解决问题,而不是告诉我不要这样做。 : - )
答案 0 :(得分:3)
您知道正确答案 - 您已将应用程序暴露给SQL注入。通常,ad-hoc解决方案不健壮。并且,将该陈述置于交易中并没有帮助。毕竟,commit
可能是其中一个命令。
某些界面具有“执行单个查询”的等效功能。这几乎可以解决您的问题,因为第二个查询会在应用程序中生成错误。
我建议不要在用户生成的条件中允许以下任何字符/单词:
;
update
delete
insert
create
exec
grant
select
(除非您想支持子查询)这可能会在某种程度上限制条件允许的内容。
这不是对注射的保证,而是应该让事情变得更好的事情。
答案 1 :(得分:1)
由于我需要快速修复,我最终最终从SQL Server方面解决了这个问题:
SQL:
CREATE LOGIN MrReadOnly
WITH PASSWORD = 'LetMeIn!';
USE MyDatabase;
CREATE USER MrReadOnly FOR LOGIN MrReadOnly;
GO
EXEC sp_addrolemember N'db_datareader', N'MrReadOnly'