はまやんはまやんはまやん

hamayanhamayan's blog

Flatt Security mini CTF #4 Writeups

Flatt Security mini CTF #4に行ってきました。

Self

Welcome to Mini CTF #3!
あなたは管理者になれますか?

管理者になってGET /v1/flagを叩いてください!

2nd blood。うれしい。

とりあえずBurpを開いて、もらったサイトを眺めてみる。
一方はwebサイトが立ち上がり、ログイン画面となる。もう一方はtokenが無いと動かないようでAPI用のエンドポイントのようだ。
adminでログインするんだろうとなーと思っているとヒントが与えられる。

操作方法がわからない?
2024-01-16 19:10:04
AWSSDKCLI は基本的に命名が一貫しているので、調べやすいかも?
新規登録は sign-up
ログインは initiate-auth
https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/#cli-aws-cognito-idp

Mini CTF #3!の反省でヒントが今回はたくさん出るらしい。
ありがたい。
もらったキーワードで検索してみる。

sign-upで検索するとREADME.mdで以下のような説明が出てくる。

CLIENT_ID=<user-pool-client-id>
USERNAME=<username>
PASSWORD=<password>
aws cognito-idp sign-up \
  --region "ap-northeast-1" \
  --client-id $CLIENT_ID \
  --username  $USER_NAME \
  --password $PASSWORD \
  --no-sign-request

CLIENT_IDか…と思いながらBurpの履歴を見ていくと、cognito-idp.ap-northeast-1.amazonaws.comへのPOST /でClientIdが渡されていることに気が付く。
ということで、上の説明を参考にユーザーを作ってみる。

aws cognito-idp sign-up --region "ap-northeast-1" --client-id "21[reducted]9t" --username "evilman" --password "fdsajkj3irfjkjfisadj4A!" --no-sign-request

すると、なんか作れてそうな応答が帰ってくる。
これでevilman:fdsajkj3irfjkjfisadj4A!でログインしてみるとログインできるようにはなった。
You are not Admin user.
ok.

adminで検索するとself/lib/api/functions/authorizer.tsに以下のような部分が見つかる。

    if (payload["custom:role"] !== "admin") {
      return denyPolicy(event.methodArn, "not admin");
    }

ここですね。custom:roleとやらをadminにすればフラグがもらえそう。
どうすればいいかなと思っているとちょうどヒントが降ってくる。

ユーザーの属性の特性、どないせい?
2024-01-16 19:15:26

ユーザーの属性に対するアクセス制御のデフォルト値は?
ユーザーの作成や属性の変更は、アプリケーションクライアントや IAM の権限によって制御することが可能です。 アプリケーションクライアントの属性の権限は、デフォルトでは全ての属性を許可しています。このため、アプリケーションクライアントの属性の制御は明示的に行う必要があります。

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/user-pool-settings-attributes.html#user-pool-settings-attribute-permissions-and-scopes

カスタム属性はどうやって追加するの?
このドキュメントを参考にしてください。 https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/user-pool-settings-attributes.html#user-pool-settings-custom-attributes

そう。それがやりたいことなんだけれど、やり方が分からない。
でも何とかして外部からカスタム属性をつけることができそうなのはヒントから分かる。
aws cognito-idp sign-upで属性を追加できないか?というアイデアが出る。
aws cognito-idp sign-up helpを眺めてみる。

...
          [--user-attributes <value>]
          [--validation-data <value>]
          [--analytics-metadata <value>]
          [--user-context-data <value>]
          [--client-metadata <value>]
...

なんかそれっぽいオプションがたくさんありますね。
ここから熱烈ググると以下の記述を見つける。

aws cognito-idp update-user-attributes --access-token ACCESS_TOKEN --user-attributes Name="nickname",Value="Dan" https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/update-user-attributes.html#:~:text=aws%20cognito%2Didp%20update%2Duser%2Dattributes%20%2D%2Daccess%2Dtoken%20ACCESS_TOKEN%20%2D%2Duser%2Dattributes%20Name%3D%22nickname%22%2CValue%3D%22Dan%22

まさに求めていたものがそこにあった。
update-user-attributesについてのものだが、--user-attributes自体の用法は同じだろうということで以下のようにやってみると成功する。

aws cognito-idp sign-up --region "ap-northeast-1" --client-id "21[reducted]9t" --username "evilman2" --password "fdsajkj3irfjkjfisadj4A!" --no-sign-request --user-attributes Name="custom:role",Value="admin"

これでevilman2:fdsajkj3irfjkjfisadj4A!でログインするとフラグが得られた。

ちなみに、この後にも2つヒントが出ていた。

認可?どこでやってるんだろう?
2024-01-16 19:20:21
このアプリケーションでは、API Gateway のカスタムオーソライザーを利用しています。 https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html
ファイルは、self/lib/api/functions/authorizer.js にあります。

それと

必要な属性は?
2024-01-16 19:25:15
self/lib/api/functions/authorizer.js では、どのような処理をしていましたか? 後ろで待ち構える Lambda Function には、context という引数が渡されます。

あと更なるヒントが口頭でも出ていた。

「Flatt Security Blogにあるかもな~」

この後解説も聞いたが、ソースコードをちゃんと読んでおらず、いかに雰囲気で問題を解いているかが分かる。

Miss Box 解けなかった

令和最新版の画像共有サービス「File Box Advance」を使ってみました!
とても便利!いっぱい使ってみてください!
あと、もし何か面白い画像があったら管理者に教えてくださいね!
使い方は添付ファイルを見てください!

解けなかったので以下感想です。
記憶を思い出せる限り書きだしただけなので、興味のある方のみどうぞ。

画像ファイルをアップロードできるサイトが与えられる。
とりあえず、サイトを閲覧してみると、ReportができるのでXSS問題かなと考えていた。

既にヒントが出ているのでヒントを見てみる。

前回の続きと、その派生を考えよう
2024-01-16 19:24:59
self と同じように属性に何か鍵があるかも?

属性を変える必要がある。 属性を同じように持ってきている部分を探してみるとmiss_box/infra/lib/api/functions/authorizer.tsにあった。

    return allowPolicy(event.methodArn, {
      tenant: payload["custom:tenant"],
    });

何に対するポリシーが許可されるのか分からないが、custom:tenantに入れ込んだテナントが許可されるっぽい。
テナントってなんだと思いながら巡回するがよく分からない。

まあ、気を取り直して、目玉機能のファイルアップロードの部分について読んでいこう。
miss_box/infra/lib/api/functions/signedUrlPut.tsを開いて中身を見てみると、拡張子、ファイルサイズ、Content-Typeのチェックをしている。
突破できなさそうに見えるな…と思いながらも、これを何とかするんだろうなぁと思いを巡らすがアイデアは特に出ず。

ヒントが出る。

アップロード用の署名付き URL はどこで作ってるんだろう?
2024-01-16 19:34:49
miss_box/infra/lib/api/functions/signedUrlPut.ts を読んでみると、どうやら S3 の署名付き URL を作っている条件が書かれているようです。

Burpでの履歴を眺めてみると、アップロード時は

  1. rp065n90h5.execute-api.ap-northeast-1.amazonaws.comPOST /v1/box/signed-url/putjson形式でメタデータを入れ込む
  2. 応答に署名付きURLが帰ってくる
  3. それを使ってmissbox-web-web-host-bucket.s3.ap-northeast-1.amazonaws.comにPOSTでファイルアップロード

という流れになっている。これは着目すべきポイントになりそう。
しかも中身を見ると X-Amz-SignedHeaders=content-length%3Bhost というのが含まれていて、Content-Typeが含まれていない。
これは差し込めるのでは?

…とさらっと書いているが、思考が行ったり来たりして時間内に考察できていたのはここまで。
ここまでの考察でContent-Typeを自由に変更する所までは成功している。
次の問題はどうやって管理者にこのファイルを「元のサイトのドメインで」踏ませるかであり、ここにもう1つ超えるべき壁があった。

復習したらこの続きを追記するかもですが、st98さんの解説を見る方が遥かに良いです。
nanimokangaeteinai.hateblo.jp