Unicodeオーバーフローで文字ブロックリストを回避する手口――コードポイント切り捨ての落とし穴
元ソースは、PortSwigger Researchの記事「Bypassing character blocklists with unicode overflows」です。
概要
PortSwigger Researchは、Unicodeの文字(コードポイント)をサーバ側で誤って「1バイト」で扱おうとしたときに発生するコードポイントの切り捨て(truncation)を、文字制限の回避に悪用できるケースとして紹介しています。記事中では、この現象を「Unicode codepoint truncation」あるいは「Unicode overflow attack」と呼び、最大値が255である1バイトへ格納しようとする設計が根本原因になり得る、と説明しています。
文字ブロックリスト(特定の文字だけを禁止する方式)は、入力を止める最前線として使われがちです。しかし、検証が「Unicode文字としての意味」を前提にしている一方で、保存・比較・照合のどこかが8ビット(1バイト)に丸められると、同じ入力でも“別の値”として扱われる可能性が生まれます。そのズレが、結果として「禁止したはずの文字」を別表現で通してしまう抜け道になります。
詳細
ポイントは、Unicodeのコードポイントは1バイトに収まらない範囲が広いのに対し、1バイトは0〜255までしか表現できない、という単純な制約です。PortSwigger Researchは、サーバがUnicode文字を1バイトに格納しようとして切り捨てが起きると、入力文字が本来のコードポイントのまま保持されず、別の値(別の文字や別のバイト値)として残り得る、と述べています。ここで「入力チェックで見ていたもの」と「後段で実際に扱うもの」の間に差が生じ、ブロックリストのような“特定文字に依存する防御”が破綻しやすくなります。
この種の問題が厄介なのは、アプリケーション全体のどこか1箇所でも「1バイト前提」の処理が紛れ込むと、前段でどれだけ丁寧に検証していても効果が薄れる点です。たとえば、入力の受付はUnicode前提でも、途中で古い型・古いAPI・独自実装の変換処理などを通って1バイト化(あるいは実質的な切り捨て)されると、禁止文字の判定やログ、監査、後続処理の分岐が想定外の挙動になります。PortSwigger Researchの記事は、こうした「表現の不一致」そのものが攻撃面(attack surface)になる、という注意喚起として読むのが重要です。
対策の方向性は、文字そのものを“禁止リスト”で追いかける発想から一段引いて、(1) 入力の正規化と、(2) 検証・保存・比較で同じ表現を一貫して使うこと、(3) そもそも損失のある変換(1バイト化や切り捨て)が起きないデータ型・保存形式を選ぶこと、に集約されます。特に「どの層がどのエンコーディング/型で文字を扱っているか」を明示し、境界(リクエスト受信、DB格納、ログ出力、検索キー化など)ごとに“丸めが起きない”ことをテストで確認できる状態にしておくことが、同種のすり抜けを防ぐ実務的な要点になります。
なお本件は、PortSwiggerの元記事に言及する投稿がX(旧Twitter)やLinkedIn上でも共有されており、セキュリティ実務者の間で「文字制限の実装の甘さが攻撃に直結する」論点として注目されていることがうかがえます。
出典
- 元ソースBypassing character blocklists with unicode overflowsPortSwigger Research
- [XML] https://portswigger.net/sitemap.xmlportswigger.net
- All Articles - PortSwigger Researchportswigger.net
- Bypassing character blocklists with unicode overflowsx.com
- Bypassing character blocklists with unicode overflowsx.com
- Bypassing character blocklists with unicode overflows | Luke J.linkedin.com