【问题标题】:re SQL Injection Attack using MySQL, does this meet baseline requirements? [duplicate]使用 MySQL 进行 SQL 注入攻击,这是否符合基线要求? [复制]
【发布时间】:2011-11-16 21:19:33
【问题描述】:

我有一个单页应用程序,浏览器在其中完成所有逻辑工作。除了初始加载之外,服务器几乎是一个漂亮的数据库接口。

例如,浏览器发送数据字典键、列名/值对以及 SELECT 的 where 子句。服务器将这些部分组装成 SQL,执行查询并回复。新:例如,在 SELECT 中,提取的表名和列来自数据字典 - 浏览器提供数据字典键和 SELECT where 子句。

这种非常开放的环境很容易受到 SQL 注入攻击。目标是防止上述攻击造成的损害。

需要克服的问题

首先,作为discussed,不可能参数化随机SELECT where clause - SELECT 不能使用准备好的语句。

其次,mysqli,用于 MySQL 参数化语句的库,不支持 NULL 或 MySQL 函数,例如,CURRENT_DATE 或 NOW(),如 discussed。

建议的解决方案

首先,如果 SELECT 无法参数化,则由没有 DML 或 DDL 权限的用户执行 SELECT。这将防止 SQL 注入攻击更改数据库。

其次,为mysqli 编写一个包装函数,允许将NULL 和MySQL 函数作为参数传递。这将允许参数轻松地用于所有 DML。

第三,隐藏高度敏感的数据,普通查询或普通用户无法看到或触及这些数据。这会将敏感数据(例如密码)置于攻击范围之外。

第四,编写一个包装顺序来强制执行用户/查询类型关系。这将确保 SELECT 由select 用户执行,例如

努力的结果是here。从逻辑上讲,问题是这种方法能否成功防止 SQL 注入攻击?

未回答的答案

我提出了同样的问题before。由于我的演示工作不佳,收到的答案和 cmets 最终专注于虚假问题,而不是解决(公认的)困难问题 - 这真的有效吗?

作为参考,以下是其中的一些 cmets 和答案。

使用 PDO 的预处理语句

首先,准备好的语句不能用于所有 SELECT - PDO 有什么帮助?其次,mysqli 不接受 NULL 或 MySQL 函数——PDO 有什么帮助?

为什么要重新发明轮子

如果您知道克服这些问题的方法,我真的很想知道 - 这是一个难题。

看不到mysql_real_escape_string()

值应该在传递给数据库查询函数之前进行清理。 mysql_real_escape_string() 是一组可用的消毒功能之一,例如,可以对日期使用不同的消毒剂。

工作量太大

请与我分享您对克服这些问题的任何方法的了解 - 我真的希望有更好的见解。也就是说,从我重新设置整个东西开始,按照我的笔记花了 30 到 45 分钟。此后不会产生时间成本。

我很高兴mysqli

当您无法对 SELECT 进行参数化时,您将如何防止 SQL 注入攻击?您是否希望在更新列时从不使用 NULL?每个人都有自己的毒药,但这些都是我希望解决的问题——而不是忍受。

@Konerack 指出参数数量有限

没错。更改为使用解决问题的eval()(不寒而栗)的代码。需要安全审查。

又是一个问题

这种方法能否在克服无参数化 SELECT 和mysqli 的参数限制的问题的同时防止 SQL 注入攻击?

【问题讨论】:

  • Will this approach protect against SQL Injection Attacks?不,不会。
  • @Johan - 如果它不能保护,我很想听听一个具体的例子,这样我就可以理解它了!
  • 我不知道为什么,但是让浏览器发送动态表/列名是一个糟糕的主意。我不知道您要解决的问题是什么,但这似乎是错误的方法。
  • @N.B. - 所有工作在浏览器中完成!例如,在与用户交互时,浏览器知道我们需要一个员工列表,其中这个和那个。它要求服务器检索它。
  • 那又怎样?浏览器告诉您的服务器“调用存储过程以检索用户数据”而不是“嘿,从 where 中选择 x、y、z”有什么问题?我很抱歉这么说,但你采取了错误的方法。最后,浏览器必须知道它需要发送什么表/列/where子句。因此,它不再需要知道应该调用什么过程来获取相同的数据。你的设计方法是错误的,你看到了一个巨大的限制——清理数据和暴露你的结构。

标签: php mysql security mysqli sql-injection


【解决方案1】:

答案很简单:

对于参数,请使用 PDO 或mysql_real_escape_string()。

对于其他动态 SQL(表名、列名、语法元素)使用白名单。

见:How to prevent SQL injection with dynamic tablenames?

您不能相信浏览器会保持在您在 Javascript 中设置的范围内。这很容易被操纵。因此,您必须将来自该端的所有数据视为不受信任。确保对照允许的关键字列表检查 where 子句中的所有元素。

为此,您将使用:

  1. 检查符号白名单:=, <>, >, LIKE, NULL, IS。
  2. 检查布尔运算符的白名单:AND, OR, XOR, NOT
  3. 所有值都必须正确地包含在单个 ' 引号中,并且您需要通过 mysql_real_escape_string() 提供这些值,以确保没有恶作剧。
  4. 所有不在 (1,2) 中且未用单引号括起来的值都是列名,请对照允许的列名白名单检查它们。
  5. 拒绝所有其他输入。

【讨论】:

  • 我认为你没有读过这个问题!如果 SELECT where clause 无法参数化,如何将其列入白名单?如果mysqli 不能接受 NULL 或 MySQL 函数,PDO 将如何提供帮助?
  • 我读了这个问题。如果您执行select $var FROM table1,则需要根据允许的列名白名单检查 $var。请阅读链接。
  • 已阅读链接 - 干得好!首先,要选择的列不是由浏览器设置的,而是数据字典的一部分,因此不需要白名单。其次,如果where clause不能参数化,那么它就不能被列入白名单,所以我们还是有问题
  • as discussed - 参见示例,例如,“与”不同 - 我仍然正确地维护白名单 where 子句需要完整的 SQL 解析器。请注意,如果查询失败也没关系 - 如果 SQL 注入攻击造成伤害,则不行。
  • @cc 年轻,想想还有另一种方法。 Stackexchange 允许对其数据库进行自定义查询(实际上是它的副本),您必须检查这是如何保护的,只允许访问数据的子集,并且只有 select 应该走很长的路
猜你喜欢
  • 1970-01-01
  • 2014-07-04
  • 2011-03-27
  • 1970-01-01
  • 2012-04-14
  • 1970-01-01
  • 2012-08-01
  • 2019-07-10
相关资源
最近更新 更多