外部決済サービスを利用する上での脆弱ポイントと対策 #devio2022

DevelopersIO 2022 で「外部決済サービスを利用する上での脆弱ポイントと対策」というテーマでビデオセッションを公開しました。特に外部サービスから結果を受け取る場合にセキュリティ上考慮が必要なことについてお話しました。
2022.07.28

概要

prismatix 事業部の野村です。

クラスメソッドのオンライン型イベント DevelopersIO 2022 技術セッションとして、「外部決済サービスを利用する上での脆弱ポイントと対策」というテーマで動画を公開しました。

ECサイトなどで決済機能を作る場合は外部の決済サービスを扱うことがほとんどだと思います。特に外部サービスから結果を受け取る場合にセキュリティ上考慮が必要なことについて話しました。

動画

スライド

話したこと

アジェンダ

  • 外部の決済サービスを利用した、よくある遷移についてまず紹介
    • その中で脆弱となり得るポイントも合わせて説明
  • 脆弱ポイントへの対策を紹介

想定する視聴者

  • ECサイトなどの決済機能を開発する方
  • 外部の決済サービス ( Stripe, Amazon Pay など) を利用

決済でよくある遷移

以下は、3Dセキュア決済と Amazon Pay 決済などに共通する画面遷移

  • 支払い方法を選択、注文を受付
  • 注文完了
    • ECサイトなど、「決済サービスを利用するシステム」側で用意する機能
  • 本人認証や利用するカード情報など入力
    • 外部決済サービスが提供する機能

気をつけるべきポイント

外部サービスから注文完了に遷移する箇所に注目します。

注文完了機能に遷移できるのははたして外部サービスからだけでしょうか?

そうとは限らないのが気をつけるべきポイントです。

悪意あるユーザー操作の例

この悪意あるユーザーは、注文受付まで進んだ後に本人認証など操作は行いません。 注文完了の機能にリクエストを偽装してアクセスします。

本人認証やカード情報選択など外部サービス側の機能を通していないにもかかわらず、 リクエスト内容が問題なかった場合、そのまま注文が成立してしまいます。

外部サービスから結果を受け取る機能の例

  • 外部サービスからのコールバック(リダイレクト)先となる画面
    • 先に例示した「注文完了画面」など
  • 外部サービスが発行したイベントを受け取るエンドポイント(Webhookなど)
    • 外部サービスからアクセス可能とするため公開していることが前提。公開エンドポイントに無策でいると、誰でもアクセス可能な状態に

脆弱ポイントへの対策

想定する送信元であることを検証する

注文完了機能へのアクセスがあった際に、その送信元をチェックします。 送信元が想定通りであることを確認してから、注文完了の処理を続行します。

IPアドレスやリファラなど、外部サービスを特定できる情報から検証しましょう。

あるいは、外部サービスが提供する検証方法の利用も推奨します。 例えば、 Stripe で与信完了などの情報を通知する Webhook の機能には、署名確認 を行うことを推奨しています。

Stripe 以外のほとんどの外部サービスも、このような検証方法を提供しています。お使いのサービスのドキュメントを確認の上、対策をしておきましょう。

任意のパラメータを使って検証する

  • 注文受付→外部サービスへの遷移する前に、任意でパラメータを生成し、お客様には見えない形で保持
    • 値は特定困難な形でランダムに生成する
  • 注文完了コールバック先を指定する際に、クエリパラメータなどで生成した値を含めるよう設定
  • 注文完了へのコールバック受信をした後、最初に保持したパラメータと外部サービスからのコールバック時に渡されたパラメータを照合
    • この値が一致していればリクエストOKとみなし、注文完了処理を続行

悪意あるユーザーはランダムなパラメータ値の特定まではできない想定です。

まとめ

外部の決済サービスを間に挟む遷移がある場合、その決済結果の受け取りを伴う機能は誰でも実行できる可能性が高いです。 今回の動画および記事で紹介した方法を参考に、誰でも実行できないように対策しましょう。

prismatix について補足

prismatix 決済サービスの開発で得た知見をもとに今回お話させていただきました。prismatix や決済サービスについては以下のブログに詳しく記載していますので合わせてご参照ください。

一緒に開発してくれる仲間も引き続き募集中です。