>  기사  >  백엔드 개발  >  PHP 직렬화 및 역직렬화 구문 차이점

PHP 직렬화 및 역직렬화 구문 차이점

(*-*)浩
(*-*)浩원래의
2019-11-21 10:40:122570검색

P 공식 문서에서는 PHP 직렬화 및 종속화를 소개합니다.

PHP 직렬화 및 역직렬화 구문 차이점

Environment

글에 설명된 콘텐츠의 사용 환경은 다음과 같습니다.

所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示。unserialize()函数能够重新把字符串变回php原来的值。序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。为了能够unserialize()一个对象,这个对象的类必须已经定义过。如果序列化类A的一个对象,将会返回一个跟类A相关,而且包含了对象所有变量值的字符串。

환경 구성 권장 사항: "

Windows에서 VSCODE를 사용하여 PHP7 소스 코드 디버깅

"매개변수 역직렬화 실행 프로세스 매우 상세하지만 직렬화와 역직렬화의 구문 차이를 포함하여 일부 세부 사항에 몇 가지 단점이 있습니다

차이 문제

직렬화

컴파일된 PHP 커널 소스 코드를 분석한 결과 PHP 직렬화를 발견했습니다. 문자열로 연결하기 위해 기본적으로 객체 변환에 { 및 }를 추가합니다.

PHP7.3.1、SDK
VSCode
C++和C

위 코드를 살펴보겠습니다. PHP는 smart_str_appendl을 사용하여 직렬화된 문자열({and})을 연결하고 var.c의 882번째 줄부터 시작하는 직렬화 논리를 입력합니다. 직렬화된 문자열 접합은 896행에서 수행되며, 952행과 995행은 인라인 방식으로 접합됩니다.

Deserialization

Deserialization은 특정 문법 규칙에 따라 직렬화된 문자열을 변환하고 복원하는 것입니다.

[var.c]
Line:882
static void php_var_serialize_intern()

Line:896
if (ce->serialize(struc, &serialized_data, &serialized_length, (zend_serialize_data *)var_hash) == SUCCESS) {
                        smart_str_appendl(buf, "C:", 2);
                        smart_str_append_unsigned(buf, ZSTR_LEN(Z_OBJCE_P(struc)->name));
                        smart_str_appendl(buf, ":\"", 2);
                        smart_str_append(buf, Z_OBJCE_P(struc)->name);
                        smart_str_appendl(buf, "\":", 2);

                        smart_str_append_unsigned(buf, serialized_length);
                        smart_str_appendl(buf, ":{", 2);
                        smart_str_appendl(buf, (char *) serialized_data, serialized_length);
                        smart_str_appendc(buf, '}');
                    }

Line:952
smart_str_appendl(buf, ":{", 2);

Line:995
smart_str_appendc(buf, '}');

커널 코드를 통해 655행이 역직렬화에 들어가는 것을 볼 수 있습니다. 역직렬화는 어휘 스캐닝을 사용하여 각 기호 변환의 해당 객체를 결정합니다. deserialization 중에 }가 처리되는 것을 볼 수 있습니다. 처리 중에 카운터는 1씩만 증가하고 다른 작업은 수행되지 않습니다.

실제 효과

역직렬화 구문의 차이는 보안 보호 장비의 역직렬화 판단에 큰 영향을 미칩니다. Snort에는 다음과 같은 규칙이 있습니다.

[var_unserialize.c]
Line:655
static int php_var_unserialize_internal()

Line:674
{
    YYCTYPE yych;
    static const unsigned char yybm[] = {
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
        128, 128, 128, 128, 128, 128, 128, 128, 
        128, 128,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
          0,   0,   0,   0,   0,   0,   0,   0, 
    };
    if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
    yych = *YYCURSOR;
    switch (yych) {
    case &#39;C&#39;:
    case &#39;O&#39;:    goto yy4;
    case &#39;N&#39;:    goto yy5;
    case &#39;R&#39;:    goto yy6;
    case &#39;S&#39;:    goto yy7;
    case &#39;a&#39;:    goto yy8;
    case &#39;b&#39;:    goto yy9;
    case &#39;d&#39;:    goto yy10;
    case &#39;i&#39;:    goto yy11;
    case &#39;o&#39;:    goto yy12;
    case &#39;r&#39;:    goto yy13;
    case &#39;s&#39;:    goto yy14;
    case &#39;}&#39;:    goto yy15;
    default:    goto yy2;
    }

Line:776
yy15:
    ++YYCURSOR;
    {
    /* this is the case where we have less data than planned */
    php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data");
    return 0; /* not sure if it should be 0 or 1 here? */
}

공격 페이로드에서 대부분의 문자를 {} 대신 사용할 수 있으므로 규칙이 무효화됩니다.

요약

PHP 직렬화 및 역직렬화 구문의 차이점은 레드팀 공격에서 보호를 우회하기 위해 악용될 수 있습니다.

블루팀 방어에서는 객체를 저장하지 않고 클래스 이름만 저장한다는 정의에 설명된 방법을 고려하는 것이 좋습니다. , 저장된 클래스의 이름을 가로채고 방어를 위해 콜론과 같은 구문에 동일한 문자를 사용합니다.

위 내용은 PHP 직렬화 및 역직렬화 구문 차이점의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.