PicoCTF 2023に参加しました!
忙しくてあまり問題解けなかったのですが、自分の解いた問題のwrite-up書きます。
本当は、もっと問題解きたかった。。。
Web Exploitation
findme
「ユーザー名をtest、パスワードをtest!として送信し、フォームのテストにご協力ください!」ということで、とりあえずサイトにアクセスしてみます。
すると下記のような画面に遷移。
問題文に書かれている通りにusernameにtest、passwordにtest!を入力してみます。
すると下記のような画面に遷移。
確認すると、どうやら友人にこのページにリダイレクトされたが何もフラッグを見つけられなかったという文言が。
そこで、OWASP ZAPやBurp suiteなどのツールを用いて通信をのぞいてみました
今回はOWASP ZAPを用いました。
通信を確認してみると、loginページからhomeのページに遷移するまでに
/next-page/id=cGljb0NURntwcm94aWVzX2Fs
/next-page/id=bF90aGVfd2F5X2JlNzE2ZDhlfQ==
の2つのページにアクセスしていることが分かりました。
その中の一つの通信を確認してみると、Javascriptで強制的に画面を遷移させているようでした。
タイトルもflagとなっており、この中にflagがあるようなので、この中でflagとなりそうな怪しいものとして、URLのid=以降の文字に注目してみます。
/next-page/id=cGljb0NURntwcm94aWVzX2Fs
/next-page/id=bF90aGVfd2F5X2JlNzE2ZDhlfQ==
二つ目の文字列が最後==で終わっているので、base64でエンコードされたものだと疑ってみます。
CyberChefを用いて一つ目の文字列をデコードしてみるとpicoCTF{proxies_al
というflagの一部と思われる文字列が出てきました。
そこで、二つ目を一つ目の後ろに連結させて再びデコードすると
picoCTF{proxies_all_the_way_be716d8e}
More SQLi
「このページでflagを見つけることはできますか?」ということで、サイトにアクセスしてみます。
すると下記のような画面に遷移。
問題文にSQLiと書いてあり、SQLインジェクションの問題だと思われるので、
usernameは適当で、passwordに' or '1' = '1';--
というSQLインジェクションでは定番の文字列を入れてみます。
すると、画面遷移し新たなページが現れました。
だが、いろいろやってもこのページにはflagはないらしいです。
どうやらloginに成功するだけで良かったようです。
picoCTF{G3tting_5QL_1nJ3c7I0N_l1k3_y0u_sh0ulD_3b0fca37}
Java Code Analysis!?!
どうやら、BookShelf Picoというプレミアムオンラインブックリーディングサービスを作ったらしいです。製作者はこのウェブサイトは超安全だと信じているようです。
やることとしては、サイト内の"Flag"という本を読むことです。
とりあえず、サイトを開くとまず下記のような画面に遷移します。
問題文に示されている通り、Email:user、password:userでログインしてみると、下記のような画面に遷移しました。
"Flag"という本を読むことが目標なので、一番右の"Flag"を開いてみるとどうやらロックされていて見れないようです。
どうやら、このサイトにはFree
やPremium
、Admin
などのRoleが存在するようで、該当するRoleに割り当てられていないユーザはその本を読むことができないようです。
"Flag"はAdminのRoleに割り当てられているユーザが読めるものなので、Freeに割り当てられている自分たちはロックがかけられ読むことができなかったようです。
ここで、もし自分のRoleをFreeからAdminに変えることができたのならば、この"Flag"を見ることができそうです。
ログイン時の通信を見てみます。
レスポンスとしてJWTのTokenが送られてきているようです。
JWTとは、Json Web Tokenの略で、Json形式で認証やアクセス制御についての情報を記述し一定の手順で符号化したトークンを生成することができます。このトークンをやり取りすることで、認証情報などを安全にやり取りすることができます。
送られてきたJWTのトークンはbase64でエンコードされているので、base64でデコードしてみます。
JWTのデコードなどは下記サイトを使うと良いです。
https://jwt.io/
roleやuserIdなどの情報を読み取ることができます。
ここで、roleなどを自分の手で変更してそれをbase64で再びエンコードすればAdminとして認証してくれそうですが、JWTにはちゃんと公開鍵暗号に基づく改ざん検知の仕組みがあります。つまり秘密鍵がないとこちら側で改ざんすることはできません。
ここで、配布されるソースコードを見てみます。
/src/main/java/io/github/nandandesai/pico/security/SecretGenerator.java
に秘密鍵を生成するコードが書かれています。
これよく見てみると、23行目秘密鍵がハードエンコーディングされているようです。
generateRandomStringは本来はランダムな文字列を生成する関数のようですが、ただ1234
を返しています。
おそらく、これが秘密鍵になるようなので、これを用いてJWTのトークンを改ざんします。
まず、該当の本のデータを取得するAPIは下記でした。
/base/books/pdf/{bookId}
例えば、/base/books/pdf/3
とすると、LITTLE BROTHERの本のデータをPDFとして取得できます。
"Flag"の本のデータは/base/books/pdf/5
でした。
試しに、roleだけをAdminに変更しデータを取得してみます。
JWTをデコードできるサイトでは、JWTの編集もできるので、それで変更をします。
秘密鍵1234
を一番下ののVERIFY SIGNATUREに入れ、PAYLOADのFreeをAdminへ変更します。
おそらく、userIdとemailの情報をAdminのroleを持つユーザの情報に変える必要があるので、それを調べます。
ユーザの情報を取得するAPIは下記でした。
/base/users/{userId}
例えば、/base/users/1
とすると、最初にログインしたuserのユーザ情報を取得することができます。
このユーザ情報を取得する際にも、JWTのトークンが必要になり、Freeのroleが割り当てられたユーザでは、Adminのユーザ情報を取得することはできませんでしたが、PDFのデータ取得とは異なり、今回は、roleだけを改ざんすることでAdminのユーザ情報を取得することができました。
Adminのroleを持つuserIdとemailの情報を取得できたので、JWTトークンを改ざんし、PDFを取得してみます。
picoCTF{w34k_jwt_n0t_g00d_ca4d9701}
補足として、今回はJWTの署名アルゴリズムにHS256
が使われていましたが、None
を指定することもできて、これを許可していると改ざん検知の機能をすり抜けることができてしまいます。この問題では対策されていたようですが、JWTを使ってアプリケーションなど作る時は注意が必要です。
Binary Exploitation
VNE
どうやら、ディレクトリをroot権限でリストできるプログラムを制作したようです。
まず、下記コマンドで問題のサーバに接続します。
※-p
はポート番号の指定です。出題された問題に合わせて変更をしてください。
ssh -p 57344 ctf-player@saturn.picoctf.net
そして、下記は問題サーバに接続した後にls
コマンドを打った結果です。
どうやら、bin
というのが今回制作したプログラムのようです。
bin
を実行してみます。
SECRET_DIR
という環境変数を設定しないと、このプログラムは動かないようです。
そして、この環境変数に設定したディレクトリをroot権限として参照することができるようになるようです。
下記コマンドで、環境変数を設定をし/root
を参照してみます。
export SECRET_DIR=/root
おそらく、このプログラムにはコマンドインジェクションの脆弱性がありそうなので、下記コマンドで再度環境変数を設定しなおします。
export SECRET_DIR="/root | cat /root/flag.txt"
flag.txtを参照できました。
picoCTF{Power_t0_man!pul4t3_3nv_1ac0e5a3}
おそらくこのプログラムは、SECRET_DIRの環境変数の値を特に何も加工することなくプログラム内で使用し、結果的にコマンドインジェクションが可能となっています。
ls {SECRET_DIR}
環境変数の値を/root
などとすれば、ls /root
となり/root配下を参照することができますが、
環境変数の値を/root | cat /root/flag.txt
などとすると、ls /root | cat /root/flag.txt
となり、flag.txtを参照できてしまいます。
成績
大学の研究室でチームを組んで参加しました。
メンバーの皆様、あまり参加できなくてすみません。
自分は上記の4問解き、800pt分貢献しました。
結果は、全体で716/6925位、日本で15/77位でした!
最後に
暇があったら難易度の高い問題もたくさん解きたかったです。
後、個人的にJava Code Analysis!?!の問題は前にJWT関連の問題をやっていたので、その良い復習になりました。
面白かったです!