求mysql_real_escape_string()防注入详解

mysql_real_escape_string()被视为替代addslashes()和mysql_escape_string()的好方法,可以解决宽字节和注入问题,不过官方对其的描述却说的不清不楚:

图片描述

mysql_real_escape_string — 转义 SQL 语句中使用的字符串中的特殊字符,并考虑到连接的当前字符集

这句真没懂,考虑到连接的当前字符集啥意思,请高手详细讲讲,谢谢!

参考:
http://php.net/manual/zh/function.mysql-real-escape-string.php
http://www.cnblogs.com/suihui/archive/2012/09/20/2694751.html
http://www.neatstudio.com/show-963-1.shtml

补充问题: @演演演演
1.加的\并不会传入mysql中,那么如果注入了' or 1=1;-- s ,这里的注入内容最终还不是传到mysql去了执行了吗?
参照:https://segmentfault.com/q/1010000005994443

2.并考虑到连接的当前字符集啥意思呢? 改变当前连接的字符集?

阅读 9.8k
2 个回答

这个说的就是mysql gbk双字节注入

比如用户登录 假设你的sql语句:
$sql = "select * from user where user_name='$username' and password='$password'";

1 如果存在注入点 并且也没有转义。传递参数username=' or 1=1;-- s 那么此时的sql语句就是

$sql = "select * from user where user_name='' or 1=1;-- s ' and password='$password'";

因为--是注释符 所以后面不用判断成功绕过

2 如果存在注入点 并且使用了特殊字符转义。那么此时的sql语句就是

$sql = "select * from user where user_name='\' or 1=1;-- s ' and password='$password'";

无法绕过

3 这个时候问题来了,牛逼的黑客发现了gbk编码时存在宽字节注入。这个时候传递username=%df%27 or 1=1;--

这个时候执行的sql语句变成了:

$sql = "select * from user where user_name='運' or 1=1;-- s ' and password='$password'"; 成功绕过

如何解决这个问题

mysql_real_escape_string — 转义 SQL 语句中使用的字符串中的特殊字符,并考虑到连接的当前字符集

mysql_real_escape_string方法对SQL语句的转义机制,随着当前数据库连接的字符集的改变而改变。相同的SQL语句,不同的字符集下,转义后的结果不一定相同。

重要:

mysql_real_escape_string方法属于mysql扩展,该扩展自PHP版本5.5.0之后已被标记为过时,并在PHP版本7之后被移除。请使用mysqli或者PDO扩展进行数据库操作。数据库字符集请尽量使用utf8或者utf8mb4(更好)。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏