清理MySQL存储过程参数

时间:2017-11-01 19:59:55

标签: mysql stored-procedures sql-injection

我正在研究一个基于输入参数值动态生成查询的存储过程。 sp使用mysql中的CONCAT()函数来构建查询。其中一个参数允许用户输入搜索字符串作为varchar数据类型。

mysql中是否有类似于php mysql_real_escape_string()的函数可以阻止sql注入攻击?

以下是sp正在做的事情的一个例子:

  

//尝试发布代码。继续被拒绝。不告诉我为什么。   enter image description here

2 个答案:

答案 0 :(得分:3)

永远不要使用CONCAT()函数来构建查询。

使用。编写。语句。

PREPARE stmt1 FROM 'SELECT * FROM whatever WHERE something LIKE ?';
EXECUTE stmt1 USING @search_parameter;
DEALLOCATE PREPARE stmt1;

答案 1 :(得分:3)

重新评论:

  

我同意你的意见,但是你如何根据输入在准备好的声明中添加特定部分。例如,如果参数_A和_B可用,那么加入另外两个表并包含WHERE语句?然后知道正在运行预处理语句的查询版本,以了解哪些参数需要绑定?

有时您必须使用条件代码块:

CREATE PROCEDURE MyProc(IN _A INT, IN _B INT)
BEGIN
  IF _A IS NOT NULL AND _B IS NOT NULL
    PREPARE stmt1 FROM 'SELECT * FROM MyTable WHERE A = ? AND B = ?';
    SET @A = _A, @B = _B;
    EXECUTE stmt1 USING @A, @B;
    DEALLOCATE PREPARE stmt1;
  ELSEIF _A IS NOT NULL
    PREPARE stmt1 FROM 'SELECT * FROM MyTable WHERE A = ?';
    SET @A = _A;
    EXECUTE stmt1 USING @A;
    DEALLOCATE PREPARE stmt1;
  ELSEIF _B IS NOT NULL
    PREPARE stmt1 FROM 'SELECT * FROM MyTable WHERE B = ?';
    SET @B = _B;
    EXECUTE stmt1 USING @B;
    DEALLOCATE PREPARE stmt1;
  END
END

对于具有条件LIMIT和OFFSET的示例,您可以更简单地执行此操作。输入参数没有SQL注入风险,这些参数受限于INT数据类型。然后,您可以使用COALESCE()来使用一些合理的值来默认变量。

CREATE PROCEDURE MyProc(INT _quick_search VARCHAR(50),
  IN _limit INT, IN _offset INT)
BEGIN
  SET @LIMIT = COALESCE(_limit, 1);
  SET @OFFSET = COALESCE(_offset, 0);

  PREPARE stmt1 FROM 'SELECT ...blah blah... LIMIT ? OFFSET ?';
  EXECUTE stmt1 USING @LIMIT, @OFFSET;
  DEALLOCATE PREPARE stmt1;
END

我同意@YourCommonSense的声明,即存储过程不是最好的解决方案。 MySQL对存储过程的实现是原始的,难以使用。我在Stack Overflow上看到很多关于如何在MySQL存储过程中执行某些任务的问题,这让我每次都感到畏缩。

最好使用几乎任何其他脚本语言,而不是使用MySQL存储过程。