【発表日付】 2023年2月22日
【イベント】 Security.Tokyo
【発表概要】 Stripe APIの直接呼出しにより、競売で売られている商品を、最初入札額及び競売終了前に購入できた脆弱性を解説
決済代行サービスの実装における検証不備を悪用Andrew Croft (bubby963)
View Slide
1. 対象アプリ上の競売商品の購入の流れ対象アプリ上で競売対象商品を購入する際の処理の流れは以下になります1. 登録済み決済手段を持つユーザが競売ルームに参加2. 競売実施期間中にその時点の入札価格より高い限り、任意の金額で入札できる3. 競売終了時に落札者の登録済み決済手段を使用してStripe API経由で決済を実行Stripe API呼び出しを含む決済関連処理のほとんどはバックエンドで実行
2. マーケットプレース商品の購入の流れ• 競売とは別に、商品が一定価格で販売される「マーケットプレース」という機能もあります。• マーケットプレースから商品を購入する際は、以下の流れで処理されます。1. 買いたい商品の購入手続きを開始するリクエストを送信2. Stripeによる、「Payment Intent」というオブジェクトが生成され、それを一意に識別する「Payment IntentClient Secret」が返されます3. ユーザのブラウザから、保存された決済手段の識別子及びpayment intent client secretを渡してStripeAPIを直接呼び出すことにより、決済が実行競売商品購入時との一番大きな違いは、Stripe APIを呼び出して決済を実行する処理は、バックエンドではなく、クライアント側で行われる点になります。1. 購入手続き開始用リクエスト2. Payment intent secretの取得3. Stripe API直接呼出しによる決済実行
3. StripeのPayment IntentとはStripeの公式仕様書では以下のように定義されていますPaymentIntent (支払いインテント) API を使用して、複雑な決済フローを処理できる組み込みを構築します。この APIは、支払いの作成から決済までを追跡し、必要に応じて追加の認証ステップをトリガーします。簡潔にいうと• 支払いの開始から完了までの決済過程全般を、ユーザ及び支払いセッションごとに管理するための仕組み• 決済手段を登録できる「Payment Method API」と組み合わせて使用するのが基本• 各Payment Intentオブジェクトに、それを一意に識別するPayment Intent Client Secret、及び購入価格や通貨といった支払い詳細が格納されます
4. 競売商品のPayment Intentの取得対象アプリでは、マーケットプレースと同様、競売商品に対するPayment Intent Client Secretが発行できるgraphQLのクエリーが存在しました。発行されるこのインテントの内容は、購入価格が発行時点の最高入札額となっていました。そのため、これから説明する通り、最初入札額で競売商品を購入できる攻撃が成立。この攻撃の特徴としては• 発行時点の最高入札額で購入可能• 別ユーザが最高入札者の場合でも発行可能• 発行後に最高入札額が上がった場合でも、発行時点の最高入札額で購入可能なまま• 競売終了前に購入可能
5. 攻撃の流れ (1/3)1. 競売対象商品に対し、$1等低価格の入札を入れます。2. リクエストが正常に受け付けられたことを確認します。
5. 攻撃の流れ (2/3)3. 「auctionId」を渡して、当該競売に対しその時点の最高入札額に紐づいたPayment Intent ClientSecretを発行するリクエストを送信。4. 応答内容からPayment Intent Client Secretの値を取得。
5. 攻撃の流れ (3/3)5. Payment Intent Client Secret、使用するユーザの登録済み決済方法を識別する「PaymentMethod ID」、及び対象アプリの「Stripe Public Key」を渡して、Stripe APIに対し決済を実行するリクエストを直接送信します。6. 発行時の最高入札額で購入できたことを確認します
6. その他応用できる場面の考察基本的には、Payment Intent Client Secretがユーザに渡される仕様となっているサイトであればこういった脆弱性が潜在している可能性あり。実際には、下図の通り、公式手順書に従って導入した場合はこの仕様になるので、標的となり得るサイトが多い。この動きを悪用した他の脆弱性候補として、以下を考察しました。• クレジット制度のあるサイト上で、クレジット残高を差し引いた金額を持つPayment Intent Client Secretを多数作成しておき、順番に決済を実行していく• ユーザが商品を販売できるサイト上で、低価格で売っている商品に対しPayment Intent Client Secretを生成後、当該商品の価格を大きく上げる。