环境准备
让我们来重现一下常见的数据库环境,来测试我们的注入。我们先安装三款企业常用的关系数据库管理系统(RDBMS),MySQL、MSSQL、和Oracle,并在它们中各创建一个储存用户的表(USERS),如下。
MySQL 5.7.12
CREATE TABLE USERS (username VARCHAR(100) NOT NULL,password VARCHAR(100) NOT NULL,email VARCHAR(100) NOT NULL);
添加用户:
INSERT INTO USERS (username, password, email) values('jake','reynolds','[email protected]'),('net','spi','[email protected]'),('johnjacob','jingle','[email protected]');
MSSQL Server 2014 Express Edition
CREATE TABLE USERS(username varchar(100), password varchar(100), email varchar(100));
添加用户:
INSERT INTO USERS(username, password, email) VALUES('jake','reynolds','[email protected]'),('net','spi','[email protected]'),('johnjacob','jingle','[email protected]');
Oracle SQL 12c
CREATE TABLE USERS("username" VARCHAR2(100),"password" VARCHAR2(100),"email" VARCHAR2(100))
添加用户
INSERT into USERS ("username", "password", "email") values('jake','reynolds','[email protected]'),('net','spi','[email protected]'),('johnjacob','jingle','[email protected]')
新手渗透工程师的第一天
在设置完成后,每个数据库里都有一个名为USERS的表,它们的结构如下:
username |
password |
|
|
1 |
jake |
reynolds |
|
2 |
net |
spi |
|
3 |
johnjacob |
jingle |
对于多数渗透测试来说,用户表通常第一个被触碰的表,因为它被用于用户登录。我们假设查询它的代码如下:
SELECT username FROM USERS WHERE username='$username' and password='$password';
很明显,这段代码存在SQL注入漏洞,但它本身并不能对系统造成什么影响(仅是泄露数据),所以我们案例中的新手渗透工程师可以大胆地随意注入’ or 1=1 --。但如果是下面这段查询代码呢?这段代码用于更新用户的电子邮箱:
UPDATE USERS set email='$email' where username='$username';
这回,如果渗透工程师还在大意地随便乱用’ or 1=1 --,则后果不堪设想。
UPDATE USERS set email=''; -- where username = '$username';
username |
password |
|
|
1 |
jake |
reynolds |
|
2 |
net |
spi |
|
3 |
johnjacob |
jingle |
公司数据库中的所有电子邮件都被删除了。假设这个公司没有完整的备份,无法恢复这些邮件,那接下来该怎么办?更新一下简历,准备去面试吧– 这个工程师可以和这份工作说再见了。
如何保住你的工作
有几种办法可以避免上述的失误,而它们的关键其实都在于多花一秒时间去思考服务器需要执行什么类型的查询来实现被测试的功能。咱们换个角度来看刚才执行的这个查询。
UPDATE USERS set email='$email' where username='$username';
虽然在黑盒测试中我们看不到服务器上执行的代码,但我们能看到浏览器向它发送的请求,如下:
POST /updateEmail HTTP/1.1Host: jakereynolds.coConnection: closeContent-Length: 165Content-Type: application/x-www-form-urlencodedusername=jake&[email protected]
从这个HTTP请求的格式和服务端点的名称应该不难推断出服务器需要执行的查询。很明显,这个服务端点的用途是更新用户的电邮,那必然会执行UPDATE查询。我们的目标就是找到既可证明SQL注入漏洞存在,又不会造成破坏的注入载荷,并用其进行测试。
我们先来试试串联两个字符串。我们先用一个单引号结束当前的字符串,然后用相应的串联运算符将另一个字符串与其串联。如果数据库成功将两个字符串串联在一起,我们就能得知它存在SQL注入漏洞了。
MSSQL |
MySQL |
Oracle |
'+'concat |
con' 'cat' |
'||'concat |
虽然每个数据库系统的语法不太一样,但它们的功效都等同于:
UPDATE USERS set email=''+'concat' where username='jake';
若是成功,那么数据库的内容将被更新为:
username |
password |
|
|
1 |
jake |
reynolds |
concat |
2 |
net |
spi |
|
3 |
johnjacob |
jingle |
再来看看一些其他办法。MySQL和Oracle都允许对数字字符串进行算术运算。对于MSSQL,如果某个注入点不是字符串,而是整数值,则可以直接注入数字进行算术运算。
MSSQL |
MySQL |
Oracle |
1+1 1-1 1/1 1*1 |
'='test 1'+'1 1'-'1 1'/'1 1'*'1 |
1'+'1 1'-'1 1'/'1 1'*'1 |
举例如下:
UPDATE USERS set email='1'+'1' where username='jake';
username |
password |
|
|
1 |
jake |
reynolds |
2 |
2 |
net |
spi |
|
3 |
johnjacob |
jingle |
我们现在已经有办法根据不同数据库系统进行安全的SQL注入测试了。但如果我们不知道服务器运行的具体是哪个数据库系统,该怎么办?有没有任何一个载荷,可以通用于这三种RDBMS?
在做了一系列尝试后,我没能发现任何一个在这三种数据库系统中功能完全一样的运算符或函数。但是,我们并不需要这个载荷在对每种系统效果都一模一样,只要它能核实注入漏洞的存在就够了。
如之前所述,在MSSQL中“+”运算符被用于串联字符串和加法运算,而在 MySQL和Oracle中它只被用于加法运算。也就是说,在MSSQL中,表达式‘1’+‘1’ 会被评估为‘11’,而在MySQL和Oracle中它则会被评估为‘2’。所以,以下载荷便可通用于测试全三种数据库系统:
MSSQL |
MySQL |
Oracle |
1'+'1 |
1'+'1 |
1'+'1 |
UPDATE USERS set email='1'+'1' where username='jake';
username |
password |
|
|
1 |
jake |
reynolds |
2 |
2 |
net |
spi |
|
3 |
johnjacob |
jingle |
若数据库是 MSSQL ,则新的值会是‘11’。成功了!我们现在可以利用这个载荷随意对最常见的三种RDBMS进行测试,并且不用担心会造成任何不可逆转的影响。
往期精彩
登陆页面的检测及渗透
渗透实战篇(一)
渗透测试信息收集的方法
常见Web中间件漏洞利用及修复方法
内网渗透 | 流量转发场景测试
Waf从入门到Bypass
实战渗透-看我如何拿下学校的大屏幕
技术篇:bulldog水平垂直越权+命令执行+提权
渗透工具实战技巧大合集 | 先收藏点赞再转发一气呵成
感兴趣的可以点个关注!!!
本文始发于微信公众号(安全先师):如何安全地进行SQL注入测试
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论