php mysql_real_escape_string addslashes及mysql绑定参数防SQL注入攻击


Posted in PHP onDecember 23, 2016

php mysql_real_escape_string addslashes及mysql绑定参数防SQL注入攻击

php防止SQL注入攻击一般有三种方法:

  1. 使用mysql_real_escape_string函数
  2. 使用addslashes函数
  3. 使用mysql bind_param()

本文章向大家详细介绍这三个方法在防止SQL注入攻击中的效果及区别。

mysql_real_escape_string防sql注入攻击

mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。

在有些时候需要将mysql_real_escape_string与mysql_set_charset一起使用,因为如果不指定编码,可能会存在字符编码绕过mysql_real_escape_string函数的漏洞,比如:

$name=$_GET['name'];
$name=mysql_real_escape_string($name);
$sql="select *from table where name like '%$name%'";

当输入name值为name=41%bf%27%20or%20sleep%2810.10%29%3d0%20limit%201%23时,sql语句输出为:

SELECT * FROM table WHERE name LIKE '%41¿\\\' or sleep(10.10)=0 limit 1#%';

这时候引发SQL注入攻击。

下面是mysql_real_escape_string函数防止SQL注入攻击的正确做法:

<?php
function check_input($value)
{
// 去除斜杠
if (get_magic_quotes_gpc())
 {
 $value = stripslashes($value);
 }
// 如果不是数字则加引号
/* http://www.manongjc.com/article/1242.html */
if (!is_numeric($value))
 {
 $value = "'" . mysql_real_escape_string($value) . "'";
 }
return $value;
}

$con = mysql_connect("localhost", "hello", "321");
if (!$con)
 {
 die('Could not connect: ' . mysql_error());
 }

// 进行安全的 SQL
mysql_set_charset('utf-8');
$user = check_input($_POST['user']);
$pwd = check_input($_POST['pwd']);
$sql = "SELECT * FROM users WHERE
user=$user AND password=$pwd";

mysql_query($sql);

mysql_close($con);
?>

addslashes防sql注入攻击

国内很多PHP coder仍在依靠addslashes防止SQL注入(包括我在内),我还是建议大家加强中文防止SQL注入的检查。addslashes的问题在于可以用0xbf27来代替单引号,而addslashes只是将0xbf27修改为0xbf5c27,成为一个有效的多字节字符,其中的0xbf5c仍会被看作是单引号,所以addslashes无法成功拦截。当然addslashes也不是毫无用处,它可用于单字节字符串的处理。

addslashes会自动给单引号,双引号增加\,这样我们就可以安全的把数据存入数据库中而不黑客利用,参数'a..z'界定所有大小写字母均被转义,代码如下:

echo addcslashes('foo[ ]','a..z'); //输出:foo[ ] 
$str="is your name o'reilly?"; //定义字符串,其中包括需要转义的字符 
echo addslashes($str); //输出经过转义的字符串

mysql bind_param()绑定参数防止SQL注入攻击

什么叫绑定参数,给大家举个例子:

<?php  
$username = "aaa";  
$pwd = "pwd";  
$sql = "SELECT * FROM table WHERE username = ? AND pwd = ?";  
bindParam($sql, 1, $username, 'STRING'); //以字符串的形式.在第一个问号的地方绑定$username这个变量  
bindParam($sql, 2, $pwd, 'STRING');    //以字符串的形式.在第二个问号的地方绑定$pwd这个变量  
echo $sql;  
?>

你肯定不知道会输出什么..更无法知道绑定参数有什么好处!这样做的优势是什么.更不知道bindParam这个函数到底做了什么.

下面我简单的写一下这个函数:

<?php  
/**  
 * 模拟简单的绑定参数过程  
 *  
 * @param string $sql  SQL语句  
 * @param int $location 问号位置  
 * @param mixed $var   替换的变量  
 * @param string $type  替换的类型  
 */ 
$times = 0;  
//这里要注意,因为要“真正的"改变$sql的值,所以用引用传值 
function bindParam(&$sql, $location, $var, $type) {  
  global $times;  
  //确定类型  
  switch ($type) {  
    //字符串  
    default:          //默认使用字符串类型  
    case 'STRING' :  
      $var = addslashes($var); //转义  
      $var = "'".$var."'";   //加上单引号.SQL语句中字符串插入必须加单引号  
      break;  
    case 'INTEGER' :  
    case 'INT' :  
      $var = (int)$var;     //强制转换成int  
    //还可以增加更多类型..  
  }  
  //寻找问号的位置  
  for ($i=1, $pos = 0; $i<= $location; $i++) {  
    $pos = strpos($sql, '?', $pos+1);  
  }  
  //替换问号  
  $sql = substr($sql, 0, $pos) . $var . substr($sql, $pos + 1);  
}  
?>

注:由于得知道去除问号的次数..所以我用了一个global来解决.如果放到类中就非常容易了.弄个私有属性既可

通过上面的这个函数.我们知道了..绑定参数的防注入方式其实也是通过转义进行的..只不过是对于变量而言的..

我们来做一个实验:

<?php  
$times = 0;  
$username = "aaaa";  
$pwd = "123";  
$sql = "SELECT * FROM table WHERE username = ? AND pwd = ?";  
bindParam($sql, 1, $username, 'STRING'); //以字符串的形式.在第一个问号的地方绑定$username这个变量  
bindParam($sql, 2, $pwd, 'INT');    //以字符串的形式.在第二个问号的地方绑定$pwd这个变量  
echo $sql; //输出 SELECT * FROM table WHERE username = 'aaaa' AND pwd = 123  
?>

可以看到.生成了非常正规的SQL语句.那么好.我们现在来试下刚才被注入的那种情况

<?php  
$times = 0;  
$username = "aaa";  
$pwd = "fdsafda' or '1'='1";  
$sql = "SELECT * FROM table WHERE username = ? AND pwd = ?";  
bindParam($sql, 1, $username, 'STRING'); //以字符串的形式.在第一个问号的地方绑定$username这个变量  
bindParam($sql, 2, $pwd, 'STRING');    //以字符串的形式.在第二个问号的地方绑定$pwd这个变量  
echo $sql; //输出 SELECT * FROM table WHERE username = 'aaa' AND pwd = 'fdsafda\' or \'1\'=\'1'  
?>

可以看到.pwd内部的注入已经被转义.当成一个完整的字符串了..这样的话.就不可能被注入了.

 总结:

上面三个方法都可以防止sql注入攻击,但第一种方法和第二种方法都存在字符编码的漏洞,所以本文章建议大家使用第三种方法。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

PHP 相关文章推荐
PHP脚本的10个技巧(2)
Oct 09 PHP
php中在PDO中使用事务(Transaction)
May 14 PHP
php中自定义函数dump查看数组信息类似var_dump
Jan 27 PHP
制作安全性高的PHP网站的几个实用要点
Dec 30 PHP
Laravel 5框架学习之表单
Apr 08 PHP
php通过curl模拟登陆DZ论坛
May 11 PHP
详解HTTP Cookie状态管理机制
Jan 14 PHP
CodeIgniter配置之autoload.php自动加载用法分析
Jan 20 PHP
PHP设计模式之简单投诉页面实例
Feb 24 PHP
Zend Framework实现具有基本功能的留言本(附demo源码下载)
Mar 22 PHP
PHP+JQUERY操作JSON实例
Mar 23 PHP
PHP开发api接口安全验证操作实例详解
Mar 26 PHP
php的4种常用运行方式详解
Dec 22 #PHP
php curl 模拟登录并获取数据实例详解
Dec 22 #PHP
使用PHP连接多种数据库的实现代码(mysql,access,sqlserver,Oracle)
Dec 21 #PHP
Docker配置PHP开发环境教程
Dec 21 #PHP
PHP符合PSR编程规范的实例分享
Dec 21 #PHP
利用PHP生成CSV文件简单示例
Dec 21 #PHP
PHP实现支付宝即时到账功能
Dec 21 #PHP
You might like
删除无限级目录与文件代码共享
2006/07/12 PHP
php excel类 phpExcel使用方法介绍
2010/08/21 PHP
yii2.0使用Plupload实现带缩放功能的多图上传
2015/12/22 PHP
基于命令行执行带参数的php脚本并取得参数的方法
2016/01/25 PHP
js实现添加可信站点、修改activex安全设置,禁用弹出窗口阻止程序
2016/08/17 Javascript
JS鼠标滚动分页效果示例
2017/07/05 Javascript
详解如何实现一个简单的Node.js脚手架
2017/12/04 Javascript
微信小程序实现banner图轮播效果
2020/06/28 Javascript
Vue 实现把表单form数据 转化成json格式的数据
2019/10/29 Javascript
Vue实现简单计算器案例
2020/02/25 Javascript
vue 实现动态路由的方法
2020/07/06 Javascript
[01:07:11]Secret vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
python实现搜索指定目录下文件及文件内搜索指定关键词的方法
2015/06/28 Python
python僵尸进程产生的原因
2017/07/21 Python
python OpenCV学习笔记之绘制直方图的方法
2018/02/08 Python
python中matplotlib的颜色及线条控制的示例
2018/03/16 Python
python实现log日志的示例代码
2018/04/28 Python
python 哈希表实现简单python字典代码实例
2019/09/27 Python
Python vtk读取并显示dicom文件示例
2020/01/13 Python
Python实现遗传算法(二进制编码)求函数最优值方式
2020/02/11 Python
JetBrains PyCharm(Community版本)的下载、安装和初步使用图文教程详解
2020/03/19 Python
使用python matplotlib 画图导入到word中如何保证分辨率
2020/04/16 Python
如何把外网python虚拟环境迁移到内网
2020/05/18 Python
css3实现背景模糊的三种方式(小结)
2020/05/15 HTML / CSS
Backcountry旗下的户外商品闪购网站:steep&cheap
2016/09/22 全球购物
NYX Professional Makeup英国官网:美国平价专业彩妆品牌
2019/11/13 全球购物
全球最大化妆品零售网站:SkinStore
2020/10/24 全球购物
法学毕业生自我鉴定
2014/01/31 职场文书
超市中秋节促销方案
2014/03/21 职场文书
小学班主任培训方案
2014/06/04 职场文书
医学专业毕业生推荐信
2014/07/12 职场文书
村党总支部公开承诺书2016
2016/03/25 职场文书
python 算法题——快乐数的多种解法
2021/05/27 Python
java调用Restful接口的三种方法
2021/08/23 Java/Android
Redis读写分离搭建的完整步骤
2021/09/14 Redis
uniapp引入支付宝原生扫码插件步骤详解
2022/07/23 Javascript