PR 本記事には広告(Amazonアソシエイト・もしもアフィリエイト・A8.net等)が含まれます。掲載情報の正確性には努めていますが、商品の詳細は必ずリンク先で最新情報をご確認ください。
CTF・セキュリティ学習

【ビジネスロジック編】仕様の隙間を突く攻撃と守り方|CTF思考フレームワーク #13

かも次郎とアンペンが「ビジネスロジック」を解説するマスコットイラスト
安全に生きたい編集部

こんにちは、アンペンです!

前回は、タイミングの隙間を突くレースコンディションを扱いました。

今回は、コードや通信の異常がないのに「業務として不正な結果」が成立してしまうビジネスロジックの脆弱性を見ていきます。仕様の前提が崩れる瞬間を、攻撃者の目で追ってみましょう。

仕様通りに動いてるのに、なんで攻撃になるの?

仕様の中に『これは普通やらないよね』っていう暗黙の前提が混ざっていて、そこを意図的に外されると、コードはそのまま動いてしまうんだ。

これまで扱ってきた攻撃の多くは、『コードのどこかにミスがある』タイプでした。でも今回はちょっと毛色が違います。コードは完璧、通信もエラーなし、ログにも異常なし——なのに“業務としてはアウト”な結果が起きてしまう。それがビジネスロジックの脆弱性です。自動スキャナーにも引っかからず、人の目でしか見つけにくい。だからこそ、攻撃者の「そこ、疑っていいんだ?」という視点を知っておくことが、いちばんの近道になります。

まず結論

ビジネスロジック脆弱性は、コードのバグではなく「想定していない使われ方を仕様が許してしまう」問題です。手順スキップ・マイナス値・限度超過のような行為を、サーバ側で必ず再検証する設計が必要になります。

この記事で分かること

  • ビジネスロジック脆弱性が「コードのバグ」と違う理由
  • 手順スキップ・マイナス値・限度超過の典型3パターン
  • 守り側として「サーバで再検証する」設計の考え方
難易度:すこし慣れてから 所要時間:10分 体験:仕様の前提を疑う おすすめ:#12の後

📖 はじめてのWebセキュリティ #13|ビジネスロジック編
『仕様通りに動くのに、業務的にはアウト』な脆弱性を、攻撃者の見方で読み解きます。 シリーズ一覧を見る →

⚠️ 大事なお約束
この記事の確認は、CTF・公式ラボ・自分で作った検証環境だけで行ってください。実在するサービスで手順スキップやマイナス値の挙動を試す行為は、不正アクセスや業務妨害に該当する可能性があります。

「コードは正しい、でも業務として不正」

普通のセキュリティ脆弱性は、入力検証ミスやエスケープ忘れなど「コードのバグ」が原因です。一方ビジネスロジック脆弱性は、コード自体は仕様通りに動いています。問題は仕様が想定していない使われ方を許してしまっていることです。

たとえば「マイナスの金額を入力されることはない」「画面の順番通りに進むはず」といった暗黙の前提が、攻撃者には真っ先に疑うポイントになります。

ここで攻撃者の思考をのぞいてみましょう。彼らはマニュアル通りに使う気がありません。「この数量欄、マイナスを入れたら?」「“次へ”ボタンを押さずに、いきなり完了APIを叩いたら?」「無料体験を、別のメールで何回も申し込んだら?」。ふつうの人なら“やらない”ことを、わざとやる。その一つひとつが、仕様の前提を揺さぶるテストになっているんです。

鍵になるのは『暗黙の前提』という言葉です。私たちは仕様を作るとき、無意識にたくさんの“当たり前”を前提にしています。「金額にマイナスは入れないよね」「画面は上から順に進むよね」「1人1回までだよね」——どれも“言われてみればそうだけど、明文化していない”ルールです。攻撃者は、まさにこの“書かれていない当たり前”を、片っ端から疑ってかかります。

図解:想定フローと攻撃者フロー

想定どおりA→B→C→Dと進むフローと、攻撃者がB・Cを飛ばしてA→Dへ直接進むフローを比較した図
サーバ側で『前のステップが終わっているか』を確認していないと、飛ばされて成立してしまう。

想定どおりに画面を進む正規利用者と、途中をスキップして直接APIを叩く攻撃者では、サーバが受け取る状態が異なります。

つまりサーバから見ると、『律儀に全ステップを踏んだ人』も『最後だけ叩いてきた人』も、最終リクエストだけを見れば見分けがつかないことがあります。だからこそ、サーバ自身が“ここに来るには前のステップが終わっているはず”という事実を、自分で覚えておく必要があるんです。

市役所の受付で申込書の2ページ目が抜けたまま受理されてしまう様子のたとえ図
途中のページが抜けていても受け付けられてしまう。Webでもステップを飛ばした直接リクエストが通る。
📝 たとえるなら、申込書のページを飛ばす

役所の手続きで、A→B→Cの順に申込書を書くルールだとします。本来Bには「身分証コピーの提出」があるとしましょう。Aを書いた後にBを飛ばしてCを出すと、受付がそのまま処理してしまえば、身分証なしで申込が通ってしまいます。Webでも、画面のステップ番号を入力に含めて送るだけで、サーバ側が信用してしまえば同じことが起きます。

ここで覚える用語:ビジネスロジック脆弱性
機能としては仕様通りに動いているのに、業務目線では本来許してはいけない結果になる問題です。OWASP では Business Logic Vulnerabilities として整理されており、設計レビューで発見することが多いタイプです。

だからこの脆弱性は、自動の脆弱性スキャナーがいちばん苦手とする相手です。スキャナーは「おかしな入力(記号や攻撃文字列)」には反応できても、「ふつうに見える、でも業務的におかしい使い方」までは判断できません。マイナスの金額も、コンピュータにとっては“ただの数字”ですからね。結局これを見つけられるのは、「この機能、業務的に変な使い方ができないか?」と考えられる人間の頭だけ。そこが、この分野の面白さでもあります。

代表的な3つのパターン

ビジネスロジックの“想定外”は、大きく3つの形で現れます。『ありえない値を入れる(マイナス値)』『順番を飛ばす(ステップスキップ)』『上限を超える(限度突破)』。どれも特別な技術はいりません。必要なのは“ふつうはやらないことを、あえてやってみる”発想だけです。

よくある「想定外」の使われ方

マイナス値・ステップスキップ・限度突破の3つのビジネスロジック脆弱性パターンを示したカード型インフォグラフィック
①マイナス値 ②ステップスキップ ③限度突破。守りはサーバ側での前提再検証とステートマシン管理。
  • マイナス値の入力:送金額・購入数量・割引率などに負の値を入れて、逆向きの効果を狙う
  • ステップスキップ:本人確認・利用同意・支払い確認などを飛ばして最終ステップだけ実行する
  • 限度・上限の突破:1人1個までの商品を別の経路から複数注文する、無料枠を超えて利用する

これらはすべて、画面操作を経由しない直接リクエストで成立しがちです。つまり攻撃者目線では「画面はそもそも飾り」と捉えるのが基本姿勢です。

ここでも、シリーズを通して何度も出てきた合言葉が効いてきます。『画面はそもそも飾り』。私たちは画面のボタンや順番を“ルール”だと感じますが、攻撃者にとってそれは、ただの見た目にすぎません。裏でサーバに届くリクエストは、画面を無視して自由に組み立てられます。だから「画面でそうなっているから大丈夫」は、ビジネスロジックの世界でもまったく通用しないんです。

自分のラボで試すときのコツは、“意地悪な利用者”になりきることです。といっても本物のサービスは厳禁。自分の演習環境で、「マイナスを入れたら?」「途中を飛ばしたら?」と、ふだんやらない操作をわざと試してみる。コードが素直に受け入れてしまったら、それがビジネスロジック脆弱性のサインです。

CTFでやってみよう:仕様の暗黙の前提を洗い出す

やってみよう / 演習環境限定

自分のラボで、手順スキップやマイナス値のリクエストを試そう

目的は本物のサービスを攻撃することではなく、「自分の演習環境がどんな前提に依存しているか」を見抜くことです。

  1. CTFや自分の検証環境のフォームで、画面のステップを洗い出す(A→B→Cなど)
  2. 直接最後のステップだけにリクエストを送り、サーバ側でブロックされるか確認する
  3. 金額・数量・割引率などの入力欄に、負の値や上限を超える値を入れて挙動を見る
  4. レスポンスとデータベースの状態を比較し、サーバ側で再検証されているかを確認する
  5. 「コードは動いているが、業務として困る結果」が出たら、それがビジネスロジック脆弱性
他人のアカウント・本物のサービスでの試行は絶対にやめてください。確認は自分のラボ・自分のテストアカウントの範囲だけです。

マイナス値の話は、具体例を聞くと一気にピンと来ます。

金額にマイナスを入れるって、何がそんなにマズいの?

たとえば送金機能で『-1000円を送る』と指定できてしまったら?プログラムが素直に計算すると、“相手から自分へ1000円送る”、つまり逆向きの送金になりかねない。返品処理で個数にマイナスを入れたら、返すどころか在庫やポイントが増えることも。コンピュータはマイナスを“悪意”だとは思わず、ただ律儀に計算するだけ。だからサーバ側で「0以上か」を必ず確かめる必要があるんだ。

守る側なら、「サーバで前提を再確認」が基本

ビジネスロジック脆弱性を防ぐ核は、「画面・クライアントを信用せず、サーバ側で業務上の前提を必ず再検証する」ことです。仕様レビューと設計テストが、コードレビューと同じくらい重要になります。

守るための基本チェック
  • 金額・数量などの数値項目には、サーバ側で最小値・最大値・符号を必ず検証する
  • 手順の進行はサーバ側のステートマシンで管理し、画面側の番号を信用しない
  • 1ユーザ・1端末・1期間あたりの利用上限は、サーバ側でカウントして強制する
  • 外部から来た「重要な前提」(価格、割引率、ポイント)はサーバ側のマスタを再参照する
  • 不審な操作パターンは監査ログに記録し、後から異常検知できるようにする
  • QA・セキュリティテストに「異常系の業務シナリオ」を必ず含める

『画面のチェック』を当てにしないって、ここでも共通の考え方だね。

そう。サーバが『業務として正しいか』を最後の砦として判断する、というのが共通の防御姿勢だよ。

ここまでをひと言で言うと、ビジネスロジックの守りは『当たり前を、もう一度サーバで確かめる』ことです。人間が“常識”で省略してしまう前提を、コードはくみ取ってくれません。だから「マイナスはダメ」「順番は守る」「上限は超えない」を、暗黙にせず、サーバ側ではっきりルールとして書く。これが唯一の確実な守りになります。

まとめ:「想定外を許さない」設計が肝

今回のポイント
  • ビジネスロジック脆弱性はコードのバグではなく仕様の前提が問題
  • マイナス値・ステップスキップ・限度超過が代表3パターン
  • 画面側のチェックは信用せず、サーバ側で再検証する
  • QAやテストに異常系の業務シナリオを組み込む

今日の持ち帰りは『“まさかそんな使い方はしないよね”が、いちばん危ない』です。その“まさか”をやってみるのが攻撃者。だから設計や仕様レビューのときは、ぜひ一度“意地悪な利用者”になって、自分の機能をいじめてみてください。そこで見つかった違和感こそ、本番で塞いでおくべき穴なんです。

次回は、テンプレートに値を埋め込む処理が攻撃に使われるSSTI(サーバサイドテンプレートインジェクション)を扱います。テンプレートに混ざる悪意とRCEへの道を、優しく見ていきましょう。

次に読みたい記事

参考資料

記事URLをコピーしました