我有一个项目(私有,ASP.net网站,密码用https保护),其中一个要求是用户能够输入将直接查询数据库的Sql查询。我需要能够允许这些查询,同时防止它们对数据库本身造成损害,以及访问或更新它们无法访问/更新的数据。
我已经提出了以下实施规则:
我错过了什么吗?
目标是用户能够以他们认为合适的任何方式查询/更新他们有权访问的表,并防止任何意外或恶意企图破坏数据库。 (并且由于要求用户生成sql,我无法使用我所知的任何内置工具对查询进行参数化或清理它。)
答案 0 :(得分:16)
这是一个坏主意,而不仅仅是从注射预防的角度来看。对于一个不知道更好的用户而言,如果不小心运行会占用所有数据库资源(内存/ CPU)的查询,实际上很容易,从而导致拒绝服务攻击。
如果必须允许这样做,最好为这些查询保留一个完全独立的服务器,并使用复制使其非常接近生产系统的精确镜像。当然,这不适用于您的UPDATE要求。
但我想再说一遍:这不行。如果用户可以运行即席查询,则无法保护数据库。
答案 1 :(得分:4)
这个东西怎么样,想想选择是EXEC
select convert(varchar(50),0x64726F70207461626C652061)
答案 2 :(得分:4)
我的直觉反应是,您应该专注于设置帐户权限并尽可能严格授予。彻底查看您的RDBMS安全文档,可能有一些您不熟悉的功能会证明是有帮助的(例如,Oracle的虚拟专用数据库,我相信在这种情况下可能会有用)。
特别是,您的想法是“验证(使用正则表达式)用户有权访问正在查询/更新的表,包含在连接中等”。听起来你会试图重新实现已经内置到数据库中的安全功能。
答案 3 :(得分:3)
您所缺少的是攻击者在您的应用程序中找到漏洞的独创性。
如果你允许的话,我几乎可以保证你无法关闭所有的洞。甚至可能存在您不知道的数据库引擎中的错误,但是他们这样做允许您认为安全的SQL语句可以破坏系统中的破坏。
简而言之:这是一个非常糟糕的主意!
答案 4 :(得分:3)
嗯,你已经有足够的人告诉你“不要这样做”,所以如果他们无法阻止你,这里有一些想法:
包含好,不要试图排除不良
(我认为正确的术语是白名单 vs 黑名单)
通过这个,我的意思是不要寻找邪恶或无效的东西来抛弃(有太多的方式可以写出或伪装),而是寻找有效的东西包括并抛弃其他一切。
您在另一条评论中已经提到过,您正在寻找一个用户友好的表名列表,并替换实际的架构表名。这就是我所说的 - 如果你打算这样做,那么也要用字段名称来做。
我仍然倾向于某种形式的图形用户界面:选择要在此处查看的表格,选择要在此处查看的字段,使用一些下拉菜单来构建where子句,等等。痛苦,但仍然可能更容易。
答案 5 :(得分:2)
正如其他人所说,让最终用户这样做并不是一个好主意。我怀疑要求并不是用户真正需要临时SQL,而是一种以最初没有预期的方式获取和更新数据的方法。要允许查询,请按照Joel建议并保留“只读”数据库,但使用报告应用程序(如Microsoft Reporting Services或Data Dynamics Active报告)允许用户设计和运行临时报告。我相信两者都有办法向用户呈现“他们的”数据的过滤视图。
对于更新,它更棘手 - 我不知道现有的工具来做到这一点。一种选择可能是设计您的应用程序,以便开发人员可以快速编写插件以公开新表单以更新数据。该插件需要公开UI表单,用于检查当前用户是否可以执行它的代码,以及用于执行它的代码。您的应用程序将加载所有插件并公开用户有权访问的表单。
答案 6 :(得分:2)
事件看似安全的技术,如Dynamic LINQ, is not safe from code injection issues,您正在谈论提供低级访问。
无论您如何努力清理查询和调整权限,仍然可以通过发送一些CPU密集型查询来冻结您的数据库。
因此,其中一个“保护选项”是显示一个消息框,告诉所有访问受限对象或导致不良副作用的查询将记录在用户的帐户中并立即向管理员报告
另一种选择 - 只是尝试寻找更好的替代方案(即如果您真的需要处理和更新数据,为什么不公开API来安全地执行此操作?)
答案 7 :(得分:1)
一个(可能是矫枉过正的)选项可以使用编译器来减少SQL语言。像使用带有修改后的SQL语法的JavaCC只允许SELECT语句,然后你可能会收到查询,编译它,如果编译它就可以运行它。
对于C#我知道Irony但从未使用它。
答案 8 :(得分:1)
使用更新声明可以造成大量伤害。
我有一个类似于此的项目,我们的解决方案是让用户通过一个非常讨厌的向导,允许他们做出选择,但查询本身是由应用程序代码在幕后构建的。创建非常费力,但至少我们控制了最终执行的代码。
答案 9 :(得分:1)
问题是,您信任您的用户吗?如果您的用户必须登录系统,那么您正在使用HTTPS&采取预防措施防止XSS攻击,然后SQL注入是一个较小的问题。如果您信任合法用户,则在受限制的帐户下运行查询应该足够了。多年来我一直在网上运行MyLittleAdmin并且还没有遇到问题。
如果在正确受限的SQL帐户下运行,则选择convert(varchar(50),0x64726F70207461626C652061)将不会走得太远,您可以通过在数据库请求上设置短暂超时来防止资源占用查询。人们仍然可以做不正确的更新,但那么你回到了信任你的用户吗?
您总是将管理风险附加到网络上的任何数据库,但那就是备份的目的。
答案 10 :(得分:0)
如果他们不必执行真正的高级查询,您可以提供仅允许某些选择的UI,例如带有“更新,删除,选择”的下拉列表,然后下一个ddl将自动填充可用列表表等。类似于sql management studio中的查询生成器。
然后在您的服务器端代码中,您将这些ui元素组转换为sql语句并使用参数化查询来阻止恶意内容
答案 11 :(得分:0)
这是一个非常糟糕的做法。我会创建一些存储过程来处理您想要做的所有事情,甚至是更高级的查询。将它们呈现给用户,让他们选择他们想要的那个,然后传递参数。
我上面的答案也非常好。
答案 12 :(得分:0)
虽然我同意Joel Coehoorn和SQLMenace,但我们中的一些人确实有“要求”。不要让他们发送ad Hoc查询,为什么不创建一个可视化查询构建器,就像在asp.net上找到的MS示例应用程序中那样,或者试试这个link。
我并不反对乔尔提出的观点。他是对的。拥有用户(记住我们在这里谈论用户,他们可能不太关心你想要强制执行什么)抛出查询就像没有“业务逻辑层”的应用程序,更不用说当某些结果不匹配时需要回答的其他问题其他支持申请结果。
答案 13 :(得分:0)
这是另一个例子
黑客不需要知道真正的表名,他/她可以像这样运行无证的procs
sp_msforeachtable 'print ''?'''
而不是打印它将会掉落