レート制限のない事業は簡単に落ちる

レート制限のない事業は簡単に落ちる
レート制限のない事業が平穏だったのは防御が強いからではなく、誰も本気で攻めなかっただけです。買収で標的の魅力が上がった途端、同じコードのまま総当たり・スクレイピング・スパムで簡単に落ち、従量課金なら請求まで膨らむ。ログインやSMS送信、問い合わせの穴を、429ステータスや応答ヘッダ、コードとインフラの二層で見抜き、移管後も防御が生き残るかまで確かめる方法を整理します。

買収したサービスの請求書が、引き継いだ翌月にいきなり跳ね上がる。中身を見ると、売上は増えていないのに、SMS送信費とサーバーの実行時間だけが数倍になっている。あるいは、朝の障害通知で「ログインが異常に遅い」と気づき、アクセスログを開くと、同じ数十個のIPアドレスから、一秒間に何十回もログインが試されている。こうした場面を、私たちは事業の引き渡し後に何度も見てきました。

共通しているのは、いずれも「前のオーナーの手元では一度も起きなかった」ことです。売り手は嘘をついていません。数年間、本当に平穏に運用できていた。ところが買い手に渡った瞬間、同じコードのまま、同じインフラのまま、事業が簡単に落ちるようになる。その差を生んでいるのが、多くの事例記事も査定表も触れない「レート制限」──濫用(不正な使い方)を数えて止める仕組みの有無です。

「今まで問題なかった」は、誰も本気で殴っていなかっただけ

「今まで問題なかった」は、誰も本気で殴っていなかっただけ

レート制限がない事業がそれでも動いていたのは、防御が優れていたからではなく、誰も攻める理由がなかったからです。月商が小さく、名前も知られていない個人開発のサービスは、攻撃者にとって割に合わない標的でした。総当たりを仕掛けるコストより、そこから得られるものが小さい。だから放置され、結果として「問題が起きなかった」という運用実績だけが積み上がります。

ところが事業譲渡は、その静けさを壊す出来事です。買収は多くの場合どこかで話題になり、リニューアルの告知が出て、取り扱う金額の桁が変わります。標的としての魅力が上がった瞬間に、それまで一度も試されなかった穴が、初めて本気で殴られる。運用実績は「攻撃に耐えた実績」ではなく「攻撃されなかった記録」にすぎず、この二つを取り違えると、買収後に痛い目を見ます。

技術デューデリジェンス(買収前の技術的な精査、以下DD)で見るべきなのは、過去に障害が起きたかどうかではありません。「まだ起きていないだけの障害」がどれだけ仕込まれているか、です。レート制限の欠如は、その典型です。平穏な運用ログは、防御の証明には一切なりません。

レート制限とは「同じ相手を数えて止める」だけの仕組み

レート制限とは「同じ相手を数えて止める」だけの仕組み

レート制限は、難しい技術ではありません。「同じ相手(IPアドレスやアカウント、APIキー)から、一定時間に何回リクエストが来たかを数え、決めた上限を超えたら一定時間はねる」というだけの仕組みです。上限を超えたリクエストには、HTTPの「429 Too Many Requests」というステータスコードを返し、いつ再試行してよいかを示す「Retry-After」ヘッダを添えるのが定石です。

実装の置き場所はいくつかあります。アプリの手前に立つCloudflareのようなCDN/WAF(不正な通信を弾く防御層)でルールとして設定する方法、nginxの「limit_req」のようにWebサーバーの設定で絞る方法、アプリ側でexpress-rate-limitやdjango-ratelimitのようなミドルウェア(処理の途中に挟む部品)を通し、Redisにカウンタを持たせて制御する方法。どこか一箇所にでもあれば、素の状態よりはるかに落ちにくくなります。

これほど単純なのに抜け落ちるのは、レート制限が「動くために必要な機能」ではないからです。無くてもサービスは完璧に動作します。ユーザー登録もログインも決済も、テスト環境では何の問題も起きない。だから開発の初期に後回しにされ、そのまま忘れられる。売り手が誠実であっても、無いことに気づいていないケースが大半です。この「動くから気づかれない欠落」は、SaaS売却で値引きされる技術的負債の中でも、査定に最も響きにくく、しかし買収後に最も高くつく種類の負債です。

ログインフォームは総当たりとクレデンシャルスタッフィングの入り口

ログインフォームは総当たりとクレデンシャルスタッフィングの入り口

レート制限が無くて最初に狙われるのは、たいていログインフォームです。攻撃には二種類あります。一つは総当たり(ブルートフォース)で、一つのアカウントに対してパスワードを片端から試す方法。もう一つがクレデンシャルスタッフィングで、他社サービスから流出した「メールアドレスとパスワードの組」を大量に持ち込み、使い回している利用者を炙り出す方法です。後者は正しい組み合わせを試すため、一回あたりの成功率が高く、静かに成立します。

どちらも、レート制限とアカウントロック(一定回数失敗したら一時的に締める仕組み)が無ければ、秒間数十回のペースで延々と試行できます。DDでは、ログイン画面でわざと五回、十回と間違えてみて、六回目以降に挙動が変わるかを確かめるのが手っ取り早い。何回間違えても同じ速度で反応が返るなら、防御は無いと考えてよい。パスワードの正解・不正解でエラー文言が変わる(「そのメールは存在しません」と返してしまう)実装なら、有効なアカウントの一覧化まで許していることになります。

ログイン以外に、パスワード再発行フォームも同じ穴を抱えがちです。ここが無防備だと、攻撃者は再発行メールを他人のアドレス宛に大量に送りつけ、送信元の評価(メールの信頼度)を落とすことができます。認証まわりの綻びは連鎖するため、一箇所を見つけたら周辺の全フォームを疑うのが定石です。

従量課金と組むと、濫用は「攻撃」ではなく「請求」になる

従量課金と組むと、濫用は「攻撃」ではなく「請求」になる

レート制限の欠如が最も残酷な形で表れるのが、従量課金(使った分だけ払う課金)と組み合わさったときです。サービスを落とすまでもなく、攻撃者はただリクエストを送り続けるだけで、買い手の財布から直接お金を抜いていきます。代表例がSMS認証です。電話番号を入力するとSMSが飛ぶフォームに制限が無いと、攻撃者は高額課金の国番号を大量に投入し、通信費を釣り上げる。これはSMSポンピング(またはトールフラウド)と呼ばれ、一晩で数十万円が消えることもあります。

サーバーレスや従量課金のインフラでは、この構造がさらに広がります。リクエスト一回ごとに関数の実行時間、データベースの読み取り、外部への転送量(egress)が積み上がる設計だと、濫用がそのまま請求額に翻訳される。重い検索エンドポイントや画像生成のようにリクエスト単価が高い機能を、無制限に外へ晒しているサービスは特に危うい。ここは外部サービスへの依存構造とも直結するため、Webサービス売却で効く第三者API依存と併せて、一回のリクエストがいくらのコストを発生させるかを、必ずお金の単位で棚卸ししてください。

買い手がここで確認すべきは、過去の請求書の推移だけではありません。「もし悪意ある相手が一日中このエンドポイントを叩いたら、上限はいくらか」という最悪値です。上限が設計されていない従量課金は、実質的に上限のない負債を引き受けることと同じです。決済フォームであれば、盗んだカード番号の有効性を試す「カード試行(カーディング)」の温床にもなり、決済代行の手数料と不正利用の両方で損失が出ます。

問い合わせ・登録・通知 ── 送信系エンドポイントは静かに汚染される

問い合わせ・登録・通知 ── 送信系エンドポイントは静かに汚染される

攻撃はサービスを落とすためだけに行われるわけではありません。むしろ多いのは、事業の信用をじわじわ削るタイプの濫用です。問い合わせフォームにレート制限もCAPTCHA(人間かどうかを確かめる仕組み。TurnstileやreCAPTCHAが代表)も無ければ、ボットが一日に何千件ものスパムを投げ込み、運営者は本物の問い合わせを埋もれさせ、対応工数を奪われます。

ユーザー登録フォームが無防備なら、捨てアドレスによる大量の偽アカウントが生成されます。この偽アカウントは、統計値を汚し(アクティブユーザー数が水増しされる)、投稿型のサービスならスパム投稿の発射台になり、確認メールの送信費まで発生させます。買収時に見せられた登録者数の何割が実在するのか、という疑問がここで生じます。数字の裏付けは、レート制限の有無とセットで確認しないと意味を持ちません。

メールやSMSを送る全てのフォーム──登録確認、パスワード再発行、通知、招待──は、送信元の評価を人質に取られる場所です。ここが濫用されると、送信ドメインがスパム判定を受け、正規のメールまで届かなくなる。復旧には時間がかかり、その間の機会損失は査定額に一切載っていません。送信系のエンドポイントは、DDのチェックリストで独立した一項目を立てる価値があります。

防御層があるかは、ヘッダとステータスコードで数分で分かる

防御層があるかは、ヘッダとステータスコードで数分で分かる

レート制限の有無は、コードを読む前に、外から数分で当たりをつけられます。まず対象のエンドポイントに、短時間に連続してリクエストを送ってみる。健全な防御があれば、どこかで「429 Too Many Requests」が返り、「Retry-After」や「X-RateLimit-Remaining」といったヘッダで残り回数や待ち時間が示されます。何百回叩いても200が返り続けるなら、その経路に制限は無いと判断できます。

応答ヘッダも手がかりの宝庫です。「Server」や「cf-ray」といったヘッダから、Cloudflareのような防御層が手前に立っているかが分かります。逆に、オリジンのサーバーが生のIPで直接見えていて、CDNを介していない構成なら、そもそもエッジ(利用者に近い縁の部分)で濫用を止める層が無いということです。ログインやパスワード再発行のフォームで、失敗を重ねたときにCAPTCHAが差し込まれるか、ロックがかかるかも、ブラウザ操作だけで確かめられます。

ただし、外から「叩いてみる」検証は、対象事業の許可なく本番環境に対して行えば、それ自体が攻撃と区別がつきません。DDの一環として行うなら、売り手の同意を得た上で、検証環境や合意した時間帯に限って実施するのが筋です。そして、攻撃を受けたときにそれを事後に追える状態かどうか──アクセスログや監査ログが残っているか──も同時に確認してください。防御が無いことより、監査ログがない事業は自分を守れない状態のほうが、買収後の対処を難しくします。

コードとインフラのどちらに防御があるかを切り分ける

コードとインフラのどちらに防御があるかを切り分ける

外形の検証で「制限があるらしい」と分かっても、それがどこに置かれているかを突き止めないと、移管後に消える危険があります。防御がCloudflareのダッシュボード上のルールとして存在する場合、そのアカウントの持ち主が売り手のままだと、事業を引き渡してもルールごと引き継げないことがあります。逆に、アプリのコードにミドルウェアとして組み込まれていれば、コードと一緒に移りますが、カウンタを保持するRedisの接続情報が引き継ぎ漏れになれば、やはり機能を止めてしまいます。

コードを見せてもらえるなら、レート制限やスロットリング(流量の絞り込み)に関わるライブラリ(express-rate-limit、rack-attack、django-ratelimit等)が依存関係に入っているか、ミドルウェアとして実際に有効化されているかを確認します。ライブラリが入っていても、設定ファイルで無効化されていたり、特定のルートにしか適用されていなかったりする例は珍しくありません。こうした「入れたが効いていない」痕跡は、コードの他の部分の作り込みを推し量る兆候でもあり、サイト買収前に見るべきコードの兆候として拾っておく価値があります。

望ましいのは、エッジ(CDN/WAF)とアプリの二層で防御が効いている構成です。片方が抜けても、もう片方が最後の砦になる。単層しか無い、あるいは「あるにはあるが片方の移管が危うい」事業は、引き渡し時に防御がゼロになる瞬間が生まれ得ます。DDでは、有無だけでなく「移管後もその防御が生き残るか」まで見届けてください。

効くのは「殴られてから」ではなく「殴られる前」の設計

効くのは「殴られてから」ではなく「殴られる前」の設計

レート制限をめぐるDDの結論は単純です。防御は、攻撃が来てから慌てて足すものではなく、来る前に在るべきものだということ。買収の告知で標的としての魅力が上がるより前に、防御層が在るかを確かめ、無ければ引き渡しの条件として整備を織り込む。これは値引き交渉の材料であると同時に、買った初月に事業を落とさないための保険です。

もう一つ、防御そのものと同じくらい重要なのが、濫用が始まったときに誰が最初に気づくかです。異常なリクエストの急増を検知するアラートが、旧オーナーのメールアドレスや、引き継がれないチャットに飛ぶ設計のままだと、買い手は攻撃を受けている事実すら知らないまま請求書で気づくことになります。ここは障害の第一報が買い手に届かない構造と完全に地続きで、防御層とアラートの宛先は、移管作業の中で必ずセットで付け替えるべき項目です。

レート制限の有無は、稼働中のサービスを外から触っただけでは全体像が掴みきれず、コードとインフラの両面を突き合わせて初めて確定します。買収を検討している事業の防御層に穴がないか、どこが最初に落ちるかを専門家の視点で洗い出したいときは、AI技術デューデリジェンスで、公開エンドポイントの濫用耐性を含めた技術リスクの棚卸しができます(登録不要)。

この記事の著者

黒沢 大輔

株式会社studio C 代表取締役

これまで4回の事業譲渡を実現。上場企業にてエンジニア、制作ディレクション、SEO事業立ち上げを歴任。副業で始めた複数の掲示板サイトを国内最大規模まで成長させて事業譲渡。日本のM&Aに透明性と精度をもたらすべく、デジタル事業のM&Aプラットフォーム『RIKKA M&A』を立ち上げ。