Flatt Security Blog

株式会社Flatt Securityの公式ブログです。プロダクト開発やプロダクトセキュリティに関する技術的な知見・トレンドを伝える記事を発信しています。

株式会社Flatt Securityの公式ブログです。
プロダクト開発やプロダクトセキュリティに関する技術的な知見・トレンドを伝える記事を発信しています。

「推測不可能性」だけで安心?セキュアなURL生成について考える

f:id:flattsecurity:20220228101414p:plain

はじめに

こんにちは。株式会社Flatt Securityセキュリティエンジニアの山川です。

多くのWebサービスにおいて、ブログ記事やドキュメントの公開・下書き共有のためにURLを発行する機能が存在していると思います。このようなURLに関して、第三者に知られたくない場合「推測不可能なURL」を発行するといったセキュリティ観点は広く知られているかと思いますが、それ以外にはどのような観点が存在しているでしょうか。

本稿では、Webサービス上で発行されるURLに関して「どういったセキュリティの観点があるか」や「脆弱性・リスクに対する対策」についていくつかのパターンを前提に解説します。

前提

読者の皆様と前提を揃えるために、題材として1つのWebアプリケーション例を用いて解説していきます。

Webアプリケーションの題材は宿泊施設紹介プラットフォームです。 ユーザーである旅行会社が様々な提携先の旅館やホテルを紹介するために利用するブログのようなWebページです。

Webアプリケーションの機能を以下にまとめています。

機能一覧

f:id:flattsecurity:20220215205250p:plain

  • 記事の投稿
    • 予約投稿機能
    • 記事の下書き保存機能→プレビューURLが発行されます
  • 期間限定情報の配信
    • 割引クーポンコードが載っている静的ページを表示

セキュリティ観点

本章では、上記アプリケーションで記事を下書き保存した際に発行される 未公開URL に関して開発者が気をつけるべきセキュリティ観点を説明していきます。

パターン1: URLが推測可能かつアクセス制御に不備がある場合

パターン1はURLが推測可能かつアクセス制御に不備がある場合です。

未公開のつもりの記事下書きページURLが第三者から容易に推測可能であれば、第三者からの意図しないアクセスが行われる可能性があります。 このとき正しくログインユーザーと記事を紐付けたアクセス制御が行われていれば問題ありませんが、行われていない場合には情報漏えいに繋がります。

具体的に、第三者に推測可能なURL例を3つ紹介します。他にも、ここで紹介している例をいくつか組み合わせたようなものや、これ以外にも推測可能なものはあるでしょう。

連番になっている

単純に記事番号などをそのままURLに用いてしまっている場合です。このような場合は直感的にただ数字を増やしたり減らしたりするだけで容易にアクセス可能なことが伺えます。

日付が入っている

記事の作成日時をURLに用いてしまっている場合です。もう少し詳細にして秒やミリ秒単位のものが含まれていても同様に推測可能になるでしょう。

単純な値を用いて変換されたハッシュ値

3つ目は単純な文字列から計算されたハッシュ値が使われている場合です。 例えば最初の連番の例に対策を入れようと “1” を単純にハッシュ値に変換した場合、一見推測不可能なランダムの文字列に見えますが変換前文字列の捜索を行うツールを用いたり、自分で簡単な実験をしてみることで推測される可能性があります。

(“1”のmd5ハッシュ値をURLにしているものです)

パターン2: URLが推測不可能かつアクセス制御に不備がある場合

第三者から推測不可能なURLになっていてもアクセス制御の不備が存在していると、Webページの利用者の予期していない方法でURLが漏洩して第三者にアクセスされることがあります。したがって、第三者に推測されないURLを発行しているだけで、安心しないことが大切です。

こちらも複数の漏洩パターンが考えられますが、その例を紹介します。

未公開URLを外部ブックマークサービスでブックマークしてしまう

記事の予約投稿時に発行された未公開URLをはてなブックマークのようなソーシャルブックマークサービスでブックマークしてしまっていた場合は、未公開URLの情報が第三者に知られてしまいます。

利用者側のミスと言えばそれまでですが、機微な情報を扱うサービスも増えている現状、ヒューマンエラー対策が必要な場面も存在するでしょう。

ソースコードやAPIレスポンスからの漏洩

HTMLの<a>タグhref属性に未公開URLが含まれてしまっており、DevToolsなどを用いて容易に確認できてしまう場合や、HTMLには含まれていないがAPIレスポンス上に未公開URLの情報が含まれている場合などのケースも考えられます。

例えば、SPAでフロントエンドを構築しており、以下のようなAPIレスポンスのvisible値で判定して、表示するコンテンツを操作している場合、サーバーとの通信内容を確認すると未公開URLを知ることができます。

[
  {
    "url": "http://example.com/public",
    "visible": true
  },
  {
    "url": "http://example.com/limited",
    "visible": false
  }
]

総当りでアクセスされる

ランダムな値がURLに含まれていても、ランダム値の桁数が小さい場合や文字種が少ない場合です。このような場合は推測不可能であってもプログラムなどを用いて総当りでアクセスされることで非公開ページにアクセスされる可能性があります。

結局、URLを発行するアプリケーションの運用はどうしたら良いの?

ここまでにURLを発行するアプリケーションにおける問題点を解説しましたが、では実際にどのように対策・運用を行うと良いのかについてを提示します。

根本対策

ユーザー規模が大きくなるほど、パターン2のような推測不可能なケースでも意図せず未公開URLが暴露する可能性が高まります。

なので、WebアプリケーションがURL発行するときに重要なセキュリティ対策としては、URLにアクセスできるユーザーを制限しておき、URLにアクセスされた際に適切なチェックを行う「アクセス制御」が一番重要です。

仕様ごとの運用パターン

Webアプリケーションの用途によってはアクセス制御が必要ない仕様パターンや非公開のドキュメントを一時的に公開するようなパターンもあります。 そのような場合にどのような運用を行うとよいのかについても説明します。

アクセス制御をしない場合の運用方法

本記事で提示したWebアプリケーション例では「記事の投稿」機能に当たるものです。

f:id:flattsecurity:20220215205356p:plain

記事を公開した後に発行されるURLは、記事を一般公開するために発行されたのでアクセス制御をする必要がありません。

しかし、スクレイピング等をされないために、SecureRandomのような暗号論的疑似乱数を利用した値を使うようにしてください。

一時的にアクセスを許可する場合の運用方法

本記事で提示したWebアプリケーション例では「期間限定情報の配信」の機能にあたります。

f:id:flattsecurity:20220215205417p:plain

ユースケースとして、旅行会社が繁忙期に会員を増やすため、会員ではない人ももらえる1時間のタイムセールクーポンを配布したいとします。

その際、旅行会社は「期間限定情報の配信」機能を利用して1時間だけ有効なURLを発行します。

このような機能を実装するにあたって、有効期限の処理には2つの方法があります。

  1. 処理を自前で実装する
  2. 外部のサービスを活用する

1は自然と生まれる選択肢だと思いますが、先ほどのクライアントサイドでvisible値を判定している例のように、誤った実装方針を採用すると有効期限が機能しない要因になり得ます。また、他にも不適切な仕様・実装に起因する脆弱性を生んでしまうかもしれません。

多様なIDaaSサービスが提供され、認証機能のフルスクラッチを代替する事例が増えているように、2の「外部サービスを活用する」も一つの手段です。ここではAWS S3の署名付きURLを紹介します。

AWS S3 署名付きURLを利用する

期限付き公開URLの例としてAWSのS3でプライベートのオブジェクトを共有する際に署名付きURLを発行する方法について述べます。 署名付きURLとはある一定の時間(1時間など)のみ、本来権限を持っていないユーザーがあるアクションをできるようにするために発行するURLです。[1]

  1. Amazon S3コンソール上のオブジェクトリストで署名付きURLを発行したいオブジェクトを選択します。
  2. アクションメニューで「署名付きURLの作成」を選択します。
  3. 署名付きURLの有効期限を設定して「署名付きURLを作成」ボタンを押下すると生成されます。

f:id:flattsecurity:20220208142548p:plain

厳密にアクセス制御する場合の運用方法

Webアプリケーション例で「記事の下書き保存」機能の利用時に発行されたプレビューURLを取り上げます。

f:id:flattsecurity:20220215205448p:plain

下書き状態の記事はまだ未完成の記事であり、記事掲載元との調整も済んでいないため、公開されるべきでない情報であるものとします。

その場合、仮にプレビューURLがセキュリティ観点のパターン2のようなユースケースで漏洩することになっても、第三者がアクセスできないように適切にアクセス制御するべきです。

アクセス制御の具体的な実装方法

一般的なアクセス制御方法を紹介します。

1つ目はURLにアクセスした際にサービスへのサインインとユーザー単位での認可を必須にすることです。 一番オーソドックスな実装方法ですが、URLを共有されたユーザーはURL先にアクセスするために、アカウント作成が必須になります。

2つ目はURLの発行時にユーザーにパスワードを発行する方法です。

こちらの実装だとURLにアクセスするユーザーの認証をしなくて良いため、URLを共有されたユーザーはアカウントを作成する必要がありません。 しかし、URL生成時に発行されるパスワードの共有範囲を間違えないようにパスワードの取り扱いには要注意です。

また、万が一、アクセス制御の不備があってもスクレイピング等で自動的にアクセスされてしまうことを防ぐために、発行するURLは第三者に推測されないような文字列にすることが推奨されます。 他にも、こんな実装方法があるよ〜というのがあればぜひはてブのコメント等で教えてください。

どれくらいの厳格さでアクセス制御をすれば良いのか考えるヒント

ここまで、サンプルアプリケーションを例に第三者とURLを共有する際の仕様ごとの運用パターンについて紹介しました。

一方で、アクセス制御とユーザビリティは多くの場合トレードオフになってしまうので、どういう基準でどういったアクセス制御を選択すれば良いのか悩んでしまうところでもあるため、考慮した方が良いことを述べます。

例として、サンプルアプリケーションの下書き機能を取り上げます。 上記の「厳密にアクセス制御する場合の運用方法」では、記事に書かれている内容を以下のように限定しました。

下書き状態の記事はまだ未完成の記事であり、記事掲載元との調整も済んでいないため、公開されるべきでない情報であるものとします。

このように公開予定の記事の内容は考慮して判断する必要があります。

例えば、コンシューマ向けのブログサービスなど、重要な情報が載らないアプリケーションであればアクセス制御よりURL単体で共有できるUXを優先する場合も考えられます。

一方で、発売前の商品情報など、未公開情報が漏洩した時の想定被害・インパクトが特に上場企業が関わってくる場合大きいため、そういった情報を扱うアプリケーションであれば厳密にアクセス制御できることが求められます。

このように、アプリケーション上に掲載される情報のビジネス上の特性によって仕様も変わるため、上記の内容も考慮した上でどれくらい厳格にアクセス制御を実装するのか考えるようにしてください。

終わりに

本稿では、Webアプリケーション上で発行されるURLに関するセキュリティ観点について、具体例を交えながら解説しました。

大切なことは、他ユーザーもしくは不特定多数と情報を共有するためにURLを発行する機能をWebアプリケーション上で実装する際、用途に合わせた適切なアクセス制御を実施することです。

アクセス制御に限らず、アプリケーションの仕様やビジネスロジックに照らし合わせなければ発見できない脆弱性を洗い出すため、Flatt Securityセキュリティエンジニアの手動検査とツールを組み合わせたセキュリティ診断サービスを提供しています。

過去に診断を実施したが不安や課題がある、予算やスケジュールに制約がありどのように診断を進めるべきか悩んでいる等、お困り事にあわせて対応策をご提案いたしますので、まずはお気軽にお問い合わせください。

お問い合わせは下記リンクよりどうぞ。

https://flatt.tech/assessment/contact

Flatt Securityはセキュリティに関する様々な発信を行っています。 最新情報を見逃さないよう、公式Twitterのフォローをぜひお願いします!

twitter.com

ここまでお読みいただきありがとうございました!