PHP防SQL注入不要再用addslashes和mysql_real_escape_string了,有需要的朋友可以参考下。

博主热衷各种互联网技术,常啰嗦,时常伴有强迫症,常更新,觉得文章对你有帮助的可以关注我。 转载请注明"深蓝的镰刀"


看了很多PHP网站在防SQL注入上还在使用addslashes和str_replace,百度一下"PHP防注入"也同样在使用他们,实践发现就连mysql_real_escape_string也有黑客可以绕过的办法,如果你的系统仍在用上面三个方法,那么我的这篇博文就有了意义,以提醒所有后来者绕过这个坑。

出于为后人栽树而不是挖坑的考虑,给出PHP以及MYSQL的版本信息,以免将来“问题”不再是“问题”了。

用str_replace以及各种php字符替换函数来防注入已经不用我说了,这种“黑名单”式的防御已经被证明是经不起时间考验的。

下面给出绕过addslasher和mysql_real_escape_string的方法(Trick)。

注意:虽然在MYSQL5.5.37-log下该Trick已经被修复了,但仍然没有确切地解决注入问题,介于很多公司的系统仍在使用Mysql5.0,我建议立马做出改进,这点也是我《也说说几种让程序员快速提高能力的方法 
中提到的一个十分重要的点。

注意:如果你不确定你的系统是否有SQL注入的风险,请将下面的下面的DEMO部署到你的服务器,如果运行结果相同,那么请参考最后的完美的解决方案。

MYSQL:

mysql> select version();
+---------------------+
| version() |
+---------------------+
| 5.0.45-community-ny |
+---------------------+
1 row in set (0.00 sec)
mysql> create database test default charset GBK;
Query OK, 1 row affected (0.00 sec)
mysql> use test;
Database changed
mysql> CREATE TABLE users (
username VARCHAR(32) CHARACTER SET GBK,
password VARCHAR(32) CHARACTER SET GBK,
PRIMARY KEY (username)
);
Query OK, 0 rows affected (0.02 sec)
mysql> insert into users SET username='ewrfg', password='wer44';
Query OK, 1 row affected (0.01 sec)
mysql> insert into users SET username='ewrfg2', password='wer443';
Query OK, 1 row affected (0.01 sec)
mysql> insert into users SET username='ewrfg4', password='wer4434';
Query OK, 1 row affected (0.01 sec)=

PHP:

<?php
echo "PHP version: ".PHP_VERSION."\n"; mysql_connect('servername','username','password');
mysql_select_db("test");
mysql_query("SET NAMES GBK"); $_POST['username'] = chr(0xbf).chr(0x27).' OR username = username /*';
$_POST['password'] = 'guess'; $username = addslashes($_POST['username']);
$password = addslashes($_POST['password']);
$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysql_query($sql) or trigger_error(mysql_error().$sql); var_dump(mysql_num_rows($result));
var_dump(mysql_client_encoding()); $username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string($_POST['password']);
$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysql_query($sql) or trigger_error(mysql_error().$sql); var_dump(mysql_num_rows($result));
var_dump(mysql_client_encoding()); mysql_set_charset("GBK");
$username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string($_POST['password']);
$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysql_query($sql) or trigger_error(mysql_error().$sql); var_dump(mysql_num_rows($result));
var_dump(mysql_client_encoding());

结果:

PHP version: 5.2.5
int(3)
string(6) "latin1"
int(3)
string(6) "latin1"
int(0)
string(3) "gbk"

可以看出来不论是使用addslashes还是mysql_real_escape_string,我都可以利用编码的漏洞来实现输入任意密码就能登录服务器的注入攻击!!!!(攻击的原理我就不多说了,感兴趣的同学可以研究下字符编码中单字节和多字节的问题)

注意:第三个mysql_real_escape_string之所以能够防注入是因为mysql_escape_string本身并没办法判断当前的编码,必须同时指定服务端的编码和客户端的编码,加上就能防编码问题的注入了。虽然是可以一定程度上防止SQL注入,但还是建议以下的完美解决方案。

完美解决方案就是使用拥有Prepared Statement机制的PDO和MYSQLi来代替mysql_query(注:mysql_query自 PHP 5.5.0 起已废弃,并在将来会被移除):

PDO:

$pdo = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass');

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
$stmt->execute(array('name' => $name)); foreach ($stmt as $row) {
// do something with $row
}

MYSQLi:

$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->bind_param('s', $name); $stmt->execute(); $result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// do something with $row
}

PHP防SQL注入不要再用addslashes和mysql_real_escape_string的更多相关文章

  1. 【荐】PDO防 SQL注入攻击 原理分析 以及 使用PDO的注意事项

    我们都知道,只要合理正确使用PDO,可以基本上防止SQL注入的产生,本文主要回答以下几个问题: 为什么要使用PDO而不是mysql_connect? 为何PDO能防注入? 使用PDO防注入的时候应该特 ...

  2. PDO防 SQL注入攻击 原理分析 以及 使用PDO的注意事项

    我们都知道,只要合理正确使用PDO(PDO一是PHP数据对象(PHP Data Object)的缩写),可以基本上防止SQL注入的产生,本文主要回答以下几个问题: 为什么要使用PDO而不是mysql_ ...

  3. 防止SQL 注入;如何进行防SQL 注入。

    防止SQL 注入:1.开启配置文件中的magic_quotes_gpc 和magic_quotes_runtime 设置2.执行sql 语句时使用addslashes 进行sql 语句转换3.Sql ...

  4. php防sql注入

    [一.在服务器端配置] 安全,PHP代码编写是一方面,PHP的配置更是非常关键. 我 们php手手工安装的,php的默认配置文件在 /usr/local/apache2/conf/php.ini,我们 ...

  5. php防sql注入、xss

    php自带的几个防止sql注入的函数http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2013/0318/12234.html addslashe ...

  6. PHP防SQL注入攻击

    PHP防SQL注入攻击 收藏 没有太多的过滤,主要是针对php和mysql的组合. 一般性的防注入,只要使用php的 addslashes 函数就可以了. 以下是一段copy来的代码: PHP代码 $ ...

  7. 回头探索JDBC及PreparedStatement防SQL注入原理

    概述 JDBC在我们学习J2EE的时候已经接触到了,但是仅是照搬步骤书写,其中的PreparedStatement防sql注入原理也是一知半解,然后就想回头查资料及敲测试代码探索一下.再有就是我们在项 ...

  8. php防sql注入过滤代码

    防止sql注入的函数,过滤掉那些非法的字符,提高sql安全性,同时也可以过滤XSS的攻击. function filter($str) { if (empty($str)) return false; ...

  9. golang 防SQL注入 基于反射、TAG标记实现的不定参数检查器

    收到一个任务,所有http的handler要对入参检查,防止SQL注入.刚开始笨笨的,打算为所有的结构体写一个方法,后来统计了下,要写几十上百,随着业务增加,以后还会重复这个无脑力的机械劳作.想想就l ...

随机推荐

  1. PHP网页显示乱码问题总结

    其实,乱码,都是因为编码不统一的问题导致的. 以UTF-8编码为例: 第一步,确定数据库字段的编码,字符集:urt8 第二部,PHP脚本设置编码:header('Content-Type: text/ ...

  2. Spark代码调优(一)

    环境极其恶劣情况下: import org.apache.spark.SparkContext import org.apache.spark.rdd.RDD import org.apache.sp ...

  3. linux命令按文件内容查找文件

    [root@hn web]# find /app/code/hzg/web/ -type f -name "*.php" | xargs grep "slog"

  4. [REP]AWS Regions and Availability Zones: the simplest explanation you will ever find around

    When it comes to Amazon Web Services, there are two concepts that are extremely important and spanni ...

  5. 无需写try/catch,也能正常处理异常 (转)

    原文地址: http://www.cnblogs.com/artech/archive/2012/10/28/automatic-exception-handling-aspnet.html 对于企业 ...

  6. TCP\IP三次握手连接,四次握手断开分析

    TCP(Transmission Control Protocol) 传输控制协议 TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接: 位码即tcp标志位,有6种标 ...

  7. 时间--cd //lastyear

    夏木, 天堂里面有没有车来车往,就像当年南京 街头的喧嚣,我知道即使繁华一片,仍是无法填补你心头无底洞般的孤独! 只是因为在人群中多看了你一眼再也无法忘掉你容颜 是不是真的可以一醉解千愁 爱要怎么说出 ...

  8. android activity的启动方式

    1.Standard正常启动,默认的启动方式,没什么说头 2.SingleTop 意思就是在栈顶只能存在一个相同的activity 不能叠加,如果再A上继续启动A的话,只会调用A的onNewInten ...

  9. Linux压缩打包命令

    tar命令 [root@linux ~]# tar [-cxtzjvfpPN] 文件与目录 .... 参数 -c :建立一个压缩文件的参数指令(create 的意思): -x :解开一个压缩文件的参数 ...

  10. 一、OWIN初探

    前言 OWIN在.NET Web Servers与Web Application之间定义了一套标准接口,OWIN的目标是用于解耦Web Server和Web Application.基于此标准,鼓励开 ...