热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PDO场景下的SQL注入探究

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

前言

PHP数据对象(PDO)扩展为 PHP 访问数据库定义了一个轻量级的一致接口。PDO提供了一个数据访问抽象层,这意味着,不管使用哪种数据库,都可以使用相同的函数(方法)来查询和获取数据。PDO随PHP 5.1发行,在PHP 5.0的PECL扩展中也可以使用,无法运行于之前的PHP版本。今天我们讨论PDO多语句执行(堆叠查询)和PDO预处理下的 SQL 注入问题导致SQL注入的问题。如有不足,不吝赐教。

PDO 多语句执行

PHP连接 MySQL 数据库有三种方式(MySQL、Mysqli、PDO),同时官方对三者也做了列表性比较:

Mysqli

PDO

MySQL

引入的PHP版本

5.0

5.0

3.0之前

PHP5.x是否包含

服务端prepare语句的支持情况

客户端prepare语句的支持情况

存储过程支持情况

多语句执行支持情况

大多数

可以看到Mysqli和PDO是都是支持多语句执行的,我们对比一下看看两者的区别

1.  My sqli 通过 multi_query () 函数 来进行多语句执行

$host = '192.168.27.61' ;

$ dbName = 'test' ;

$user = 'root' ;

$pass = 'root' ;

$ mysqli  =  mysqli_connect ( $ host , $ user , $pass , $ dbName );

if ( mysqli_connect_ errno ( ))

{

echo   mysqli_connect_ error ( );

}

$ sql  =  "select * from user where id=1;" ;

$ sql  . "create table test2 like user" ;

$ mysqli -> multi_query ( $ sql );

$data  =  $ mysqli -> store_ result ( );

print_r ( $data -> fetch_ row ( ));

mysqli_close ( $ mysqli );

请求脚本后发现数据库中成功创建了test2表,说明多语句成功执行

PDO场景下的SQL注入探究

我们通过wireshark分析一下,首先登录请求Multiple statements字段未设置

PDO场景下的SQL注入探究

通过multi_query()函数可以看到在执行Query前向Mysql服务器发送了一次Set Option请求将multi statements设置打开

PDO场景下的SQL注入探究

而使用 普通的 mysqli_query () 函数 在执行Query前不会向 Mysql 服务器 发送 set  option 请求

PDO场景下的SQL注入探究

2.  使用PD O中的q uery () 函数同数据库交互

$ dbms = ' mysql ' ;

$host = '192.168.27.61' ;

$ dbName = 'test' ;

$user = 'root' ;

$pass = 'root' ;

$ dsn = " $ dbms :host = $ host ;dbname = $ dbName " ;

try  {

$ pdo  =  new   PDO ( $ dsn $user $pass );

catch  ( PDOException   $e ) {

echo   $e ;

}

$ sql  =  "select * from user where id=1;" ;

$ sql  . "create table test2 like user" ;

$ stmt  =  $ pdo -> query ( $ sql );

while ( $row = $ stmt -> fetch ( PDO ::FETCH_ASSOC))

{

var_dump ( $row );

echo   "< br >" ;

}

请求脚本后发现数据库中成功创建了test2表,说明多语句成功执行

PDO场景下的SQL注入探究

通过wireshark分析,通过PDO方式同数据库交互时,在登录时会设置Multiple statements字段,然后通过Query方式直接发送多语句到Mysql服务器

PDO场景下的SQL注入探究

PDO默认支持多语句查询,如果php版本小于5.5.21或者创建PDO实例时未设置PDO::MYSQL_ATTR_MULTI_STATEMENTS为false时可能会造成堆叠注入

$ dbms = ' mysql ' ;

$host = '192.168.27.61' ;

$ dbName = 'test' ;

$user = 'root' ;

$pass = 'root' ;

$ dsn = " $ dbms :host = $ host ;dbname = $ dbName " ;

try  {

$ pdo  =  new   PDO ( $ dsn $user $pass );

catch  ( PDOException   $e ) {

echo   $e ;

}

$id  =  $_GET [ 'id' ];

$ sql  =  " SELECT   *   from  user  where  id  = " . $ id ;

$ stmt  =  $ pdo -> query ( $ sql );

while ( $row = $ stmt -> fetch ( PDO ::FETCH_ASSOC))

{

var_dump ( $row );

echo   "< br >" ;

}

$id变量可控,构造连接访问,成功创建aaa数据表

PDO场景下的SQL注入探究

如果想禁止多语句执行,可在创建PDO实例时将    PDO::MYSQL_ATTR_MULTI_STATEMENTS设置为false

new  PDO( $ dsn , $user, $pass, array( PDO::MYSQL_ATTR_MULTI_STATEMENTS => false))

My SQL 预处理

MySQL数据库支持预处理,预处理或者说是可传参的语句用来高效的执行重复的语句。

MySQL官方将prepare、execute、deallocate统称为PREPARE STATEMENT

预制语句的SQL语法基于三个SQL语句:

prepare  stmt_name   from   preparable _stmt ;

execute  stmt_name  [using @ var_name  [, @ var_name ] ...];

{deallocate | drop} prepare  stmt_name ;

PDO 预处理

PDO分为模拟预处理和非模拟预处理。

模拟预处理是防止某些数据库不支持预处理而设置的,在初始化PDO驱动时,可以设置一项参数,PDO::ATTR_EMULATE_PREPARES,作用是打开模拟预处理(true)或者关闭(false),默认为true。PDO内部会模拟参数绑定的过程,SQL语句是在最后execute()的时候才发送给数据库执行。

非模拟预处理则是通过数据库服务器来进行预处理动作,主要分为两步:第一步是prepare阶段,发送SQL语句模板到数据库服务器;第二步通过execute()函数发送占位符参数给数据库服务器进行执行。

首先我们通过wireshark抓包方式对比一下模拟预处理和非模拟预处理

模拟预处理代码:

$ dbms = ' mysql ' ;

$host = '192.168.27.61' ;

$ dbName = 'test' ;

$user = 'root' ;

$pass = 'root' ;

$ dsn = " $ dbms :host = $ host ;dbname = $ dbName " ;

try  {

$ pdo  =  new   PDO ( $ dsn $user $pass array PDO ::MYSQL_ATTR_MULTI_STATEMENTS =>  false ));

catch  ( PDOException   $e ) {

echo   $e ;

}

$username  =  $_GET [ 'username' ];

$ sql  =  "select * from user where username  = ? " ;

$ stmt  =  $ pdo -> prepare ( $ sql );

$ stmt -> bindParam ( 1 , $ username );

$ stmt -> execute ( );

while ( $row = $ stmt -> fetch ( PDO ::FETCH_ASSOC))

{

var_dump ( $row );

echo   "< br >" ;

}

PDO在模拟预处理通过wireshark抓包可以看到是将处理完的SQL语句发送给MySQL服务器

PDO场景下的SQL注入探究

非模拟预处理代码,在 $username = $_GET['username']; 代码 前增加 $ pdo -> setAttribute (PDO::ATTR_EMULATE_PREPARES, false); 这里就是上面提到的,首先给MySQL服务器发送SQL语句模板,然后通过EXECUTE发送占位符参数给服务器

PDO场景下的SQL注入探究

预处理 的安全问题

模拟预处理下

$ dbms = ' mysql ' ;

$host = '192.168.27.61' ;

$ dbName = 'test' ;

$user = 'root' ;

$pass = 'root' ;

$ dsn = " $ dbms :host = $ host ;dbname = $ dbName " ;

try  {

$ pdo  =  new   PDO ( $ dsn $user $pass );

catch  ( PDOException   $e ) {

echo   $e ;

}

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

$username  =  $_GET [ 'username' ];

$ sql  =  "select  id, " . $ _GET [ 'field' ]. " from user where username = ?" ;

$ stmt  =  $ pdo -> prepare ( $ sql );

$ stmt -> bindParam ( 1 , $ username );

$ stmt -> execute ( );

while ( $row = $ stmt -> fetch ( PDO ::FETCH_ASSOC))

{

var_dump ( $row );

echo   "< br >" ;

}

可以看到sql语句field字段可控,这样我们构造field,达到多语句执行的效果。

PDO场景下的SQL注入探究

当设置$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);时,也可以达到报错注入效果

PDO场景下的SQL注入探究

将上面模拟预处理代码$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);的注释关闭来进行非模拟预处理

同样的field字段可控,这时多语句不可执行,但是当设置$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);时,也可进行报错注入

PDO场景下的SQL注入探究

PDO场景下的SQL注入探究

这里可进行报错注入是因为MySQL服务端prepare时报错,然后通过设置PDO::ATTR_ERRMODE将MySQL错误信息打印

在MySQL中执行prepare语句

prepare  statm  from "select  id,updatexml (0x7e,concat(0x7e,user(),0x7e),0x7e) from user where username=?";

PDO场景下的SQL注入探究

总结

1、使用PDO时尽量使用非模拟预处理。

2、创建PDO实例时将PDO::MYSQL_ATTR_MULTI_STATEMENTS设置为false,禁止多语句查询。

3、SQL语句模板不使用变量动态拼接生成

参考

https://dev.mysql.com/doc/apis-php/en/apis-php-mysqli.quickstart.multiple- statement.html

https://secure.php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-multi-statements

https://www.leavesongs.com/PENETRATION/thinkphp5-in-sqlinjection.html


以上所述就是小编给大家介绍的《PDO场景下的SQL注入探究》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 我们 的支持!


推荐阅读
  • MySQL笔记_MySQL笔记1|数据库17问17答
    本文由编程笔记#小编为大家整理,主要介绍了MySQL笔记1|数据库17问17答相关的知识,希望对你有一定的参考价值。 ... [详细]
  • PDO MySQL
    PDOMySQL如果文章有成千上万篇,该怎样保存?数据保存有多种方式,比如单机文件、单机数据库(SQLite)、网络数据库(MySQL、MariaDB)等等。根据项目来选择,做We ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文由编程笔记小编整理,介绍了PHP中的MySQL函数库及其常用函数,包括mysql_connect、mysql_error、mysql_select_db、mysql_query、mysql_affected_row、mysql_close等。希望对读者有一定的参考价值。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 如何在php中将mysql查询结果赋值给变量
    本文介绍了在php中将mysql查询结果赋值给变量的方法,包括从mysql表中查询count(学号)并赋值给一个变量,以及如何将sql中查询单条结果赋值给php页面的一个变量。同时还讨论了php调用mysql查询结果到变量的方法,并提供了示例代码。 ... [详细]
  • 延迟注入工具(python)的SQL脚本
    本文介绍了一个延迟注入工具(python)的SQL脚本,包括使用urllib2、time、socket、threading、requests等模块实现延迟注入的方法。该工具可以通过构造特定的URL来进行注入测试,并通过延迟时间来判断注入是否成功。 ... [详细]
  • 本文介绍了一个免费的asp.net控件,该控件具备数据显示、录入、更新、删除等功能。它比datagrid更易用、更实用,同时具备多种功能,例如属性设置、数据排序、字段类型格式化显示、密码字段支持、图像字段上传和生成缩略图等。此外,它还提供了数据验证、日期选择器、数字选择器等功能,以及防止注入攻击、非本页提交和自动分页技术等安全性和性能优化功能。最后,该控件还支持字段值合计和数据导出功能。总之,该控件功能强大且免费,适用于asp.net开发。 ... [详细]
  • 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之六 || API项目整体搭建 6.1 仓储模式
    代码已上传Github+Gitee,文末有地址  书接上文:前几回文章中,我们花了三天的时间简单了解了下接口文档Swagger框架,已经完全解放了我们的以前的Word说明文档,并且可以在线进行调 ... [详细]
  • 浅解XXE与Portswigger Web Sec
    XXE与PortswiggerWebSec​相关链接:​博客园​安全脉搏​FreeBuf​XML的全称为XML外部实体注入,在学习的过程中发现有回显的XXE并不多,而 ... [详细]
  • 本文介绍了使用postman进行接口测试的方法,以测试用户管理模块为例。首先需要下载并安装postman,然后创建基本的请求并填写用户名密码进行登录测试。接下来可以进行用户查询和新增的测试。在新增时,可以进行异常测试,包括用户名超长和输入特殊字符的情况。通过测试发现后台没有对参数长度和特殊字符进行检查和过滤。 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
author-avatar
Ms丶娇丶
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有