💀

SSRF(サーバーサイド・リクエストフォージェリ)攻撃について知ってもらう

2024/07/29に公開

あなたのWebサービスは大丈夫?
私は、古いWebサイトのリニューアルに携わった経験のなかで、いくつかのSSRF脆弱性を目にしてきました。
最近では、フロントエンドエンジニアがサーバーコードを書くことも普通にあるので、SSRFの脆弱性について理解を深めましょう。

SSRF (Server Side Request Forgery)

SSRF,サーバーサイド・リクエストフォージェリは、サーバーに成り代わりリクエスト送信を強要する攻撃手法とその脆弱性です。

CSRFもそうですが、*RF攻撃は、その送信者に特有の権限を使って、本来意図していない細工したリクエストを送信させることで成立します。

サーバーの置かれている状況

SSRFについての詳しい説明の前に、Webアプリケーションにおいて、サーバーがいったいどんな役割をこなしているのかを再確認しましょう。
(この記事では、サーバーレスも含めてサーバーと呼んでおきます)

現代のWebサービスは、多くの場合、WebサーバーやAPIサーバーがリクエストを受け付けて、適切な認証・認可をして、背後にあるストレージとデータのやりとりをして、返却する仕組みになっているよね。

この、サーバーの背後がどうなっているのか、というシステム構成は、多岐にわたります。
また、設計のベストプラクティスとして、クライアントは、背後がどのようなシステム構成になているか意識しないことが望ましいです。(関心事の分離)

AWSなどでよくありがちな、仮想ネットワークを構成するパターンだとこんな感じ。

イントラネットに依存した業務をしている組織では、こんな構成になっていることも。

他にも、説明しきれませんが、サーバーレスだったり、クラウドネイティブだったり、コンテナネイティブだったり。
サーバーにはある特定の権限が与えられていて、サーバーにしか見られない場所にアクセスして情報の読み書きをします。
この、隠されている情報は、大抵の場合、機密性が高く、改ざんや漏洩した場合深刻な被害が出ます。

SSRF の例

サーバーに不注意なコードが存在していると、予期しないリクエストを送信されてしまいます。

え!?そんなことありうるの!?

SSRF脆弱性が野放しになっている、サンプルサイトを作ってみました。
この企業「ポンポコ・コーポ」のサイトには、「ニュースフィード」を表示するUIがあります。
(ジャズの名曲 ウン・ポコ・ローコ とは無関係です)
関連会社のサイトから情報を取得して、ページに埋め込みます。このデータの取得は、バックエンド側で行います。

しかし、関連会社のURLは、たまに変わるんだよな〜
ここで、よく考えずに、「リクエストパラメータでURLを受け取れたら便利かな」って思って、次のような実装にしてみました。
Astro SSR による簡単なコードで、上の部分がサーバーで実行され、下のHTMLがクライアントにレンダリングされます。

このサイトは、リクエストパラメータ newsUrl で受け取ったURLにサーバーが fetch でアクセスして、情報を加工して、ブラウザに返しています。

http://example.com/news?newsUrl=http://other.example.com/news

やったーニュース機能が完成したぞ〜\(^o^)/

って、まてい!!

SSRFの影響

エンジニアの意図としては、 newsUrl パラメータには、関連会社のURLが入ってくる想定でした。
しかし、閲覧者は、この newsUrl パラメータを自由に書き換えられてしまいます。

もちろん、これは極端にわかりやすい例です。ブラウザのアドレスバーに現れなくても同じ。

次のような各種の情報漏洩・情報改ざんが考えられます。

  • 内部ネットワークから情報を取得できてしまう
    • http://192.168.1.* など内部ネットワークのアドレスを指定されると起こりうる
  • ファイルシステムにアクセスされてしまう
    • file:/// ではじまるURLを指定されるとファイルシステムにアクセスされてしまう
    • fetch では発生しないが、処理系によっては、起こりうる
  • クラウドサービス(AWSなど)のエンドポイントを叩かれてしまう
    • 今回の例では純粋なfetchだが、もしも認証付きのAPIクライアントだったら、深刻。
  • 情報改ざん
    • 今回の例では GETリクエストだが、もしもPOSTなど副作用があるリクエストだったら起こりうる

また、

  • 別のサービスへの攻撃の踏み台にされることもありうる
  • フィッシングなどに悪用される可能性(厳密にはSSRFから外れる)
    • 自分のドメインに、悪意があるコンテンツが表示されることになり、情報改ざんに近い被害

サーバーが置かれている状況や、実装の内容次第で、いろいろな被害が考えられそうです。

対策

SSRFの脅威にどのように向き合っていけば良いのか。

SSRFの背景

SSRFが発生しうる背景は、いくつもあると思います。

  • セキュリティ意識不足、情報不足
    • 10年前はそこまで情報が多くなかった
    • 技術不足:非エンジニアでもこのようなコードは書けてしまう
  • 役割分担
    • サーバーコード実装者が、インフラを知らない
    • インフラ設計者が、サーバーコードの実装を知らない
  • 意図しない流用
    • 例えば、本来は公開しない予定だったコードが時代の流れで公開されるとか
    • 前任者が書いたコードをよく見ずに改変・流用
  • ライブラリやサンプルコード由来のコード
    • 自分で書いたわけじゃないが、意図せず混入していた
    • ライブラリの中に危険なコードが入っていた
      • 例えば、WordPressとか、Next.jsのような、広くリクエストを処理するフレームワークに脆弱性が混入していることが考えられます
  • 過剰な汎用性
    • バックエンド開発者が過剰な汎用性を持たせてしまう
    • チーム構成による。コミュニケーション不全もあるか。
  • 不適切な権限
    • サーバーが過剰に権限を持っている
  • 薄いセキュリティ層
    • 裏側のシステムが境界防御でしか保護されていない
  • テスト不足・診断不足
    • エキスパートレビューや外部会社の診断で防げるかも
    • しかし予算が無い・・・
      などなど・・・

一般的な対策

コーディングするうえでの対策としては、入力と出力をしっかりガードすることです。

  • リクエスト検証をしっかり
    • ブラウザから受け取ったパラメータをそのまま使って後段サーバにリクエストしない
    • そもそも、本当にそこまで柔軟なパラメータが必要なのかよく考える
  • リクエストの宛先をさだめる
    • 後段サーバを可変にしないで、よく考える

また、サーバーコードの外側でも、色々と気をつけられることがあると思います。

  • フレームワークのアップデート
  • システム構成をむやみにさらさない
    • 例えば、イントラネットのネットワーク構成など
    • 裏側がどうなっているのかは(たとえアクセスできなくても)秘密にしておく
  • WAF
    • コード修正が難しい場合、WAFなどの追加レイヤーで対策も考える
  • セキュリティ診断を受ける

リスク管理の重要性

エンジニア個人がSSRFを起こさないように気をつけてコーディングやレビューすることはもちろん大事ですが、上に書いたような背景もあり、気づかないうちに成立していることもあるでしょう。
そこで、プロジェクト内でリスク評価をして、SSRFが発生しうるのか、発生したとして、どのようなインパクトがあるのか、検討していきましょう。
リスクとは、一般的に、 発生頻度 x 発生したときのインパクト で計ります。
SSRFだけに着目するのではなく、プロジェクト内で横断的にさまざまなリスクに目を向けて評価していくのが良いです。
また、一度だけでなく、継続的にリスクの再評価をしていければなお良いですね。

リスク度合いに見合った対策を慌てず実施してきましょう。

まとめ

いかがでしたか。
SSRFについての説明や、影響、対策についてざっと書きました。

興味を持っていただけたら、 OWASP Top 10 などでさらに詳しい情報を調べてみてください。

https://owasp.org/Top10/ja/A10_2021-Server-Side_Request_Forgery_(SSRF)/

chot Inc. tech blog

Discussion