ECサイトでは、残高やポイントが足りなければ商品を購入することはできません。
カートの合計金額が支払い可能な金額を超えていれば、決済は拒否されるのが普通です。
しかし、もしカートの計算ロジックに設計ミスがあった場合、本来は購入できないはずの商品を買えてしまうことがあります。
今回はラボ「Lab: High-level logic vulnerability」を題材に、なぜこの攻撃が成立するのかを整理し、WordPress環境に置き換えて考察してみます。
WSAラボ「High-level logic vulnerability」の概要
このラボの目的は、ジャケットを購入することです。
しかし問題があります。
プレイヤーが持っている Store credit(ストア残高)では、本来ジャケットを買うことができません。
普通なら、残高が足りなければ購入できないはずです。
しかし、このサイトにはある設計ミスがあります。
それは、カートの数量にマイナス値が使えることです。
攻撃者はBurp Suiteを使って、カート更新リクエストの quantity(数量)を改ざんします。
例えば次のようにします。
- ジャケット:1
- 別の商品:-10
すると、カートの合計金額が不自然に下がります。
その結果、本来は残高不足で買えないはずのジャケットが、ストア残高内に収まったように見えてしまいます。
つまり、マイナス数量を利用して合計金額を操作できるという状態になっているのです。
マイナス数量で価格を操作する攻撃の流れ
実際の攻撃の流れを整理すると次のようになります。
商品をカートに追加
↓
quantity を -10 に改ざん
↓
カート合計が減少
↓
ストア残高内に収まる
↓
高額商品が購入できる
ブラウザ画面ではマイナス値は入力できませんが、Burp Suite で HTTP リクエストを書き換えると送信できます。
例えば、 POST /cart の quantity を -10 のように変更すると、サーバーはその値をそのまま受け入れてしまいます。
その結果、カートの計算がおかしくなり、合計金額が意図しない形で減ってしまいます。
なぜマイナス数量の攻撃が成立するのかーー設計ミスのポイント
この攻撃が成立する理由は、いくつかの設計ミスが組み合わさっているためです。
主な問題は次の4つです。
- マイナス数量が拒否されない
- 合計金額のチェックが遅い
- 不正状態でも処理が続く
- 商品単体価格しか見ていない
特に重要なのはこの部分です。
サイトの設計では、おそらく次のような前提があります。
- 数量は正の数
- カート合計は自然な金額になる
- 異常な状態は発生しない
しかし実際にはその前提を検証していないのです。
つまり、「数量は正の整数のはず」という思い込みでシステムが作られています。
この前提が崩れると、カート計算全体が壊れてしまいます。
ラボ名の意味
このラボ名は「High-level logic vulnerability」です。
直訳すると「高レベルのロジック脆弱性」という意味になります。
ここでいう High-level は「重大」という意味ではありません。
そうではなく、設計レベルの問題を指しています。
セキュリティでは次のように区別されることがあります。
Low-level
コードのミス
例
- バッファオーバーフロー
- 型ミス
- 数値エラー
High-level
設計や仕様の問題
例
- 認証フローの欠陥
- ビジネスルールの破綻
- 処理順序のミス
今回のラボはカートの設計そのものが破綻しているという問題です。
だから High-level logic vulnerability と呼ばれています。
なぜこれはビジネスロジック脆弱性なのか
この問題は、よくある「入力チェックミス」とは少し違います。
例えば
- SQLインジェクション
- XSS
のような脆弱性は、入力データの処理ミスです。
しかし今回の問題はそうではありません。
コード自体は普通に動いています。
エラーも出ません。
問題はシステムの前提が間違っていることです。
例えばこのサイトは次のように考えています。
- 数量はマイナスにならない
- カートの合計は自然な値になる
- 異常状態は起きない
しかし攻撃者は、その前提を壊します。
すると、ビジネス処理そのものが破綻するのです。
こうした問題をまとめてビジネスロジック脆弱性と呼びます。
診断で確認すべきポイント
実際の診断では、次の点を確認します。
1 数量のサーバー側検証
フロント側のJavaScriptではなく、「サーバー側で検証しているか」を確認します。
例えば
- 負数を拒否しているか
- 0の扱いが決まっているか
などです。
2 カート合計の再計算
カート更新のたびに、すべての商品を再計算しているかを確認します。
部分更新だけだと、整合性が崩れることがあります。
3 不正状態のロールバック
もし不正な状態になった場合、処理を巻き戻す仕組みがあるかを確認します。
例えば
- 合計超過なら注文キャンセル
- カート状態を元に戻す
などです。
4 商品単体の判定になっていないか
商品ごとにしかチェックしていない場合、カート全体の整合性が崩れることがあります。
そのため、カート全体の計算が重要になります。
まとめ
このラボは、派手な攻撃ではありません。
しかし、設計の甘さがそのまま脆弱性になる典型例です。
今回の問題は、次の設計ミスが重なった結果です。
- マイナス数量が通る
- 合計チェックが遅い
- 状態ロールバックがない
- 商品単体の判定しかしていない
どれか一つだけなら問題にならないかもしれません。
しかし複数のミスが組み合わさると、システム全体が破綻します。
これがビジネスロジック脆弱性の怖いところです。
重要なのは「仕様の前提を疑うこと」です。
入力値は信頼せず、必ずサーバー側で整合性を確認する。
それが最も基本的で重要な防御になります。
よくある疑問
Q. JavaScriptで数量制限していれば安全ですか?
安全ではありません。
JavaScriptはブラウザ側の処理なので、リクエスト改ざんで簡単に回避できます。
必ずサーバー側で検証する必要があります。
Q. WAFで防げますか?
基本的には防げません。
この問題は攻撃文字列ではなく、ビジネス処理の設計ミスだからです。
Q. WordPressでも起きますか?
起きる可能性はあります。
特にWooCommerceでは、AJAXカート更新、クーポン処理、在庫処理などが複雑に組み合わさるため、設計ミスがあると同様の問題が起きる可能性があります。
