ホームページ  >  記事  >  バックエンド開発  >  PHP のシリアル化と逆シリアル化の原理の詳細な説明

PHP のシリアル化と逆シリアル化の原理の詳細な説明

小云云
小云云オリジナル
2018-01-16 13:40:142902ブラウズ

この記事では、主に PHP デシリアライゼーションの脆弱性シリーズの PHP シリアル化とデシリアライゼーションの原理に関する関連知識を共有します。必要な方は参照してください。皆さんのお役に立てれば幸いです。

前書き

PHP でのオブジェクトのシリアル化と逆シリアル化の結果は、JSON に似た PHP カスタマイズされた文字列形式になります。

私たちは任意の言語で設計します。オブジェクトの逆シリアル化には、いくつかの問題を解決する必要があります

オブジェクトをシリアル化した後、シリアル化の結果には自己記述関数が含まれます (オブジェクトの特定の型はシリアル化の結果からわかります。

もちろん、型を知るだけでは十分ではありません)このタイプに対応する特定の値も知っておく必要があります)。

シリアル化中の権限制御、シリアル化フィールドなどをカスタマイズできます。たとえば、golang で行うと非常に便利です。問題点: 一部のパフォーマンス重視のシナリオでは、オブジェクトのシリアル化が障害になることはありません。高パフォーマンスのサービス (私はシリアル化に protobuf をよく使用します)

スペースのパフォーマンスの問題: たとえば、シリアル化後の結果が長すぎることはできません。 , メモリ内の int オブジェクトがシリアル化され、データ長が int の長さの 10 倍になる場合は、シリアル化アルゴリズムに問題があります

この記事では、php コードの観点から php のシリアル化と逆シリアル化についてのみ説明します。シリアル化と逆シリアル化はオブジェクト データに対してのみ動作することを覚えておいてください。オブジェクト指向開発の経験がある人なら誰でも、これを簡単に理解できるはずです。 unserialize

php は、C++ とは異なり、オブジェクトのシリアル化関数をネイティブに提供します。 ..^_^. 使い方も非常に簡単で、インターフェイスは 2 つだけです。

class fobnn
{
 public $hack_id;
 private $hack_name;
 public function __construct($name,$id)
 {
  $this->hack_name = $name;
  $this->hack_id = $id;
 }
 public function print()
 {
  echo $this->hack_name.PHP_EOL;
 }
}
$obj = new fobnn('fobnn',1);
$obj->print();
$serializedstr = serialize($obj); //通过serialize接口序列化
echo $serializedstr.PHP_EOL;;
$toobj = unserialize($serializedstr);//通过unserialize反序列化
$toobj->print();

fobnn
O:5:"fobnn":2:{s:7:"hack_id";i:1;s:16:"fobnnhack_name";s:5:"fobnn";}
fobnn

出力の 2 行目を参照してください。この文字列はシリアル化の結果です。この構造は実際には簡単です。もちろん、異なるアクセス権を持つメンバーのシリアル化後のラベル名は少し異なります。上記の 3 つの質問によると、次のことがわかります。見てください

1. 自己記述関数

O:5:"fobnn":2 ここで、o はオブジェクトの型を表し、型名は fobnn です。次の 2 は、2 つのメンバー オブジェクトがあることを示します。


メンバー オブジェクトに関しては、実際には同じサブ記述のセットです。

自己記述関数は、主に文字列を通じてオブジェクトとメンバーの名前を記録することによって実装されます。パフォーマンスの問題

PHP シリアル化の時間パフォーマンスはこの記事では分析されません。詳細は後ほど参照しますが、シリアル化の結果は実際には json/bson で定義されたプロトコルに似ています。プロトコル ヘッダーには、プロトコル ヘッダーが記述されています。型に対応する値がシリアル化結果を圧縮しないことを説明しています

2. 実際には、上記の 2 番目の問題に対応します。これも PHP での解決策です。1 つはマジック メソッドを使用するもので、2 つ目はカスタム シリアル化関数を使用するものです。まず、シリアル化する前に __sleep と __wakeup を導入します。最初に __sleep が呼び出されます。 return シリアル化する必要があるメンバー名の配列です。この場合、hack_name メンバーのみがシリアル化されていることがわかります。

シリアル化が完了すると、データベースへの再接続などのフォローアップ作業を行うことができる __wakeup にジャンプします。

class fobnn
{
 public $hack_id;
 private $hack_name;
 public function __construct($name,$id)
 {
  $this->hack_name = $name;
  $this->hack_id = $id;
 }
 public function print()
 {
  echo $this->hack_name.PHP_EOL;
 }
 public function __sleep()
 {
  return array("hack_name");
 }
 public function __wakeup()
 {
  $this->hack_name = 'haha';
 }
}
$obj = new fobnn('fobnn',1);
$obj->print();
$serializedstr = serialize($obj);
echo $serializedstr.PHP_EOL;;
$toobj = unserialize($serializedstr);
$toobj->print();

このインターフェイスを通じて、シリアル化と逆シリアル化の動作をカスタマイズできます。この関数は主にシリアル化形式をカスタマイズするために使用できます。

fobnn
O:5:"fobnn":1:{s:16:"fobnnhack_name";s:5:"fobnn";}
haha

interface Serializable {
abstract public string serialize ( void )
abstract public void unserialize ( string $serialized )
}

カスタムシリアル化インターフェイスが使用されている場合、マジックメソッドは役に立ちません。


4 .PHP 動的型とPHPの逆シリアル化


上記の自己記述関数では、オブジェクトの型がシリアル化結果に保存され、PHPは動的型言語であるため、簡単な実験を行うことができます

class fobnn implements Serializable
{
 public $hack_id;
 private $hack_name;
 public function __construct($name,$id)
 {
  $this->hack_name = $name;
  $this->hack_id = $id;
 }
 public function print()
 {
  echo $this->hack_name.PHP_EOL;
 }

 public function __sleep()
 {
  return array('hack_name');
 }

 public function __wakeup()
 {
  $this->hack_name = 'haha';
 }

 public function serialize()
 {
  return json_encode(array('id' => $this->hack_id ,'name'=>$this->hack_name ));
 }

 public function unserialize($var)
 {
  $array = json_decode($var,true);
  $this->hack_name = $array['name'];
  $this->hack_id = $array['id'];
 }
}
$obj = new fobnn('fobnn',1);
$obj->print();
$serializedstr = serialize($obj);
echo $serializedstr.PHP_EOL;;
$toobj = unserialize($serializedstr);
$toobj->print();

hack_name の逆シリアル化結果を int 型、i:12345 に変更しました

fobnn
C:5:"fobnn":23:{{"id":1,"name":"fobnn"}}
fobnn

オブジェクトが正常にシリアル化されていることを確認できます! もちろん、この種の PHP メカニズムは柔軟な構文を提供します。ですが、セキュリティ リスクも発生します。PHP のシリアル化と逆シリアル化の機能によって引き起こされるセキュリティ問題の分析を継続します。 Json例の説明

PHPセッションデシリアライゼーションの脆弱性の詳細説明

以上がPHP のシリアル化と逆シリアル化の原理の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。