mysql中的任何内置函数,用于清理字符串变量

时间:2016-12-14 04:40:12

标签: mysql escaping

我在MySql中有一个存储过程,输入来自用户。我想避免SQL注入。 在MySql中是否有任何阻止SQL注入的函数,我已经用Google搜索了,但大多数网站都向我展示了My mysql_real_escape_string的MySql。

我想在存储过程级别清理输入变量。我已经使用了预处理语句但仍然在MySql中有任何内置函数来清理给定的字符串。

CREATE PROCEDURE `SP_Xyz` 
(IN _abc varchar(40),
)
BEGIN
   SET @abc = _abc;
   // This might cause sql injection
   SELECT * FROM tbl WHERE col1 = @abc;
   // We must use prepares statements 
   // But is there any mysql builtin function to sanitize input
   # Say SELECT * FROM tbl WHERE col1 = PREVENT_SQL_INJECTION(@abc);
   # In PHP we usually do
   # $name = mysql_real_escape_string($name);
   # mysql_query("SELECT * FROM users WHERE name='{$name}'");
END

所以既然php提供了一个函数,那么在MySql中是否有类似的函数。非常感谢任何帮助。

4 个答案:

答案 0 :(得分:2)

我同意你遵循这些指导原则的其他答案:

  • 只需将变量与过程中的固定查询组合即可。如果查询不是动态的,则变量不会导致SQL注入。
  • 如果查询是动态的,请将PREPARE / EXECUTE与查询参数一起使用。大多数情况下,这是不必要的,但是如果您需要在select-list中使用可选的搜索子句或可选列来形成查询,则可能必须使用动态SQL。

但要直接回答你的问题:是的,MySQL中有一个内置函数可以清理字符串,以便可以安全地插入动态SQL查询而无需使用参数。

QUOTE(str)会返回带引号的字符串,并会转义特殊字符。

mysql> SELECT QUOTE('Don''t!') as _quoted;
+-----------+
| _quoted   |
+-----------+
| 'Don\'t!' |
+-----------+

它类似于PHP PDO::quote()

也就是说,在使用MySQL的16年中,我从未需要使用此功能。使用查询参数准备和执行几乎总是更好。

答案 1 :(得分:1)

编辑 Bill Karwin(正确)指出MySQL QUOTE() 功能。这(我)的答案中的第一个陈述是错误的。我坚持认为我们不需要逃避"在准备好的声明中通过占位符提供的值。

没有内置的SQL函数可以做到这一点。没有必要。

我们可以在预准备语句中使用绑定占位符。例如:

  PREPARE stmt FROM 'SELECT * FROM tbl WHERE col1 = ?';
  EXECUTE stmt USING @abc;
  DEALLOCATE PREPARE stmt;

在这种特殊情况下,不需要使用准备好的声明。在MySQL存储程序中,我们可以在不引入SQL注入漏洞的情况下执行此操作:

  SELECT * FROM tbl WHERE col1 = @abc ;

考虑到问题中的存储过程,我们实际上不需要使用用户定义的变量,我们可以引用参数变量而不将其分配给中间的用户定义变量:

DELIMITER $$

CREATE PROCEDURE `SP_Xyz`(IN _abc varchar(40))
BEGIN
   -- no SQL Injection vulnerability
   SELECT * FROM tbl WHERE col1 = _abc;
END$$

答案 2 :(得分:1)

你问的是一个好问题。在网站安全方面,人们不能总是信任文档甚至是开发良好的产品。您可能希望阻止黑客利用PHP,MySQL或其他系统组件中已知或新发现的安全漏洞。这些被发现,利用,添加到错误列表中,修复并定期部署在新版本中。

对于高吞吐量应用程序,正则表达式匹配是速度问题,确定输入字符串是否在单引号之前插入反斜杠并正确处理utf-8或非法序列的正确方法是尝试一些并观察字符串进入MySQL。这种调查技术可能适合您。 (我不记得它如何记录存储过程I / O.)

  1. 执行以下SQL:set global general_log ='ON';
  2. 提交一个带有单引号的字符串,一些可识别的字符串,如“亚伯拉罕林肯”,以及各种各样的utf-8和非法字符。
  3. 执行以下SQL:显示变量,如general_log%;
  4. 使用一些优秀的程序员工具(例如Cygwin,LINUX,UNIX或Mac上的egrep和vim)找到'Abraham Lincoln',并确切地看到MYSQL收到的SELECT。
  5. 使用以下命令关闭重日志:set global general_log ='OFF';
  6. 使用INSERT和UPDATE更容易,因为您可以使用SELECT来查找数据库存储的内容。

    如果您没有高容量,无论其他人说什么,说什么文档,甚至上面的日志记录结果是什么,都是安全的并使用正则表达式来验证来自的所有输入值的合理性HTTP请求。这是安全架构师的最高规则之一。

    有许多方法可以验证用户字符串,但为了安全起见,必须在可以在模拟浏览期间修改的代码中完成。客户端验证是为了方便用户并减少网络带宽而不是其他方案,但它无法提供安全性。

    由于您使用的是存储过程,因此使用正则表达式对其进行验证可能会很方便。见http://dev.mysql.com/doc/refman/5.7/en/regexp.html。我相信MySQL编译模式所以它很快。您可能希望通过从JavaScript循环运行HTTP(s)事务一百万次来加速测试它。

    将上述MySQL链接中显示的表单中的一个SELECT语句替换为“//这可能导致sql注入”并测试结果。如果你返回零,确保你做了一些聪明的事情,这意味着字符串是不合理的。

    分别使用^和$开头和结尾锚定两侧的正则表达式非常重要。此示例正则表达式可能是电话号码的正常表达式:'^ [0-9a-zA-Z().-] + $'

    您可能希望在上述国际电话号码示例的情况下保留验证范围。

答案 3 :(得分:-1)

你不需要一个。

传递给存储过程的变量并没有字面上粘贴到查询中,这种方式可能会导致编写糟糕的PHP应用程序中的SQL注入漏洞。