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

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的功能使用相同的方式也是有相同效果的。


http://www.kler.cn/a/549853.html

相关文章:

  • 用deepseek学大模型04-模型可视化与数据可视化
  • 破解微服务疑难杂症:2025年全解决方案
  • CSS flex布局 列表单个元素点击 本行下插入详情独占一行
  • 数据结构笔记之时间复杂度O(n)中的O是什么的缩写,为什么要用O这个字母?
  • OpenCV机器学习(1)人工神经网络 - 多层感知器类cv::ml::ANN_MLP
  • 逻辑回归介绍
  • 什么是Spring Boot?
  • react传递函数与回调函数原理
  • pix2text 使用经验
  • 《Performance Analysisi and Tuning on Modern CPU》阅读笔记
  • springboot项目如何部署到tomcat中
  • 12. Docker 网络(bridge,host,none,container,自定义网络)配置操作详解
  • DeepSeek 与 Ollama:本地运行 AI 模型的完美组合
  • 5-CDE说明
  • Selenium定位元素的方法及其语法
  • 个人笔记二:数电篇
  • ORB-SLAM3的源码学习: Settings.cc:Settings::readCamera1/readCamera2 从配置文件中加载相机参数
  • [BJDCTF2020]EzPHP
  • 【DeepSeek】DeepSeek R1 本地windows部署(Ollama+Docker+OpenWebUI)
  • IDEA集成DeepSeek