PHPによる実装をすることは幅広いサーバー環境での実行ができるため、多くのWebアプリケーションとなり提供されていますが、一方で、経験が少ない開発者やメンテナンスされていないコードには多くの脆弱性が含まれる事があります。
今回の記事では、PHPの「unserialize()」関数が持つ脆弱性に着目し、主に中級者から上級者の開発者を対象に、その使用に伴う危険性を解説します。
また、それを回避するための最適実践や対策法についても解説し、セキュアな開発を支援します。
目次
CVE-2024-10957 脆弱性の概要
今回取り上げるCVE-2024-10957脆弱性は、PHPのunserialize()
関数がもたらす危険性に関連しています。
この脆弱性は、攻撃者が意図的に細工したシリアライズデータをアプリケーションに送り込むことで、不正なオブジェクトを生成し、任意のコード実行やシステム制御を可能にするものです。
脆弱性の詳細については以下を参照してください。それぞれのページによる紹介の仕方は異なりますが、同じ脆弱性 CVE-2024-10957 について紹介しています。
- GitHub Advisory: GHSA-vcp4-p2mp-8fpq
- PHPの
unserialize()
関数の脆弱性により、攻撃者が細工したデータを用いて任意のコードを実行する可能性があります。
- PHPの
- Wordfence: UpdraftPlus
- WordPressの人気プラグインUpdraftPlusにおいて、認証なしでのPHPオブジェクトインジェクションが可能となる脆弱性が報告されています。
- NVD: CVE-2024-10957
- PHPの認証バイパス脆弱性により、攻撃者が高権限を取得し、不正な操作を行う可能性があります。
unserialize()の危険性
PHPのunserialize()
関数は非安全な入力を処理する際に、特にWebアプリケーション開発やCMS(例: WordPress)のプラグインなど、ユーザー入力を直接処理するシステムで使用されることがあります。
攻撃者が細工したシリアライズデータを送り込むことで、任意のコード実行やシステム制御を行えるため、これらのシステムに重大なリスクをもたらします。
以下に、具体的な危険性を挙げます。
1. データの信頼性の問題
攻撃者が組み上げたシリアライズデータを、unserialize()
は直接処理してしまいます。これにより、不正なクラスのインスタンスを再現され、想定外の動作が実行される可能性があります。
2. マジックメソッドの想定外の呼び出し
__wakeup
、__destruct
、__toString
などのマジックメソッドが攻撃の内容に使用されることがあります。攻撃者はこれを利用し、想定外の操作を自動実行させることが可能です。
3. 型の混乱 (Type Confusion)
PHPのunserialize()
はデータの型を不正に変更される危険性を含みます。これにより、例えば「数値のみ可能」と思われていた場所でオブジェクトが使われるような情報流出が起こりえます。
サンプルコードによる解説
unserialize()
の危険性を具体的に理解するためには、サンプルコードを用いた解説が理解しやすいかと思います。
コードを通じて、実際のリスクや攻撃の流れを直感的に把握することができます。以下にその具体例を示します。
危険な例: 細工されたシリアライズデータの処理
class FileManager {
public $filename;
public function __destruct() {
// ファイルの内容を出力
echo file_get_contents($this->filename);
}
}
// 攻撃者が細工したデータ
$malicious_data = 'O:11:"FileManager":1:{s:8:"filename";s:12:"/etc/passwd";}';
// unserialize()を使用してデータを復元
unserialize($malicious_data);
このコードの問題点:
- 攻撃者は、
unserialize()
に細工したデータを送り込み、FileManager
クラスを作成することでシステムのファイル(例:/etc/passwd
)を読み取ることができます。 __destruct
メソッドはオブジェクトが破棄された時に自動的に呼び出されるため、作成者の意図しない操作を実行できます。
UpdraftPlusによる対策
今回取り上げた CVE-2024-10957は WordPressのUpdraftPlusプラグインに含まれていて、すでに解決されている脆弱性です。
解決するためにプラグイン内のコードが編集されており、対応策としては、unserialize()
を直接使用するのではなく、プラグイン独自で「UpdraftPlus::unserialize()」関数を作成し、その中でデータチェックやクラスの有効化をしています。
あらかじめわかっている unserialize()
関数による問題点を回避するための有効な手段となります。
unserialize()の代替案
ここでは UpdraftPlusプラグイン の対応方法を参考にしつつ、PHPアプリケーションの開発者である皆さんでの対処方法をまとめていきます。
- JSONを使用する
- 使用例: ユーザーデータを安全にやり取りする。
$data = ["name" => "John", "role" => "admin"];
$json = json_encode($data); $decoded = json_decode($json, true);
- allowed_classesを使用する
- 使用例: 特定のクラスのみを許可。
- 適用が難しいケース: 許可リストの管理が複雑な場合。
$data = 'O:8:"stdClass":0:{}';
$object = unserialize($data, ["allowed_classes" => ["stdClass"]]);
- 自己定義のデコーダーを使用する
- 使用例: データを安全な形式で復元。
- 適用が難しいケース: 複雑なオブジェクト構造を扱う必要がある場合。
function custom_decoder($data) { // 安全な解析処理を実装
return json_decode($data, true);
}
$safe_data = custom_decoder('{"key":"value"}');
おわりに
unserialize()
は便利ですが、その脆弱性は大きな危険を含んでいます。
試行と研究を続け、最適な安全実践を維持してください。
コメントを残す