이 문서는 PHP 역직렬화 취약점 시리즈에서 PHP 직렬화 및 역직렬화 원칙에 대한 관련 지식을 공유합니다. 이 문서가 필요한 친구는 이를 참조할 수 있습니다.
0. 서문
객체의 직렬화 및 역직렬화는 자세히 설명하지 않습니다. PHP의 직렬화 결과는 json과 다소 유사한 PHP 사용자 정의 문자열 형식입니다.
모든 언어에서 사용할 수 있습니다. 객체 직렬화 및 역직렬화를 설계할 때 해결해야 할 몇 가지 문제가 있습니다. 객체를 직렬화한 후 직렬화 결과에는 자체 설명 기능이 있습니다(객체의 특정 유형은 직렬화 결과에서 알 수 있으므로
유형을 아는 것만으로는 충분하지 않습니다). , 물론 이 유형에 해당하는 특정 값도 알아야 합니다.
직렬화 중 권한 제어, 직렬화 필드 등을 사용자 정의할 수 있습니다. 예를 들어 golang에서는 매우 편리합니다.
시간 성능 문제: 성능에 민감한 일부 시나리오에서는 고성능 서비스(직렬화에 protobuf를 자주 사용함)와 같이 객체 직렬화가 방해가 될 수 없습니다.
공간 성능 문제: 직렬화 후 결과가 너무 길어서는 안 됩니다. , 메모리의 int 객체가 직렬화되어 데이터 길이가 int 길이의 10배가 된다면 이 직렬화 알고리즘에 문제가 있는 것입니다.
이 기사에서는 PHP 코드의 관점에서 PHP의 직렬화 및 역직렬화만 설명합니다. 직렬화 및 역직렬화는 객체 데이터에서만 작동한다는 점을 기억하세요. 객체 지향 개발 경험이 있는 사람이라면 누구나 쉽게 이해할 수 있습니다.
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. 역직렬화의 마법 메서드
실제로도 이 문제에 해당합니다. 해결책은 PHP에 있습니다. 하나는 매직 메소드를 이용하는 것이고, 두 번째는 직렬화 전에 매직 메소드 __sleep 및 __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
3 직렬화 가능 인터페이스를 사용자 정의하세요
interface Serializable { abstract public string serialize ( void ) abstract public void unserialize ( string $serialized ) }
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();
fobnn C:5:"fobnn":23:{{"id":1,"name":"fobnn"}} fobnn
4. PHP 동적 타입과 PHP 역직렬화
위에서 언급한 자기 서술형 함수이므로 직렬화 결과에 객체의 타입이 저장되고, PHP는 동적 타입 언어이므로 간단한 실험을 해볼 수 있습니다.
class fobnn { public $hack_id; public $hack_name; public function __construct($name,$id) { $this->hack_name = $name; $this->hack_id = $id; } public function print() { var_dump($this->hack_name); } } $obj = new fobnn('fobnn',1); $obj->print(); $serializedstr = serialize($obj); echo $serializedstr.PHP_EOL;; $toobj = unserialize($serializedstr); $toobj->print(); $toobj2 = unserialize("O:5:\"fobnn\":2:{s:7:\"hack_id\";i:1;s:9:\"hack_name\";i:12345;}"); $toobj2->print();
string(5) "fobnn" O:5:"fobnn":2:{s:7:"hack_id";i:1;s:9:"hack_name";s:5:"fobnn";} string(5) "fobnn" int(12345)
PHP7 확장 개발의 안녕하세요 단어 구현 방법에 대한 자세한 설명
PHP 확장 기능 개발 함수 기반의 lib 라이브러리 사용법에 대한 자세한 설명
위 내용은 PHP 직렬화 및 역직렬화 원칙에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!