我在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中是否有类似的函数。非常感谢任何帮助。
答案 0 :(得分:2)
我同意你遵循这些指导原则的其他答案:
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.)
使用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注入漏洞。