提问人:CodeMonkeyMajor 提问时间:7/30/2021 更新时间:8/13/2021 访问量:328
通过限制可用字符和使用 REGEXP() 来防止 MySQL 中的 SQL 注入
Preventing SQL Injection in MySQL by limiting usable characters and using REGEXP()
问:
我正在寻找一种在不使用预准备语句的情况下防止 SQL 注入的方法。我知道预处理语句是防止SQL注入的正确方法,但是MySQL不允许在ALTER USER预处理语句中使用参数,因此我需要另一种选择:
# Will not work
CREATE DEFINER=`root`@`localhost` PROCEDURE `TestProcedure`()
BEGIN
SET @InputVal = 'NewPassword';
SET @SQLStr = 'ALTER USER \'SomeUser\'@\'localhost\' IDENTIFIED BY ?';
PREPARE SQLStatement FROM @SQLStr;
EXECUTE SQLStatement USING @InputVal;
DEALLOCATE PREPARE SQLStatement;
END
具体目标是创建一个允许用户更改其密码的存储过程。我假设字母数字输入不会导致 SQL 注入(大概是一个足够公平的假设,但我愿意纠正,因为我已经看到一些非常有创意的 SQL 注入使用退格字符之类的东西):
CREATE DEFINER=`root`@`localhost` PROCEDURE `ChangeCurrentUserPassword`(IN NewPassword VARCHAR(30))
BEGIN
SET @NewPassword = NewPassword;
IF @NewPassword REGEXP '^[a-z0-9]{1,}$' THEN
SET @SQLStr = CONCAT('ALTER USER \'', Substring_Index(USER(),'@',1), '\'@\'localhost\' IDENTIFIED BY \'', NewPassword, '\';');
PREPARE SQLStatement FROM @SQLStr;
EXECUTE SQLStatement;
DEALLOCATE PREPARE SQLStatement;
ELSE
# Non-alphanumeric (or blank) password.
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Password must be alpha-numeric';
END IF;
END
上面的内容确实按预期工作,并且可能是安全的(除了它允许单字符密码的事实 - 它只是为了测试逻辑而拼凑起来),但我不喜欢它将密码限制为仅字母数字的事实。我希望尽可能多地使用非字母数字字符,以便我可以将其添加到 REGEXP 语句中。
我看到很多其他线程询问使用 REGEXP 来检测 SQL 注入,但对于每个线程,他们都在询问如何从任何原始输入进行检测。这里的关键区别在于,我不是试图检测 SQL 注入尝试,而是尝试限制允许的字符,以便首先无法进行 SQL 注入。
有谁知道可以包含但仍能安全地阻止 SQL 注入的字符列表?
旁注:如果有更好的方法仍然允许手术,我很乐意采用全新的方法来处理此程序。我知道我可以直接更新 mysql.user 表,这将允许正确使用准备好的语句,但我想避免直接更新系统表 - 我觉得像 ALTER USER 这样的语句存在纯粹是因为应尽可能避免直接更新。
对不起,这太啰嗦了。感谢您抽出宝贵时间走到这一步!
答:
阅读绕过 mysql_real_escape_string() 的 SQL 注入的答案,尤其是这个。
这是一个引用已弃用的PHP函数的旧答案。这已被替换为 ,它对以下特殊字符进行编码:mysql_real_escape_string
mysqli_real_escape_string
NUL (ASCII 0)、\n、\r、\、'、“ 和 Control-Z
其中是换行符 (ASCII x'0A'),是“回车”字符 (ASCII x'0D')。\n
\r
mysqli_set_charset($link, 'utf8');
$s = mysqli_real_escape_string($link, chr(0) . "\n\r\\'" . '"' . chr(26));
var_dump($s);
指纹:
string(14) "\0\n\r\\\'\"\Z"
所以:
- 确保服务器连接使用字符集 use 或 .
utf8mb4
utf8
- 如上所示,要么转义这 7 个特殊字符,要么不允许在密码中使用部分或全部字符。
- 确保转义密码两边有单引号。
因此,例如,如果您只允许字母数字 [A-Za-z] 加上来自“@#$%&!_”的特殊字符,则不需要转义。如果您还允许使用单引号和/或双引号,那么您只需要确保这些引号用反斜杠转义即可。
评论