HOME > Scutumを支える技術 > Scutum技術ブログ

技術者ブログ

クラウド型WAF「Scutum(スキュータム)」の開発者/エンジニアによるブログです。
金床“Kanatoko”をはじめとする株式会社ビットフォレストの技術チームが、“WAFを支える技術”をテーマに幅広く、不定期に更新中!

Scutum開発者/エンジニアによる技術ブログ WAF Tech Blog

React2Shell攻撃で顕在化した、リクエストボディの先頭しか検査しないWAFを回避する攻撃

はじめに

現在多くのWAFサービスが存在しますが、そのうちのいくつかでは、HTTPリクエストのボディ部について、「先頭○KBしか検査しない(○の部分は、例えば8や16,64,128など)」というかなり注意が必要な仕様で提供されています。今回はこの点について掘り下げていきます。

リクエストボディとパラメータの基本

「ボディ部の先頭」とは具体的にはどのようなことでしょうか。HTTPリクエストのボディ部は、例えば次のようになっています。

param1=AAAAAAAAA&param2=BBBBBBBB

この例ではボディ部に2つのパラメータが含まれています。1つめのパラメータは名前が「param1」で値が「AAAAAAAAA」です。2つめのパラメータは名前が「param2」で値は「BBBBBBBB」です。

ほぼ全てのウェブアプリケーション環境において、このような場合にparam1とparam2の順番は順不同であり、リクエストを送信する側が自由に並び替えることができます。つまり上の例と次の例は同じ意味になります。

param2=BBBBBBBB&param1=AAAAAAAAA

また、基本的にウェブアプリケーションは「必要なパラメータを探して取得する」ように作られており、「本来そこにいることが期待されていないパラメータ」が存在していてもエラーになりません。例えば次の例ではghost_paramという、本来存在しないはずのパラメータを先頭に配置しています。

ghost_param=DUMMY&param1=AAAAAAAAA&param2=BBBBBBBB

本来param1とparam2のみを利用するアプリケーションにこのようなリクエストを送信しても、ほぼ全ての環境でエラーになりません。本来はghost_paramなどというパラメータが送信されるはずがない場面でも、データ送信側(クライアント)はこのように自由にパラメータを置くことができます。もちろんghost_paramは使われないので、このような行為にはウェブアプリケーションの動作上は意味がなさそうに見えます。

ボディの先頭だけを検査する仕様は容易に回避される

「ボディの先頭の○バイトだけ検査する」という仕様のWAFはこのようなリクエストボディに対し、最初のパラメータであるghost_param=DUMMY...から数えはじめ、特定のサイズまでのデータを検査対象とします。

攻撃者はこのghost_param=DUMMYをghost_param=DUUUUUUUUMMMMMMMMMMYYYYYYYYY...のように長くして、WAFが検査対象にするサイズと同じ長さにします。するとWAFはその先に置かれているparam1とparam2を検査しないため、攻撃者はparam1やparam2の内容について、WAFを完全に回避して自由に攻撃することが可能になってしまいます。つまり、まるっきりWAFがいないのと同じ状況となってしまいます。むしろ「WAFを入れているからある程度守ってくれてるはず」という勘違いをしてしまうかもしれないという点で、WAFが入っていないよりもマズい状況かもしれません。

この「ボディ先頭にゴミデータを置く」のはWAFに対する高度な攻撃あるいは回避技術というより、とてもシンプルな、ウェブアプリケーションの基礎知識があれば誰でも思いつく方法です。ましてやWAFサービスの提供を行っているようなセキュリティの専門家であれば、これに気づかないわけがありません。

ベンダーの説明

この非常に簡単に回避できてしまう仕様のWAFを提供しているベンダーは、おそらく「リクエストボディが特定のサイズより大きい通信は許可しないように設定してください」というスタンスを取っていると思います。例えばボディの先頭8KBしかWAFが検査しないのであれば、8KBを超えるリクエストボディを持つリクエストはすべてブロックするように設定します。この場合、実質的に「WAFを通過するリクエストについては、ボディ全体を検査できる」状態となりますので、セキュリティ上まったく問題ありません。

...セキュリティ上はまったく問題ないのですが、別のところに問題が出そうです。そう、8KBや16KBといったサイズを上限にしてしまうと、そもそもウェブアプリケーションが動かなくなってしまうのです。例えばサイズの小さな写真を1つアップロードするだけでも、簡単に128KBは超えてしまうでしょう。このように「リクエストボディが数KB〜128KB程度の特定のサイズより大きい通信はすべてブロックする」というウェブアプリケーションの運用は極めて非現実的です。

React2Shellでは実際にこの方法で攻撃が来た

2025年12月に大きな話題になったReact2Shell (CVE-2025-55182)では、脆弱性の情報が公開されてすぐに、このWAF回避方法を使った攻撃が観測されました。攻撃者は上記のような知識は持っており、WAFの回避を早い段階から実践していることが明らかになりました。また、あるWAFベンダーはこのReact2Shellの攻撃が激化したタイミングで急遽「ボディ先頭の128KBを検査する」という仕様を「ボディ先頭の1MBまで検査する」と変更することをアナウンスしました。この記事でここまでに示したようにベンダーとしては「リクエストボディが特定のサイズより大きい通信は許可しないように設定してください」というスタンスを取っているはずなので、本来は128KBでも問題がないはずです。しかし急遽仕様を変更したということは、おそらく実際には多くのユーザが「リクエストボディが128KBを超える場合はすべてブロックする」という形では運用できていなかったのでしょう。

React2Shellで「WAFが入っているはずなのに、任意のコード実行の被害が次々に発生する」という状況が現実味を帯びたために、慌てて1MBまでサイズを上げるというアクションが取られたのです。そもそもReact2Shellに限らずSQLインジェクション等の攻撃に対しても同じ状況(=サイズ超過のリクエストをすべてブロックするという形で運用できていない場合、実質的にWAFがいないのと同じ)だったにも関わらず、大きな話題となったReact2Shellでは対応が行われる、という点はとても印象的です。

この1MBへの変更はさらに別のトラブルをもたらしました。多くの環境で128KBから1MBに変更後、WAFによる誤検知(False Positive)で正常通信をブロックしてしまう事象が増えてしまったようで、一部はまた128KBに戻されてしまったようです。

なぜ、ボディの先頭しか検査しないのか?

このように、WAFにおいては「ボディの先頭しか検査しない」という仕様で、かつそのサイズが小さい場合、非常に大きなセキュリティ上の問題があると思います。ベンダーもこの点をわかっているはずですが、このような仕様のWAFは複数存在しているようです。実はこの仕様にはWAF提供側から見て大きなメリットがいくつかあり、そのためにこのような仕様のWAFが存在しているのです。

理由1: CPUやメモリのリソース消費

WAFがデータを検査する場合、対象のデータが大きくなるほどCPUやメモリなどのリソースを多く消費します。少ないデータのみ検査するという仕様にすれば、WAFとして用意すべきコンピューティングリソースを少なく済ませることができます。

理由2: レイテンシの悪化

WAFが別のホストで動作しており、そちらに一度データを送って検査するという仕様で提供されているWAFでは、データが大きくなるとそれだけ転送するのに時間がかかり、結果としてレイテンシが悪化します。また、理由1で述べたCPUリソースに関連しますが、データが大きくなると検査全体に要する時間も増え、こちらもレイテンシの悪化につながります。

理由3: 誤検知の増加

もしWAFが基本的にシグネチャで検知を行っている「シグネチャ依存型WAF」である場合、検査対象のデータが大きくなるほど誤検知(False Positive:本来は正常な通信を攻撃として認識してしまい、意図せぬブロックをしてしまう)が発生してしまいます。これは実際に上記に書いたReact2Shellでの実例としても観測されました。

このようにWAFベンダー側の視点から考えると、ボディ部の先頭の少しのデータしか見ないという仕様には一定の合理性があるのです。

データが増えると誤検知が増える?

話が主題からズレますが、上記の理由3は少し不思議に感じるかもしれません。「検査対象のデータが大きくなるほど、誤検知が増える」という点です。本来、データが大きいということは情報量が多いということになりますから、検査する側にとっては「参考にできる材料が増える」ようなもので、より正確に検知ができそうです。

しかし正規表現などで文字列マッチングを行う「シグネチャ依存型WAF」のアプローチでは、そのようには動いてくれません。シグネチャによる検知(分類)はいわば「減点方式」で、「悪いところだけを探す」という方式です。検査対象のデータに良いところ(正常通信に見えるところ)があってもその点は一切考慮せず、悪いところ(攻撃に見えるところ)だけを探し続け、もし1つでも条件を満たせば攻撃であると判定してしまうのです。そのため皮肉なことに、検査対象の情報量が増え、本来であればより正確に分類ができる方向に向かうはずが、完全に逆になってしまい、誤検知が増える方向に行ってしまうのです。

WAFがシグネチャのみで検知を行うことの問題点については以前、下記の記事にまとめましたので、興味がある方は読んでいただければ幸いです。

  1. シグネチャ依存型のWAFは避けよう
  2. WAFにおけるシグネチャの功罪
  3. 2020年になってもシグネチャ依存型のWAFが多いのはなぜか?

Scutumについて

我々が開発運用しているScutumでは、サービス開始当初の2010年頃から今に至るまで、「ボディの先頭だけを検査しよう」という発想をしたことがありません。容易に回避されてしまう穴は事前に潰しておくのがセキュリティ製品に当然期待される品質だと考えています。

上記の「理由1」に書いたように、ボディ全体を検査対象とする場合は必要となるCPUやメモリのリソースはかなり多くなってしまいます。つまりWAFベンダー側の視点としては、より原価が高くなります。またレイテンシについてもボディの先頭しか検査しないWAFと比較すると少し劣る面もあるかもしれませんが、何とか現実的には問題にならないよう、様々なパフォーマンスチューニングを行って運用しています。Scutumの開発チームは当然セキュリティや分類機能について多くの課題を乗り越えてきましたが、それと同じかそれ以上に、このレイテンシやパフォーマンスの問題とも戦い続けてきました。

WAF評価の場面では「100個の攻撃データを用意して検査してみた。そのうち何個を止められるか?」というような性能評価が行われることがあります。しかしそれ以前の問題として、「簡単に回避できるような仕様の抜けはないか」「WAFとして見るべきところをすべて検査対象にしているか」が重要です。そのWAFが仕様として検査しない部分については、100個の攻撃データのうち、1つも止めることができません。

ご利用中のWAFの検証をサポートします

SSTでは、導入中または導入検討中のWAFに関する評価・検証のお手伝いをいたします。
お気軽にご相談ください。
株式会社セキュアスカイ・テクノロジー
お問い合わせフォーム
TEL:03-3525-8045 (営業時間 平日10:00~18:00)
E-mail:info@scutum.jp