我有一个使用动态SQL的MySQL存储过程。我们选择了DynamicSQL,因为我们有几个具有相似列的表,并且我们正在努力使代码尽可能地可重用。
我担心SQL注入,但标准的攻击字符串似乎对此不起作用。此存储过程易受SQL注入的影响吗?如果是这样,有没有更好的写法?
CREATE DEFINER=CURRENT_USER PROCEDURE `sp_lookup`(IN tableName VARCHAR(256))
BEGIN
SET @sql = CONCAT('SELECT id, name, FROM ', tableName, ' ORDER BY name');
PREPARE stmt FROM @sql;
EXECUTE stmt;
END
存储过程不会添加任何额外的安全性。
它并不阻止SQL注入,您需要使用prepared语句。
另一种方法是使用表白名单,这意味着如果不运行查询,则首先检查表是否与现有表匹配。
但是你不应该这样做。数据库引擎最好有显式语句,这样可以正确地优化它们,而不必在每次调用时重新解析SQL。
表名应该用"ticks"包围,并转义任何ticks,如下所示:
CREATE DEFINER=CURRENT_USER PROCEDURE `sp_lookup`(IN tableName VARCHAR(256))
BEGIN
SET @sql = CONCAT('SELECT id, name FROM `', REPLACE(tableName, '`', '`'), '` ORDER BY name');
PREPARE stmt FROM @sql;
EXECUTE stmt;
END
尽管目前缺乏这些,但你的脆弱性似乎相当低;根据官方文档"准备语句的SQL语法不支持多语句"
孤立地说,是的,这个存储的proc可能有漏洞,但漏洞可能无关紧要。重要的是tablename
参数的值是否来自可靠的来源。
如果您检查其中一个"标准攻击字符串",您会发现攻击者正试图完成您的SQL查询,然后再执行另一个查询。为了做到这一点,攻击者必须能够直接修改拼接到查询中的字符串。
如果您使用此SP的方式使tablename
的值不能被敌对用户直接修改,那么您就不存在SQL注入漏洞。
我希望这是有道理的。