mysql 防注入 php,php操作mysql防止sql注入(合集)

当一个变量从表单传入到php,需要查询mysql的话,需要进行处理。

$unsafe_variable = $_POST['user_input'];

用户可以输入诸如 : value'); DROP TABLE table; ,SQL语句就变成这样了:

执行的结果就是table表被删掉了。

1.魔术引用 (推荐指数3)

addslashes()用于对变量中的' " \和NULL添加\斜杠,用于避免传入sql语句的参数格式错误,同时如果有人注入子查询,通过加\可以将参数解释为内容,而非执行语句,避免被mysql执行。

那么,tripslashes()的作用是将加了\的php变量\去掉,由于\不会写入mysql中,所以从mysql查询出来的内容不需要再tripslashes()。

如果从网页表单、php、mysql都使用utf8编码,则没有这个问题。

参考:https://segmentfault.com/q/1010000005994443

由于addslashes()不检测字符集,所以有宽字节注入风险,所以php中添加了这个函数。

gbk宽字符漏洞导致的sql注入

参考:http://www.cnblogs.com/suihui/archive/2012/09/20/2694751.html

与addslashes()相比,不仅会将' " \ NOL(ascii的0)转义,还会把\r \n进行转义。同时会检测数据编码。

此函数在使用时会使用于数据库连接(因为要检测字符集),并根据不同的字符集做不同的操作。如果当前连接不存在,刚会使用上一次的连接。

此方法在php5.5后不被建议使用,在php7中废除。

3.预处理查询 (Prepared Statements) (推荐指数5)

为什么预处理和参数化查询可以防止sql注入呢?

在mysql5.1后,提供了类似于jdbc的预处理参数化查询。它的查询方法是:

b. 再向mysql发送需要查询的参数

参考:

http://blog.csdn.net/sky_zhe/article/details/9702489

http://www.cnblogs.com/LoveJenny/archive/2013/01/15/2860553.html

预处理分为两种:

看一个完整的用法:

$stmt = $mysqli>prepare("SELECT id, label FROM test WHERE id = ?");

$stmt>execute();

$row = $res>fetch_assoc();

b.替换变量

d.得到一个二进制结果集,从二进制结果中取出php结果集

使用预处理,一条查询分两步,先是,所以很安全。也是php5.5及php7推荐方法。

http://www.cnblogs.com/liuzhang/p/4753467.html

pdo是一个php官方推荐的数据库抽象层,提供了很多实用的工具。

使用方法跟上面差不多,区别在于pdo提供了更多样的方法。

我们在上面预处理参数化查询是在mysql中进行防注入操作的,其实pdo也内置了一个预处理的模拟器,叫做ATTR_EMULATE_PREPARES。

这种情况下,PDO驱动能否正确转义输入参数,是拦截SQL注入的关键。然而PHP 5.3.6及老版本,并不支持在DSN中定义charset属性(会忽略之),这时如果使用PDO的本地转义,仍然可能导致SQL注入,

如果ATTR_EMULATE_PREPARES=false,sql会分两次把参数给送给mysql,mysql根据自身的字符集(set names )进行处理,完成查询。

但由于各版本差异,pdo在各版本中的实现程度也不一样,有些版本还有bug,我们以php5.3.6做为分界线来进行说明:

php5.3.6以下版本

$pdo = new PDO("mysql:host=localhost;dbname=test;",'root','pwd');

$pdo>setAttribute(PDO::ATTR_EMULATE_PREPARES,false);

$pdo>exec('set names utf8');

$id = '0 or 1 =1 order by id desc';

$sql = "select from article where id = ?";

$statement = $pdo>prepare($sql);

$statement>bindParam(1, $id);

$statement>execute();

如上,我们关闭了本地预处理模拟器,参数会直接分批发送给mysql,由mysql根据set name utf8字符集进行检测,完成sql注入处理。以上代码不会产生注入。

php5.3.6以上版本

$pdo = new PDO("mysql:host=localhost;dbname=test;charset=utf8",'root','pwd');

$pdo>exec('set names utf8');

$id = '0 or 1 =1 order by id desc';

$sql = "select from article where id = ?";

$statement = $pdo>prepare($sql);

$statement>bindParam(1, $id);

$statement>execute();

在php5.3.6以上版本中,默认情况下ATTR_EMULATE_PREPARES开启,模拟器会根据new PDO()中的charset=utf8进行检测,在模拟器上完成防注入操作。如果把模拟器关闭,也会像低版本一样送交mysql进行防注入处理。

参考:

PDO防注入原理分析以及使用PDO的注意事项

http://zhangxugg163com.iteye.com/blog/1835721

PHP 5.3.6及以前版本的PDO的bindParam,bindValue潜在的安全隐患

http://zhangxugg163com.iteye.com/blog/1855088

再论php 5.3.6以前版本中的PDO SQL注入漏洞问题

http://my.oschina.net/zxu/blog/163135

segmentfault讨论

https://segmentfault.com/q/1010000000723496

4. html输出与防止xss注入

特殊字符输出

比如' " < >有着特殊的意义,如果直接写到html中输出,会引起dom格式的错乱,那么就需要用到特殊的输出方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值