SECCON Beginners CTF 2019 Writeup
SECCON Beginners CTF 2019 について
SECCON Beginners CTF 2019が開催されました。
2019月5月25日 午後3時~5月26日 午後3時(24時間)
https://score.beginners.seccon.jp/score.beginners.seccon.jp
今回は、4人のチームで参加しました。結果は、72位で1291点でした。 これまで参加してきたDEFCONやTSGなどと違って易しい問題が多かったです。
SECCON Beginners CTF 2019 Writeup
(7問)
私が実際に解いた7つの問題だけ紹介します。
[Web] Ramen
問題
解答例
https://ramen.quals.beginners.seccon.jp にアクセスしてみると、ラーメン屋の店員紹介ページが表示されました。
名前の入力欄があるようです。 試しに「'」と入力してみると、PHPのエラーが表示されました。SQLインジェクションができそうです。
Fatal error: Uncaught Error: Call to a member function fetchAll() on boolean in /var/www/web/public/index.php:11 Stack trace: #0 {main} thrown in /var/www/web/public/index.php on line 11
いろいろ入力してみると、以下の入力でテーブル名一覧を取得することができました。
' UNION SELECT table_name, null FROM INFORMATION_SCHEMA.COLUMNS --
省略
flagというテーブルがあるようです。 以下のように入力してみると、フラグを取得することができました。
' UNION SELECT flag, null FROM flag --
FLAG
ctf4b{a_simple_sql_injection_with_union_select}
[Web] katsudon
問題
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
解答例
とりあえず、https://katsudon.quals.beginners.seccon.jp にアクセスしてみると、3つのシリアルコードが書かれていました。
BAhJIhByZWl3YWhhbnRlbgY6BkVU--bc5614afcef948624ebc137432c2dcdc624111b6 BAhJIhNoZWlzZWlzaG9rdWRvdQY6BkVU--f9aa81191fb073fb87bfa71b20c02bf3a30d1b10 BAhJIhRyZXN0YXVyYW50c2hvd2EGOgZFVA==--a78497e11151cffc45af945a1a243138b6084140
最後のシリアルコードだけ==という文字列があり、Base64でエンコードされているように見えます。 それぞれデコードしてみると、以下の通りになり、店名が出てきました。
..I".reiwahanten.:.ET ..I".heiseishokudou.:.ET ..I".restaurantshowa.:.ET
次に https://katsudon.quals.beginners.seccon.jp/flag に確認すると、シリアルコードだけが書かれていました。
BAhJIiVjdGY0YntLMzNQX1kwVVJfNTNDUjM3X0szWV9CNDUzfQY6BkVU--0def7fcd357f759fe8da819edd081a3a73b6052a
同様にBase64でデコードしてみると、フラグが出てきました。
..I"%ctf4b{K33P_Y0UR_53CR37_K3Y_B453}.:.ET
フラグ
ctf4b{K33P_Y0UR_53CR37_K3Y_B453}
[Reversing] Seccompare
問題
https://score.beginners.seccon.jp/files/seccompare_44d43f6a4d247e65c712d7379157d6a9.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ファイルだったので、Ghidraで開いてみました。
1文字ずつ値を代入し、strcmpで比較しているようです。 ltraceで関数呼び出しをトレース出力してみると、strcmp関数による比較処理で、フラグを確認することができました。
$ ltrace ./seccompare aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa strcmp("ctf4b{5tr1ngs_1s_n0t_en0ugh}", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...) = 2 puts("wrong"wrong ) = 6 +++ exited (status 0) +++
FLAG
ctf4b{5tr1ngs_1s_n0t_en0ugh}
[Crypto] So Tired
問題
最強の暗号を作りました。 暗号よくわからないけどきっと大丈夫!
File: so_tired.tar.gz
解答例
ダウンロードしてきたファイルにとりあえず、fileコマンドを実行しました。
$ file encrypted.txt encrypted.txt: ASCII text, with very long lines, with no line terminators
普通のテキストファイルのようなので中身を確認してみました。 末尾のほうを見ると==となっていたので、Base64でエンコードされているようです。
省略 OS79ZdkY3RZVE55QKbgtlPXoZ5vgL0L4ig5FFk07kYmt9oP4+xY8VKB7Iqh9I+5+K5v4B8HzgzA==
ここからは、CyberChefで作業しました。
まず、「From Base64」でデコードすると、zlibで圧縮されたデータが出てきました。
次に、「Zlib Inflate」で展開してみると、またBase64らしきデータが出てきました。
もう一度、「From Base64」でデコードすると、またzlibで圧縮されたデータが出てきました。
「From Base64」→「Zlib Inflate」を繰り返し展開していく問題のようです。 「Label」と「Conditional Jump」を使って、ctf4bという文字列が現れるまでループさせるとフラグを取得することができました。
FLAG
ctf4b{very_l0ng_l0ng_BASE64_3nc0ding}
[Misc] Welcome
問題
SECCON Beginners CTFのIRCチャンネルで会いましょう。
IRC: freenode.net #seccon-beginners-ctf
解答例
IRC: freenode.net と書かれていたので、freenode.netで検索すると、IRCのサービスが出てきました。
「Channels」に「#seccon-beginners-ctf」と入力して「Connect」を押すと、 SECCON Beginners CTF 2019の運営に質問するためのチャンネルに接続できました。
チャンネルの説明欄にフラグが書かれていました。
FLAG
ctf4b{welcome_to_seccon_beginners_ctf}
[Misc] containers
問題
Let's extract files from the container. https://score.beginners.seccon.jp/files/e35860e49ca3fa367e456207ebc9ff2f_containers
解答例
ダウンロードしてきたファイルにとりあえず、fileコマンドを実行しました。
$ file e35860e49ca3fa367e456207ebc9ff2f_containers e35860e49ca3fa367e456207ebc9ff2f_containers: data
dataと表示され、よく分からないのでbinwalkコマンドを実行してみました。
$ 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 1914 0x77A PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 2005 0x7D5 Zlib compressed data, compressed 2856 0xB28 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 2947 0xB83 Zlib compressed data, compressed 3666 0xE52 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 3757 0xEAD Zlib compressed data, compressed 4354 0x1102 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 4445 0x115D Zlib compressed data, compressed 5156 0x1424 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 5247 0x147F Zlib compressed data, compressed 5846 0x16D6 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 5937 0x1731 Zlib compressed data, compressed 6722 0x1A42 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 6813 0x1A9D Zlib compressed data, compressed 7757 0x1E4D PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 7848 0x1EA8 Zlib compressed data, compressed 8338 0x2092 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 8429 0x20ED Zlib compressed data, compressed 9243 0x241B PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 9334 0x2476 Zlib compressed data, compressed 10319 0x284F PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 10410 0x28AA Zlib compressed data, compressed 11042 0x2B22 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 11133 0x2B7D Zlib compressed data, compressed 12118 0x2F56 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 12209 0x2FB1 Zlib compressed data, compressed 12809 0x3209 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 12900 0x3264 Zlib compressed data, compressed 13845 0x3615 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 13936 0x3670 Zlib compressed data, compressed 14592 0x3900 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 14683 0x395B Zlib compressed data, compressed 15535 0x3CAF PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 15626 0x3D0A Zlib compressed data, compressed 16440 0x4038 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 16531 0x4093 Zlib compressed data, compressed 17313 0x43A1 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 17404 0x43FC Zlib compressed data, compressed 18218 0x472A PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 18309 0x4785 Zlib compressed data, compressed 19123 0x4AB3 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 19214 0x4B0E Zlib compressed data, compressed 19926 0x4DD6 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 20017 0x4E31 Zlib compressed data, compressed 20869 0x5185 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 20960 0x51E0 Zlib compressed data, compressed 21742 0x54EE PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 21833 0x5549 Zlib compressed data, compressed 22465 0x57C1 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 22556 0x581C Zlib compressed data, compressed 23408 0x5B70 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 23499 0x5BCB Zlib compressed data, compressed 23989 0x5DB5 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 24080 0x5E10 Zlib compressed data, compressed 24810 0x60EA PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 24901 0x6145 Zlib compressed data, compressed 25753 0x6499 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 25844 0x64F4 Zlib compressed data, compressed 26788 0x68A4 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 26879 0x68FF Zlib compressed data, compressed 27599 0x6BCF PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 27690 0x6C2A Zlib compressed data, compressed 28504 0x6F58 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 28595 0x6FB3 Zlib compressed data, compressed 29085 0x719D PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 29176 0x71F8 Zlib compressed data, compressed 29808 0x7470 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 29899 0x74CB Zlib compressed data, compressed 30844 0x787C PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 30935 0x78D7 Zlib compressed data, compressed 31524 0x7B24 PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced 31615 0x7B7F Zlib compressed data, compressed
PNG形式のデータが複数混ざっているようです。 foremostコマンドで抽出してみます。
$ foremost e35860e49ca3fa367e456207ebc9ff2f_containers Processing: e35860e49ca3fa367e456207ebc9ff2f_containers |*|
抽出したファイルを確認すると、画像に文字が書かれており、フラグになっていました。
FLAG
ctf4b{e52df60c058746a66e4ac4f34db6fc81}
[Misc] Sliding puzzle
問題
nc 133.242.50.201 24912
スライドパズルを解いてください。すべてのパズルを解き終わったとき FLAG が表示されます。
スライドパズルは以下のように表示されます。 ----------------
| 0 | 2 | 3 |
| 6 | 7 | 1 |
| 8 | 4 | 5 |
----------------0 はブランクで動かすことが可能です。操作方法は以下のとおりです。
0 : 上
1 : 右
2 : 下
3 : 左
最終的に以下の形になるように操作してください。----------------
| 0 | 1 | 2 |
| 3 | 4 | 5 |
| 6 | 7 | 8 |
----------------操作手順は以下の形式で送信してください。
1,3,2,0, ... ,2
解答例
netcatで 133.242.50.201:24912 に接続してみると、以下のように表示されました。
$ nc 133.242.50.201 24912 ---------------- | 03 | 01 | 04 | | 00 | 05 | 02 | | 06 | 07 | 08 | ---------------- 0,0,0,0,0,0 [-] Incorrect answer.
10秒でタイムアウトしてしまうようなので、プログラムを書いて解いていく問題のようです。 8パズルを解くプログラムを1から組むのは大変なので、検索していると幅優先探索で8パズルを解いているブログがありました。
上記のブログのプログラムを参考に今回の問題を解いていきます。
# 8-puzzle.py from collections import deque from pwn import * MOVE = {'U': (0, -1), 'D': (0, 1), 'L': (-1, 0), 'R': (1, 0)} # (x,y) def get_next(numbers): for d in 'UDLR': zero_index = numbers.index(0) tx, ty = zero_index % 3 + MOVE[d][0], zero_index // 3 + MOVE[d][1] if 0 <= tx < 3 and 0 <= ty < 3: target_index = ty * 3 + tx result = list(numbers) result[zero_index], result[target_index] = numbers[target_index], 0 yield d, tuple(result) def checkio(puzzle): queue = deque([(tuple(n for line in puzzle for n in line), '')]) seen = set() while queue: numbers, route = queue.popleft() seen.add(numbers) # if numbers == (1, 2, 3, 4, 5, 6, 7, 8, 0): if numbers == (0, 1, 2, 3, 4, 5, 6, 7, 8): return route for direction, new_numbers in get_next(numbers): if new_numbers not in seen: queue.append((new_numbers, route + direction)) p = remote('133.242.50.201', 24912) count = 1 while True: try: puzzle = [] for _ in range(3): p.readuntil('| ') read_line = p.readline().strip().replace(' ', '').split('|') puzzle_row = [int(read_line[0]), int(read_line[1]), int(read_line[2])] puzzle.append(puzzle_row) answer_UDLR = checkio(puzzle) answer = answer_UDLR \ .replace('U', '0,') \ .replace('D', '2,') \ .replace('L', '3,') \ .replace('R', '1,')[:-1] p.sendline(answer) print('-----' + str(count) + '-----') print(puzzle) print(answer) count += 1 except EOFError: break p.interactive()
上記のプログラムを実行してみると、100問解いた後にフラグが表示されました。
$ python 8-puzzle.py [+] Opening connection to 133.242.50.201 on port 24912: Done -----1----- [[0, 2, 5], [1, 3, 8], [6, 4, 7]] 2,1,2,1,0,0,3,3 -----2----- [[4, 3, 2], [6, 1, 8], [0, 5, 7]] 0,0,1,2,2,1,0,3,3,0 -----3----- [[1, 2, 0], [3, 4, 5], [6, 7, 8]] 3,3 -----4----- [[1, 2, 0], [3, 4, 5], [6, 7, 8]] 3,3 -----5----- [[1, 2, 5], [3, 4, 0], [6, 7, 8]] 0,3,3 省略 -----96----- [[1, 4, 2], [6, 3, 5], [0, 7, 8]] 0,1,0,3 -----97----- [[1, 4, 2], [3, 0, 7], [6, 8, 5]] 1,2,3,0,0,3 -----98----- [[3, 1, 2], [7, 6, 5], [0, 4, 8]] 0,1,2,3,0,0 -----99----- [[3, 1, 2], [0, 7, 5], [4, 6, 8]] 2,1,0,3,0 -----100----- [[1, 2, 0], [3, 4, 5], [6, 7, 8]] 3,3 [*] Switching to interactive mode ---------------- [+] Congratulations! ctf4b{fe6f512c15daf77a2f93b6a5771af2f723422c72} [*] Got EOF while reading in interactive
FLAG
ctf4b{fe6f512c15daf77a2f93b6a5771af2f723422c72}