PHP中MySQL注入防御代码,mysql注入在PHP代码层面的防御手段

前置知识

什么是sql注入?

服务端没有对用户提交的参数进行严格的过滤,导致可以将SQL语句插入到可控参数中,改变原有的SQL语义结构,从而执行攻击者所预期的结果。

sql注入的探测

判断数据库类型端口

报错信息

一些中间件常用的数据库

PHP MySQL

ASP SQL Server

ASPX SQL Server

JSP MySQL Oracle

寻找SQL注入点

寻找与数据库交互的可控参数GET

POST

COOKIE

HTTP头

确定注入点

确定注入点的核心思想就是判断插入的数据是否被当做SQL语句执行。可以使用简单的算术运算来测试。

SQL注入的防御的原理

23dc41bf10610b0c9bea2355668561e6.pngSQL语句预编译和绑定变量

使用足够严格的过滤和安全防御Web应用向数据库传递语句模板

数据库对模板进行编译,编译以后语义将不会改变

变量绑定,Web应用向数据库传递变量,变量只会被当做数据识别,不会被作为语义结构识别

执行SQL语句

SQL注入的核心:数据和代码的混淆。

PDO

什么是PDO?

PHP 数据对象 (PDO) 扩展为PHP访问数据库定义了一个轻量级的一致接口。

PDO 提供了一个数据访问抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。

PDO是php中最典型的预编译查询方式。

PDO场景下的SQL注入

PDO与安全相关的问题主要的设置有下面三项:PDO::ATTR_EMULATE_PREPARES # 模拟预编译

PDO::ATTR_ERRMODE # 报错

PDO::MYSQL_ATTR_MULTI_STATEMENTS # 多语句执行

第一项为模拟预编译,如果为False,则不存在SQL注入;如果为True,则PDO并非真正的预编译,而是将输入统一转化为字符型,并转义特殊字符。这样如果是gbk编码则存在宽字节注入。

第二项而报错,如果设置为True,可能会泄露一些信息。

第三项为多语句执行,如果设置为True,且第一项也为True,则会存在宽字节+堆叠注入的双重漏洞。

对于此类问题的防范,主要有以下三个方面:合理、安全的使用gbk编码。即使采用PDO预编译的方式,如果开启模拟预编译,依然可以造成宽字节注入。

使用PDO时,一定要将模拟预编译设置为false。

可采用Prepare Statement手动预编译,防御SQL注入。

代码示例$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', $user, $password);

$stmt = $dbh->prepare('INSERT INTO REGISTRY (name, value) VALUES (:name, :value)');

$stmt->bindParam(':name', $name);

$stmt->bindParam(':value', $value);

// insert one row

$name = 'one';

$value = 1;

$stmt->execute();

或者$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', $user, $password);

$stmt = $dbh->prepare('UPDATE people SET name = :new_name WHERE id = :id');

$stmt->execute( array('new_name' => $name, 'id' => $id) );

ODBC

ODBC 是一种应用程序编程接口(Application Programming Interface,API),使我们有能力连接到某个数据源(比如一个 MS Access 数据库)。

代码示例$stmt = odbc_prepare( $conn, 'SELECT * FROM users WHERE email = ?' );

$success = odbc_execute( $stmt, array($email) );

或者$dbh = odbc_exec($conn, 'SELECT * FROM users WHERE email = ?', array($email));

$sth = $dbh->prepare('SELECT * FROM users WHERE email = :email');

$sth->execute(array(':email' => $email));

MYSQLi

MySQLi函数允许你访问MySQL数据库服务器。$stmt = $db->prepare('update name set name = ? where id = ?');

$stmt->bind_param('si',$name,$id);

$stmt->execute();

框架

对于框架的话只要遵循框架的API就好,例如wp查询global $wpdb;

$wpdb->query(

$wpdb->prepare( 'SELECT name FROM people WHERE id = %d OR email = %s',

$person_id, $person_email

)

);global $wpdb;

$wpdb->insert( 'people',

array(

'person_id' => '123',

'person_email' => 'bobby@tables.com'

),

array( '%d', '%s' )

);

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值