이 문서는 주로 PHP 역직렬화 취약점 시리즈에서 PHP 직렬화 및 역직렬화 원칙에 대한 관련 지식을 공유합니다. 이 문서가 필요한 친구는 이를 참조할 수 있습니다. 그것이 모두에게 도움이 되기를 바랍니다.
머리말
객체의 직렬화 및 역직렬화는 자세히 설명하지 않습니다. PHP에서 직렬화의 결과는 json과 다소 유사한 PHP 사용자 정의 문자열 형식입니다.
우리는 모든 언어로 디자인합니다. 객체의 역직렬화는 여러 가지 문제를 해결해야 합니다
객체를 직렬화한 후 직렬화 결과에는 자체 설명 기능이 있습니다(객체의 특정 유형은 직렬화 결과에서 알 수 있습니다.
물론 유형을 아는 것만으로는 충분하지 않습니다) 또한 이 유형에 해당하는 특정 값을 알아야 합니다.
직렬화 중 권한 제어, 직렬화 필드 등을 사용자 정의할 수 있습니다. 예를 들어 golang에서 수행하는 것이 매우 편리합니다. : 성능에 민감한 일부 시나리오에서는 고성능 서비스(직렬화를 위해 protobuf를 자주 사용함)와 같이 객체 직렬화가 방해가 될 수 없습니다.
공간 성능 문제: 직렬화 후 결과가 너무 길면 안 됩니다. 메모리의 int 객체가 직렬화되고 데이터 길이가 int 길이의 10배가 되면 직렬화 알고리즘에 문제가 있는 것입니다.
이 문서에서는 PHP 코드의 관점에서 직렬화 및 역직렬화만 설명합니다. . 직렬화 및 역직렬화는 객체 데이터에서만 작동한다는 점을 기억하세요. 객체 지향 개발 경험이 있는 사람이라면 누구나 쉽게 이해할 수 있습니다.
1. 직렬화 및 역직렬화 메서드 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. 역직렬화의 매직 메서드
실제로는 위에서 언급한 두 번째 문제에 해당합니다. 하나는 매직 메소드를 통하는 것이고, 두 번째는 커스텀 직렬화 함수입니다. 먼저 매직 메소드인 __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
직렬화가 완료되면 데이터베이스에 다시 연결하는 등의 후속 작업을 수행할 수 있는 __wakeup으로 이동합니다.
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 deserialization
위에서 언급한 자체 설명 함수이므로 직렬화 결과에 객체의 유형이 저장되며 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();
수정했습니다 hack_name을 int 유형으로 역직렬화한 결과, i:12345
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)
객체가 성공적으로 직렬화되었음을 확인할 수 있습니다. 물론, 이러한 종류의 PHP 메커니즘은 유연한 구문을 제공합니다. 그러나 보안 위험도 발생합니다.
관련 권장 사항:
JQuery 직렬화 양식 값이 Json으로 변환됩니다. 설명 예시
위 내용은 PHP 직렬화 및 역직렬화 원칙에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!