>  기사  >  백엔드 개발  >  역직렬화 구조 지식 포인트에 대한 PHP 간략한 분석

역직렬화 구조 지식 포인트에 대한 PHP 간략한 분석

WBOY
WBOY앞으로
2022-07-29 15:18:582014검색

이 글에서는 주로 PHP에 대한 관련 지식을 소개합니다. 직렬화는 실제로 데이터를 가역적 데이터 구조로 변환하는 과정을 역직렬화라고 합니다. PHP는 데이터를 직렬화 및 역직렬화하기 위해 두 가지 기능을 사용합니다. 직렬화는 개체를 순서가 지정된 문자열로 형식화하고, 직렬화 해제는 문자열을 원래 개체로 복원합니다. 모든 사람에게 도움이 되기를 바랍니다.

역직렬화 구조 지식 포인트에 대한 PHP 간략한 분석

(추천 튜토리얼: PHP 비디오 튜토리얼)

소개

직렬화의 목적은 데이터의 전송과 저장을 용이하게 하는 것입니다. PHP에서 직렬화와 역직렬화는 일반적으로 세션 캐싱과 같은 캐싱에 사용됩니다. , 쿠키 등

deserialize의 일반적인 매직 메소드

  • __wakeup() //unserialize()를 실행할 때 이 함수가 먼저 호출됩니다.

  • __sleep() //serialize()가 실행될 때 이 함수가 먼저 호출됩니다.

  • __destruct() //객체가 파괴될 때 트리거됨

  • __call() //객체 컨텍스트에서 액세스할 수 없는 메서드가 호출될 때 트리거됨

  • __callStatic() //정적에서 호출될 때 액세스할 수 없음 context

  • __get() 메소드가 실행될 때 트리거됩니다. //이 메소드는 액세스할 수 없는 속성에서 데이터를 읽거나 키가 존재하지 않을 때 호출됩니다.

  • __set() //액세스할 수 없는 속성에 데이터를 쓰는 데 사용됩니다. 속성

  • __isset() //액세스할 수 없는 속성에서 isset() 또는empty()를 호출할 때 트리거됩니다.

  • __isset() //액세스할 수 없는 속성에서 unset()을 사용할 때 트리거됩니다.

  • __toString() / /클래스를 문자열로 사용할 때 트리거됨

  • __invoke() //객체를 함수로 호출하려고 할 때 트리거됨

역직렬화는 작은 트릭을 우회함

php7.1+ 직렬화는 클래스 속성에 민감하지 않음

앞서 변수가 보호되면 직렬화 결과 앞에 x00*x00x00*x00

但在特定版本7.1以上则对于类属性不敏感,比如下面的例子即使没有x00*x00也依然会输出abc

<?php
class test{
    protected $a;
    public function __construct(){
        $this->a = &#39;abc&#39;;
    }
    public function  __destruct(){
        echo $this->a;
    }
}
unserialize(&#39;O:4:"test":1:{s:1:"a";s:3:"abc";}&#39;);

绕过_wakeup(CVE-2016-7124)

版本:

PHP5 < 5.6.25

PHP7 < 7.0.10

利用方式:序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行

对于下面这样一个自定义类

<?php
class test{
    public $a;
    public function __construct(){
        $this->a = &#39;abc&#39;;
    }
    public function __wakeup(){
        $this->a=&#39;666&#39;;
    }
    public function  __destruct(){
        echo $this->a;
    }
}

如果执行unserialize('O:4:"test":1:{s:1:"a";s:3:"abc";}');输出结果为666

而把对象属性个数的值增大执行unserialize('O:4:"test":2:{s:1:"a";s:3:"abc";}');输出结果为abc

绕过部分正则

preg_match('/^O:d+/')匹配序列化字符串是否是对象字符串开头,这在曾经的CTF中也出过类似的考点

利用加号绕过(注意在url里传参时+要编码为%2B)

serialize(array(a ) ) ; / / a));//a));//a为要反序列化的对象(序列化结果开头是a,不影响作为数组元素的$a的析构)

<?php
class test{
    public $a;
    public function __construct(){
        $this->a = &#39;abc&#39;;
    }
    public function  __destruct(){
        echo $this->a.PHP_EOL;
    }
}
function match($data){
    if (preg_match(&#39;/^O:\d+/&#39;,$data)){
        die(&#39;you lose!&#39;);
    }else{
        return $data;
    }
}
$a = &#39;O:4:"test":1:{s:1:"a";s:3:"abc";}&#39;;
// +号绕过
$b = str_replace(&#39;O:4&#39;,&#39;O:+4&#39;, $a);
unserialize(match($b));
// serialize(array($a));
unserialize(&#39;a:1:{i:0;O:4:"test":1:{s:1:"a";s:3:"abc";}}&#39;);

利用引用

<?php
class test{
    public $a;
    public $b;
    public function __construct(){
        $this->a = &#39;abc&#39;;
        $this->b= &$this->a;
    }
    public function  __destruct(){

        if($this->a===$this->b){
            echo 666;
        }
    }
}
$a = serialize(new test());

上面这个例子将$b设置为$a的引用,可以使$a永远与$b

이 붙는다고 말했지만 특정 버전 7.1 이상에서는 클래스 속성에 대해 민감하지 않습니다. 예를 들어 다음 예는 다음과 같습니다. x00*x00

rrreee

Bypass_wakeup(CVE-2016-7124)

Version:

PHP5 <

PHP7 < 7.0.10

사용 방법: 직렬화된 문자열의 객체 속성 수를 나타내는 값이 실제 속성 수보다 클 경우 __wakeup 실행을 건너뜁니다.

다음과 같은 사용자 정의 classrrreeeunserialize('O:4:"test":1:{s:1:"a";s:3:"abc";}');를 실행하면 출력됩니다. 결과는 666

🎜이고 객체 속성 개수의 값이 증가하여 실행됩니다. unserialize('O:4:"test":2:{s:1:"a"; s:3:"abc";}');출력 결과는 abc🎜🎜일부 일반 규칙 우회🎜🎜preg_match('/^O:d+/')입니다. 직렬화된 문자열이 객체 문자열로 시작하는지 여부를 일치시킵니다. 이는 이전 CTF의 유사한 테스트 포인트였습니다.🎜🎜바이패스하려면 더하기 기호를 사용하세요(URL에서 매개변수를 전달할 때 +는 %2B로 인코딩되어야 함). 🎜 🎜<code>serialize(array(a ) ) ; / / a));//a));//a는 역직렬화할 객체입니다(직렬화 결과는 a로 시작하며 이는 영향을 주지 않습니다). 배열로 사용 $a)🎜rrreee🎜참조 사용🎜rrreee🎜위의 예에서는 $b$a의 참조로 설정합니다. code>$a 는 항상 $b🎜🎜16진수로 문자 필터링을 우회합니다🎜🎜O:4:"test":2:{s:4:"%00*%00a " ;s:3:"abc";s:7:"%00test%00b";s:3:"def";}🎜🎜다음과 같이 쓸 수 있습니다🎜🎜O:4:"test":2:{S :4: "

위 내용은 역직렬화 구조 지식 포인트에 대한 PHP 간략한 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 jb51.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제