首页 运维 安全 PDO原理及正确使用方法

PDO原理及正确使用方法

Jan 11, 2020 pm 05:29 PM
pdo 原理 方法 正确使用

PDO原理及正确使用方法

前言

随着数据库参数化查询的方式越来越普遍,SQL注入漏洞较之于以前也大大减少,而PDO作为php中最典型的预编译查询方式,使用越来越广泛。

众所周知,PDO是php中防止SQL注入最好的方式,但并不是100%杜绝SQL注入的方式,关键还要看如何使用。

之前在一篇文章中了解到PDO场景下参数可控导致的多句执行等问题(https://xz.aliyun.com/t/3950)于是对PDO场景下的SQL注入又进行了一些探究。

PDO查询语句可控存在的安全问题:

首先在本地新建一个库和表,随便写点东西。

1.jpg

然后写一个test.php,用PDO进行简单的查询:

<?php 
try{
  $db = new PDO(&#39;mysql:host=localhost;dbname=pdotest&#39;,&#39;root&#39;,&#39;&#39;);
} 
catch(Exception $e)
{  echo $e->getMessage();
}if(isset($_GET[&#39;id&#39;]))
{
  $id = $_GET[&#39;id&#39;];
}else{
  $id=1;
}
$query = "select balabala from table1 where 1=?";echo "id:".$id."</br>";
$row = $db->prepare($query);
$row->bindParam(1,$id);
$row->execute();
$result = $row->fetch(PDO::FETCH_ASSOC);if($result)
{  echo "结果为:";
  print_r($result);  echo "</br>";
}
登录后复制

将输入的内容和得到的结果打印在页面上:

32b816b79f148ba849ab804acc67b16.png

PDO与安全问题相关的主要的设置有下面三个:

PDO::ATTR_EMULATE_PREPARES
PDO::ATTR_ERRMODE
PDO::MYSQL_ATTR_MULTI_STATEMENTS
登录后复制

分别与模拟预编译、报错和多句执行有关。

PDO默认是允许多句执行和模拟预编译的,在之前的很多文章中已经写到,在参数可控的情况下,会导致堆叠注入。

例如我们把查询语句改成:

$query = "select balabala from table1 where 1={$id}";
$row = $db->query($query);
登录后复制

则在$db->query()这一步执行之前,我们便可以对$query进行非法操作,那PDO相当于没用:

9f5fdf6b85204f167dd37d28aaf7b4d.png

PDO默认设置存在的安全隐患:

如果我们在查询语句中没有可控的参数,并把输入的参数按照prepare->bindParam->execute的方式去写就一定没有问题了吗?

我们按如下语句进行查询:

$query = "select balabala from table1 where 1=?";
$row = $db->prepare($query);
$row->bindParam(1,$_GET[‘id’]);
$row->execute();
登录后复制

我们在URL中随便输入一个参数:?id=asdasd,然后通过设置SET GLOBAL GENERAL_LOG=ON,从.log里实时监控,看看sql语句到底执行了什么:

b08a16a065087ac13690013e2b2d227.png

我们发现模拟预编译的请求发送方式和以往的mysqli并没有什么区别,但我们注意到,在原有的查询语句中对参数并没有用单引号包裹,而在此却用单引号进行了包裹,于是我们可以尝试输入一些特殊字符,比如单引号:

b7e2944b73272a8dd73bb400746c3a0.png

发现单引号被转义了,这时我们不由得想到如果设置了gbk编码会怎么样:

2.jpg

我们会发现select * from table1成功执行了,尽管PDO只会返回一个结果,但是它的的确确执行了。

也就是说,即使查询语句里没有可控参数,只有?或者:id这类被绑定的参数,依然可以进行堆叠注入。

那如果把多句执行关掉呢?

我们把PDO::MYSQL_ATTR_MULTI_STATEMENTS设为false,重复上述操作:

3.jpg

发现已经行不通了。

021c9104380da557e2c67499806bdf8.png

实际也只执行了设置gbk这一条语句

但是这样就结束了吗?

为什么不试试union注入等其他方式呢?

4.jpg

经过尝试,发现union注入也是可以的!根本不需要进行多句执行!

实际上,在模拟预编译的情况下,PDO对于SQL注入的防范(PDO::queto()),无非就是将数字型的注入转变为字符型的注入,又用类似mysql_real_escape_string()的方法将单引号、双引号、反斜杠等字符进行了转义。

这种防范方法在GBK编码的情况下便可用宽字节进行绕过,而在非GBK编码的情况下,若存在二次注入的情况,是否能利用呢?

答案是否定的。

二次注入是由于对添加进数据库中的数据没有再次处理和转义而导致的,而预编译对每次查询都进行转义,则不存在二次注入的情况。

上述安全隐患,是由于未正确设置PDO造成的,在PDO的默认设置中,PDO::ATTR_EMULATE_PREPARES和PDO::MYSQL_ATTR_MULTI_STATEMENTS都是true,意味着模拟预编译和多句执行是默认开启的。

而在非模拟预编译的情况下,若语句中没有可控参数,是否还能这样做呢?

答案是否定的。

我们将PDO::ATTR_EMULATE_PREPARES设为false,来看看sql语句到底执行了什么:

5.jpg

它对每一句sql语句都进行了预编译和执行两个操作,在执行select balabala from table1 where 1=?这句时,如果是GBK编码,那么它将会把?绑定的参数转化成16进制,这样无论输入什么样的东西都无法再进行注入了。

如果不是GBK编码,如上面所说,也不存在二次注入的情况,故可以避免SQL注入漏洞。

相同原理的Prepare Statement方法

PDO的原理,与Mysql中prepare语句是一样的。上面PDO所执行的SQL语句,用如下的方式可以等效替代:

Set @x=0x31
Prepare a from “select balabala from table1 where 1=?”
Execute a using @x
登录后复制

我们可以手动将输入的参数设置为@x,并将其转化为16进制,随后预编译,再执行

也就是说,不用PDO也可以仿照其原理手动设置预编译:

$db = new mysqli(&#39;localhost&#39;,&#39;root&#39;,&#39;&#39;,&#39;pdotest&#39;);if(isset($_GET[&#39;id&#39;]))
{
	$id = "0x".bin2hex($_GET[&#39;id&#39;]);
}else{
	$id=1;
}echo "id:".$id."</br>";
$db->query("set names gbk");
$db->query("set @x={$id}");
$db->query("prepare a from &#39;select balabala from table1 where 1=?&#39;");
$row = $db->query("execute a using @x");
$result = $row->fetch_assoc();if($result)
{	echo "结果为:";
	print_r($result);	echo "</br>";
}
登录后复制

得到的结果和使用PDO是一样的:

6.jpg

这样设置不用担心没有合理地设置PDO,或是用了GBK编码等情况。

Prepare Statement在SQL注入中的利用

Prepare语句在防范SQL注入方面起到了非常大的作用,但是对于SQL注入攻击却也提供了新的手段。

Prepare语句最大的特点就是它可以将16进制串转为语句字符串并执行。如果我们发现了一个存在堆叠注入的场景,但过滤非常严格,便可以使用prepare语句进行绕过。

例如我们将createtable table2 like table1转化成16进制,然后执行:

7.jpg

我们发现数据库中已经多了一个表table2。则语句成功执行了。

总结

对于此类问题的防范,主要有以下三个方面:

1. 合理、安全地使用gbk编码。即使采用PDO预编译的方式,如若配置不当,依然可造成宽字节注入

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

3. 可采用使用Prepare Statement手动预编译,杜绝SQL注入

相关文章教程推荐:网站安全教程

以上是PDO原理及正确使用方法的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

怎么在番茄免费小说app中写小说 分享番茄小说写小说方法教程 怎么在番茄免费小说app中写小说 分享番茄小说写小说方法教程 Mar 28, 2024 pm 12:50 PM

  番茄小说是一款非常热门的小说阅读软件,我们在番茄小说中经常会有新的小说和漫画可以去阅读,每一本小说和漫画都很有意思,很多小伙伴也想着要去写小说来赚取赚取零花钱,在把自己想要写的小说内容编辑成文字,那么我们要怎么样在这里面去写小说呢?小伙伴们都不知道,那就让我们一起到本站本站中花点时间来看写小说的方法介绍吧。分享番茄小说写小说方法教程  1、首先在手机上打开番茄免费小说app,点击个人中心——作家中心  2、跳转到番茄作家助手页面——点击创建新书在小说的结

七彩虹主板怎么进入bios?教你两种方法 七彩虹主板怎么进入bios?教你两种方法 Mar 13, 2024 pm 06:01 PM

  七彩虹主板在中国国内市场享有较高的知名度和市场占有率,但是有些七彩虹主板的用户还不清楚怎么进入bios进行设置呢?针对这一情况,小编专门为大家带来了两种进入七彩虹主板bios的方法,快来试试吧!  方法一:使用u盘启动快捷键直接进入u盘装系统  七彩虹主板一键启动u盘的快捷键是ESC或F11,首先使用黑鲨装机大师制作一个黑鲨U盘启动盘,然后开启电脑,当看到开机画面的时候,连续按下键盘上的ESC或F11键以后将会进入到一个启动项顺序选择的窗口,将光标移动到显示“USB”的地方,然

微信删除的人如何找回(简单教程告诉你如何恢复被删除的联系人) 微信删除的人如何找回(简单教程告诉你如何恢复被删除的联系人) May 01, 2024 pm 12:01 PM

而后悔莫及、人们常常会因为一些原因不小心将某些联系人删除、微信作为一款广泛使用的社交软件。帮助用户解决这一问题,本文将介绍如何通过简单的方法找回被删除的联系人。1.了解微信联系人删除机制这为我们找回被删除的联系人提供了可能性、微信中的联系人删除机制是将其从通讯录中移除,但并未完全删除。2.使用微信内置“通讯录恢复”功能微信提供了“通讯录恢复”节省时间和精力,用户可以通过该功能快速找回之前被删除的联系人,功能。3.进入微信设置页面点击右下角,打开微信应用“我”再点击右上角设置图标、进入设置页面,,

手机字体大小设置方法(轻松调整手机字体大小) 手机字体大小设置方法(轻松调整手机字体大小) May 07, 2024 pm 03:34 PM

字体大小的设置成为了一项重要的个性化需求,随着手机成为人们日常生活的重要工具。以满足不同用户的需求、本文将介绍如何通过简单的操作,提升手机使用体验,调整手机字体大小。为什么需要调整手机字体大小-调整字体大小可以使文字更清晰易读-适合不同年龄段用户的阅读需求-方便视力不佳的用户使用手机系统自带字体大小设置功能-如何进入系统设置界面-在设置界面中找到并进入"显示"选项-找到"字体大小"选项并进行调整第三方应用调整字体大小-下载并安装支持字体大小调整的应用程序-打开应用程序并进入相关设置界面-根据个人

Win11管理员权限获取方法汇总 Win11管理员权限获取方法汇总 Mar 09, 2024 am 08:45 AM

Win11管理员权限获取方法汇总在Windows11操作系统中,管理员权限是非常重要的权限之一,可以让用户对系统进行各种操作。有时候,我们可能需要获取管理员权限来完成一些操作,比如安装软件、修改系统设置等。下面就为大家总结了一些获取Win11管理员权限的方法,希望能帮助到大家。1.使用快捷键在Windows11系统中,可以通过快捷键的方式快速打开命令提

手机版龙蛋孵化方法大揭秘(一步一步教你如何成功孵化手机版龙蛋) 手机版龙蛋孵化方法大揭秘(一步一步教你如何成功孵化手机版龙蛋) May 04, 2024 pm 06:01 PM

手机游戏成为了人们生活中不可或缺的一部分,随着科技的发展。它以其可爱的龙蛋形象和有趣的孵化过程吸引了众多玩家的关注,而其中一款备受瞩目的游戏就是手机版龙蛋。帮助玩家们在游戏中更好地培养和成长自己的小龙,本文将向大家介绍手机版龙蛋的孵化方法。1.选择合适的龙蛋种类玩家需要仔细选择自己喜欢并且适合自己的龙蛋种类,根据游戏中提供的不同种类的龙蛋属性和能力。2.提升孵化机的等级玩家需要通过完成任务和收集道具来提升孵化机的等级,孵化机的等级决定了孵化速度和孵化成功率。3.收集孵化所需的资源玩家需要在游戏中

nohup的作用及原理解析 nohup的作用及原理解析 Mar 25, 2024 pm 03:24 PM

nohup的作用及原理解析在Unix和类Unix操作系统中,nohup是一个常用的命令,用于在后台运行命令,即便用户退出当前会话或关闭终端窗口,命令仍然能够继续执行。在本文中,我们将详细解析nohup命令的作用和原理。一、nohup的作用后台运行命令:通过nohup命令,我们可以让需要长时间运行的命令在后台持续执行,而不受用户退出终端会话的影响。这在需要运行

快速掌握:华为手机开启两个微信账号方法大揭秘! 快速掌握:华为手机开启两个微信账号方法大揭秘! Mar 23, 2024 am 10:42 AM

在当今社会,手机已经成为我们生活中不可或缺的一部分。而微信作为我们日常沟通、工作、生活的重要工具,更是经常被使用。然而,在处理不同事务时可能需要分开两个微信账号,这就要求手机能够支持同时登录两个微信账号。华为手机作为国内知名品牌,很多人使用,那么华为手机开启两个微信账号的方法是怎样的呢?下面就来揭秘一下这个方法。首先,要在华为手机上同时使用两个微信账号,最简

See all articles