Maison >développement back-end >tutoriel php >求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.并考虑到连接的当前字符集
啥意思呢? 改变当前连接的字符集?
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.并考虑到连接的当前字符集
啥意思呢? 改变当前连接的字符集?
这个说的就是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
(更好)。