我继承了一个非常不安全的 php web 应用程序,有 SQL 注入的历史。我无法立即修复脚本,我宁愿让它们运行以使网站运行,而且首先从 php 端要处理的 php 脚本太多了。但是,我确实可以完全控制服务器和服务器上的软件,包括完全控制 mysql 数据库及其用户。
我们估计总共有 300 个脚本,40 个半私有脚本和 20 个私有/安全脚本。
所以我的问题是,如何最好地保护数据,隐含的假设是来自 php 端的 SQL 注入(例如,在 300 个脚本的列表中的某个地方)是不可避免的?
我的第一份计划是在 mysql 数据库中创建多个不同权限用户的层级。这样,我可以首先保护最需要保护的数据和脚本(“私有/安全”类别),然后保护第二层的数据库表和脚本(“半私有”),最后处理整个 php 应用程序其余部分的安全性(最终保护主要处理“公开”信息的数据库表,例如,即使只是查看主页也需要的内容)。
因此,有 3 个数据库用户(公共、半私有和安全),每个用户分别连接三个不同的脚本组(安全脚本、半私有脚本和公共脚本)。这样,我可以阻止所有从“公共”或“半私有”访问“安全”,以及从“公共”访问“半私有”。还有其他我应该考虑的替代方案吗?如果分层访问系统是可行的方法,那么什么方法最好?
答案1
简单的答案是“您无法真正在数据库级别防止 SQL 注入”。一旦他们连接到数据库并手头有查询,您的数据库就会执行它 - 如果有人在该 SQL 中注入恶意代码,您所能希望做的最好的事情就是减轻他们可能造成的损害。
在减轻损害方面,您已经描述了一个很好的方法:限制每个脚本使用一个数据库用户帐户,该帐户仅限于该脚本所需的最低访问权限(选择、插入、更新、删除以及仅限于脚本所需的特定表子集)必须触摸)。
这并不能保护您的数据库免受 SQL 注入攻击——它只是根据攻击者入侵的脚本限制了攻击者可以窃取(或破坏)的数据量。一个坚定的攻击者可能会首先攻击“有趣的”脚本,因为这些脚本中首先包含他们想要的有用数据。
对于不可预见的问题,将用户角色分开可能只会提供最小的安全增益(如果您有大量复杂的跨表查询和执行多项操作的脚本),但存在严重破坏的风险(尤其如果您有大量执行多项操作的复杂跨表查询脚本)。
值得注意的是,在这个级别审核数据库可能会花费与用适当的参数化查询替换所有当前调用(这使得 SQL 注入攻击变得困难或不可能)一样多的时间(如果不是更多的话)。
答案2
我建议你看看 PHP-IDShttp://phpids.org/。它不会替代保护脚本,也不会阻止所有攻击,但如果必须使用安全创可贴,它确实是一种极好的创可贴。它会挫败那些方便黑客,让他们转向下一个目标。它不会阻止任何下定决心的人。
它将尽力猜测:
- 跨站脚本
- SQL 注入
- 已知的 PHP 漏洞
- 隐藏不同格式的数据
与 mod_security 结合将会有很大帮助。
您的分区策略 100% 正确。但是,请超越 SQL 注入进行思考,因为如果存在 SQL 注入,则可能存在其他类型的攻击。例如特权提升或会话劫持?您可能会发现分区比最初想象的要难,具体取决于网站设计的性质。
最终,只需要咬紧牙关,重新编码即可。
答案3
mod_security对于 Apache 或 IDS/IPS 硬件防火墙模块将对请求进行分析,阻止潜在的 SQL 注入。但我相信其他评论者会详细解释风险。
答案4
您可以(如果您有才华、时间或资源)编写一个位于数据库和 PHP 脚本之间的数据库代理,并过滤掉可疑的 SQL 查询。如果所有或大多数 PHP 脚本都调用相同的数据库 API 库,那么我建议在那里实现过滤器。一定要创建补丁文件(使用 diff),这样如果您的 PHP DB API 更新,您可以重新应用更改。