此 MySQL 存储过程易受 SQL 注入攻击吗?

Is this MySQL Stored Procedure vulnerable to SQL injection?

我有一个使用动态 SQL 的 MySQL 存储过程。我们使用 Dynamic SQL 是因为我们有几个包含相似列的表,我们正在努力使代码尽可能可重用。

我担心 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 statement。

另一种方法是使用 table 白名单,这意味着您首先检查 table 是否与您现有的 table 匹配,如果不匹配,则不要 运行查询。

SQL 注入仅在用户提供的文本字符串连接到 SQL 语句而没有充分转义时才会发生。由于您的 table 名称不会由用户提供,而是由程序员提供,因此您没有遇到麻烦。

但是你不应该这样做。数据库引擎最好有显式语句,这样可以正确优化它们,而不必在每次调用时重新解析 SQL。

table 名称应被 "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

尽管目前缺少这些,但您的漏洞似乎相当低;根据 official docs "SQL syntax for prepared statements does not support multi-statements"

孤立地说,是的,这个存储过程可能存在漏洞,但漏洞可能无关紧要。 重要的是 tablename 参数的值是否来自可靠来源。

如果您检查您的 "standard attack strings," 之一,您会发现攻击者正试图完成您的 SQL 查询,然后再进行另一个查询。为了做到这一点,攻击者必须能够直接修改正在拼接到您的查询中的字符串。

如果您使用此 SP 的方式使得 tablename 的值无法被恶意用户直接修改,那么您就没有 SQL 注入漏洞。

我希望这是有道理的。