目次
Cookie、キャッシュ、ジョブのキューなどでは、以前保存した値を読み戻す処理が日常的に動きます。その際、単なる文字列の読み込みと、クラスや振る舞いを持つオブジェクトの復元は同じではありません。復元の途中で処理が動く仕組みでは、後から内容を検証しても間に合わない場合があります。
本記事は2026年10月18日にOWASPとPHPの一次資料を確認した実務解説です。特定の脆弱性や侵害事件の速報ではありません。移行の順序と試験方法は、本サイトの提案です。実際のAPIの動作は、利用する言語とライブラリーの公式仕様で確かめてください。
スポンサーリンク
復元してから安全か調べる順序を見直す
シリアライズは、データを保存や転送できる形へ変換する処理です。デシリアライズはその読み戻しですが、何を復元できるかは形式によって異なります。文字列と数値を読む処理もあれば、クラスを作り、復元時のメソッドを呼ぶ処理もあります。
PHPのunserializeの公式マニュアルは、allowed_classesの設定にかかわらず、信頼しない入力を渡さないように警告しています。復元でオブジェクトが作られると、オートロードや特別なメソッドが関係するためです。
したがって、復元した結果を見てクラス名が正しいか調べるだけでは、復元時の副作用を防いだことになりません。危険な振る舞いを持つ形式を入口で使わないことと、値の妥当性を確認することを分けて考えます。
出典:OWASP Deserialization Cheat Sheet。
保存先の名称ではなく値の来歴を見る
Cookieやフォームの隠し項目は、利用者が変えられる入力として扱います。画面に編集欄がないことや、値が長く読みにくいことは、改変を防ぐ条件ではありません。符号化や圧縮も、真正性を保証する仕組みとは違います。
キャッシュやDBにある値も、どの経路から保存されたかを追います。外部入力を加工して入れた値、別サービスが書いた値、利用者のアップロードを取り込んだ値では、サーバー内に置かれた後も元の信頼境界が残ります。
ジョブのキューでは、書き込めるサービスとワーカーの権限を対応させます。読み戻す側が強い権限を持つとき、低い権限の入口から届くデータを、強い権限で処理しない設計が必要です。保存場所が内部だから安全という判断で止めないでください。
スポンサーリンク
交換するのは振る舞いより必要な値にする
本サイトの提案は、外部との交換には必要な値だけを明示したデータ形式を使うことです。識別子、日時、件数、選択肢などを項目として定義し、クラス名や任意のメソッドを選ばせる情報を受け付けないようにします。
JSONを使えばそれだけで安全になるわけではありません。型、必須項目、長さ、深さ、件数、許す値を検証し、受け取ったデータから内部の任意のクラスを動的に作らないことが必要です。オブジェクト復元をやめた後にも、認可や問い合わせの安全性は残ります。
たとえば配送ジョブには、対象注文のIDと処理の種類を持たせ、実行時に現在の注文を読み直す方法が考えられます。保存した時点の情報を丸ごと復元して、現在の権限や取消状態を無視しないようにします。
署名は復元前に確認し用途を限定する
改変検知のために署名やMACを使う構成では、検証を復元前に行う必要があります。検証に失敗した後に、内容の確認だけを目的として危険な復元処理を呼び出さないようにします。秘密鍵や共有秘密の管理も別の作業です。
署名は、発行者が想定する用途のデータであることまで自動では保証しません。本サイトの提案として、形式の版、目的、対象、期限などを設計へ含め、別の機能で発行した値の使い回しや、古い値の再送をどう扱うかを決めます。
発行側が侵害された場合や、署名の付いた値そのものが危険な形式である場合も考慮します。署名を追加したから任意のオブジェクトを復元してよい、と一般化せず、復元できる機能を減らす対策を優先します。
スポンサーリンク
旧形式への自動フォールバックを残さない
移行では、新しい形式を読めないときに古い形式を試す処理が残りがちです。外部入力を新形式として読むのに失敗しただけで、より危険なオブジェクト復元へ回すと、移行後も古い入口が使えます。
形式の版と読み取り元を明示し、どの経路でどの形式を認めるかを決めます。新しい入口では旧形式を受け付けず、過去の保存データの移行は、対象と期間を限定した別の処理として扱う方法が考えられます。
既存データの変換が必要な場合も、本番アプリの全権限で一括実行しないようにします。バックアップを取り、対象件数、失敗時の扱い、必要なアクセス先を定義します。危険な復元が必要な旧データは、信頼性を確認できる対象へ絞って慎重に扱います。
依存関係と実行権限を合わせて点検する
危険性は復元関数だけで決まらず、利用できるクラスやライブラリーにも左右されます。依存関係を減らし、更新を継続することは必要ですが、既知の悪用例が見つからないことを理由に、信頼しない入力の復元を許可しないでください。
ワーカーのファイルアクセス、ネットワーク、DBの権限を業務に合わせて限定します。これは被害を抑える対策であり、危険な形式を安全な形式へ変換する代わりにはなりません。実行環境を分ける場合も、秘密や共有の保存先を広く渡していないかを確認します。
入力のサイズや階層、実行時間にも上限を設けます。コード実行だけに注目すると、大量のデータや深い構造で処理資源を消費する条件を見落とすことがあります。
安全な試験で復元前の拒否を確認する
検証環境では、正常なデータ、署名が違うデータ、期限切れ、未知の版、欠けた項目、深過ぎる構造を用意します。エラーが返ることに加え、拒否する前に復元用の処理や副作用が動いていないことを確認します。
危険なクラスの連鎖を本番へ送る試験は不要です。自分たちが管理する無害な観測用の処理を使い、どの段階まで進んだかを確認できる設計にします。試験用の計測が本番へ残らないように管理してください。
正常な旧データが読めることだけでなく、移行後の入口が旧形式を拒否することも合格条件にします。ログには生のCookie、署名付きの秘密、個人情報を残さず、版や拒否理由など必要な識別情報を記録します。
移行対象を入口と保存期間で分類する
本サイトの提案として、復元する値を、短期間で消える状態、長期間残す業務データ、別サービスとの交換に分けます。短い寿命のキャッシュなら、新しい形式で作り直せる場合があります。一方、長期のデータは、変換結果を照合してから切り替える手順が必要になります。
分類ごとに、書き込む側を新形式へ切り替える時点、旧形式を読み取る期限、失敗したデータの扱いを決めます。新形式の読み取りだけを追加し、旧形式の書き込みを止めないと、移行が終わる条件がいつまでも成立しません。
破損した値は、無理に復元して救うより、業務上の再取得や利用者による再操作で回復できないかを検討します。復旧の便利さのために危険な解析を常に有効にする設計を避けることが目的です。
スポンサーリンク
注文ジョブを値だけへ変える仮想例
仮想のサイトで、注文オブジェクト全体をキューへ保存しているとします。移行案として、注文の識別子、業務上の操作、形式の版だけを保存し、ワーカーが現在の状態を読み直す方式を比較します。これにより、必要のない内部の参照を復元する場面を減らせます。
一方、読み直すと作成時とは値が変わるため、会計上の確定内容など、保存すべき事実を別に定義する必要があります。安全のための形式変更で、業務上保持すべき記録まで消さないでください。必要な確定値を、明示した項目として保存する方法を検討します。
ジョブの発行権限と、現在の注文へ操作できる条件も照合します。形式を変えた後でも、任意のIDを指定して他人の注文を動かせるなら認可の問題が残ります。オブジェクト復元の廃止と、業務の権限の確認を同じ変更の中でレビューします。
処理の境界を証拠として残す
改修レビューには、入力を読む前に何を確認するか、どの段階で型を確定するか、どのAPIを廃止したかを記録します。失敗したデータをどの処理へも再投入しないことが、運用ツールを含めて守られるかを確認します。
形式の判定に失敗した値を、調査用のスクリプトで復元する例外も、同じリスクを持ちます。運用者向けの手順へ安全な観測方法を書き、復元をしないと調べられない状態を減らすことが、再発防止につながります。
スポンサーリンク
廃止したことを運用で確かめる
改修後は、アプリ本体、バッチ、管理画面、障害復旧用のツールを含めて、危険な復元APIの利用箇所を確認します。新しいコードで使っていなくても、旧機能が別の入口から動ける場合があります。
移行が終わった読み取り経路は、期限を決めて削除します。使われていないことの確認と、呼ばれたら分かる記録を組み合わせると、例外として残した入口を放置しにくくなります。データの保存形式を変える作業は、復元できる権限を減らす作業でもあります。
参考資料
以下の一次資料を2026年10月18日に確認しました。本文の仮想例と運用手順の提案は、資料の引用とは区別しています。









