1. Fundação PHP orientada a objetos
Para falar sobre a desserialização do PHP, você precisa envolver orientação a objetos, porque a maioria das explorações de desserialização envolve a desserialização de "objetos". Portanto, você precisa entender os fundamentos da orientação a objetos.
Orientação a objetos é uma espécie de idéia de programação centrada em "objetos", que decompõe o problema a ser resolvido em vários "objetos".O objeto é um todo composto de informações e a descrição do processamento da informação.
1. Conceitos básicos
-
Objetos
Objetos são representações abstratas de coisas. Na terminologia orientada a objetos, tudo é um objeto, e um objeto representa uma operação funcional específica.Não precisamos saber como esse objeto implementa uma determinada operação, precisamos apenas saber quais operações o objeto pode concluir. -
Abstract
Abstraction (Abstract
) é ignorar as características não essenciais em coisas que não têm nada a ver com o objetivo atual e prestar mais atenção às características essenciais relacionadas ao objetivo atual, de modo a descobrir a semelhança das coisas e classificar as coisas com semelhança em uma categoria para obter um conceito abstrato de. -
Encapsulamento Encapsulamento
(Encapsulation
) refere-se à combinação das propriedades e comportamento de um objeto em uma unidade independente e ocultar os detalhes internos do objeto tanto quanto possível.De um modo geral, o encapsulamento tem dois significados:
- Combine todas as propriedades e comportamentos do objeto para formar uma unidade independente indivisível. Os valores de propriedade do objeto (exceto os valores de propriedade pública) só podem ser lidos e modificados pelo comportamento deste objeto;
- Oculte os detalhes internos do objeto o máximo possível, formando uma barreira para o mundo exterior, e a conexão com o exterior só pode ser realizada por meio da interface externa
-
Herança Herança
(Inheritance
) é um modelo hierárquico que conecta classes a classes. Herança significa que os objetos de uma classe particular possuem os atributos e comportamentos de sua classe geral. Herança significa "posse automática", ou seja, a classe especial não precisa redefinir as propriedades e comportamentos que foram definidos na classe geral, mas automaticamente e implicitamente possui as propriedades e comportamentos de sua classe geral. Quando essa classe especial é herdada por sua classe especial de nível inferior, seus atributos e comportamentos herdados e autodefinidos são herdados pela classe especial de nível seguinte. A herança é, portanto, transitiva, incorporando a relação do particular e do geral na natureza.Classe pai: Uma classe é herdada por outras classes, que podem ser chamadas de classe pai, ou classe base, superclasse Subclasse
: Uma classe que integra outras classes é chamada de subclasse, também conhecida como classe derivada
Os conceitos acima podem ser abstratos e obscuros para iniciantes. Existem muitos conceitos em orientação a objetos, como classe, objeto, herança, polimorfismo, etc. O cultivo de ideias de programação orientada a objetos precisa ser continuamente acumulado no processo de aprendizado. Para aprender o conhecimento da vulnerabilidade de desserialização do PHP, primeiro entenda o conhecimento básico de "classe", "objeto", "instanciação" e outros conhecimentos básicos, e então siga O aprofundamento do conhecimento relevante pode aprofundar a programação orientada a objetos.
2. Classes e Objetos
Uma classe é um recurso abstrato que define uma coisa. Ela encapsula a forma dos dados e as operações nesses dados. O interior de uma classe consiste em variáveis de membro (atributos) e funções de membro (métodos),
- Variável de membro: Uma variável definida dentro da classe. O valor da variável é invisível para o mundo externo, mas pode ser acessado por meio de funções de membro. Depois que a classe é instanciada como um objeto, a variável pode se tornar um atributo do objeto
- Funções de membro: define funções associadas a um determinado objeto dentro de uma classe. As funções de membro também são conhecidas como métodos, que são usados para executar operações específicas e podem acessar e manipular atributos da classe, usando palavras-chave
function
para definir funções de membro.
// 定义类的语法格式
class class_name
{
//类中定义的属性和方法
}
// 定义一个Person类
class Person
{
//类中定义的属性和方法
// 属性
public $name; // 姓名
public $age; // 年龄
// 成员函数
public function tell(){
print($this->name."今年".$this->age."岁!");
}
}
Os objetos são o resultado da instanciação da classe. Depois de definir uma classe em PHP, você pode usar new
a palavra-chave para instanciar um objeto de uma classe. Seu formato de sintaxe é o seguinte:
$object_name = new class_name();
<?php
class Person
{
public $name; // 姓名
public $age; // 年龄
// 成员函数
public function tell(){
print($this->name."今年".$this->age."岁!");
}
}
$p = new Person(); // 创建 Person 类的实例,即对象,名为$p
$p -> name = "张三"; // 给对象的 name 属性赋值
$p -> age = 18; //
echo $p -> tell(); // 张三今年18岁!
?>
3. Introdução aos modificadores comuns de classes
private
private
Indica campos privadosprivate
e métodos modificados por palavras-chave只能在类的内部使用
, que não podem ser chamados pelo objeto instanciado da classe, nem pela subclasse da classe.protected
protegido significa protegido,只能在类本身和子类中使用
.public
public
Um campo ou método modificado por uma palavra-chave indica que é público, ou seja, o campo e o método podem ser acessados através do nome do objeto em qualquer lugar do PHP. Ao mesmo tempo,public
também é o modificador padrão para campos e métodos.
4. Construtor e destruidor
O construtor é executado automaticamente quando o objeto da classe é instanciado, onde os membros podem ser inicializados ou algumas operações especiais podem ser executadas. Correspondente a ele está um destruidor, que é executado automaticamente quando o objeto instanciado é destruído. Geralmente é usado para executar algum trabalho para limpar recursos, como liberar memória, excluir variáveis e fechar conexões de banco de dados, etc.
1), construtor
Em PHP, o nome do construtor é nomeado uniformemente __construct()
. Ou seja, se uma função nomeada for declarada em uma classe __construct()
, a função será tratada como um construtor e executada quando uma instância do objeto for criada. O formato de sintaxe do construtor é o seguinte:
function __construct([参数列表]){
// 构造函数体
}
<?php
class Student{
private $name;
private $age;
function __construct()
{
$this->name = "zhangsan";
$this->age = 18;
}
public function toString(){
echo $this->name."今年".$this->age."岁。";
}
}
$s = new Student(); // 实例化对象的时候,自动去调用构造函数__construct,对属性进行初始化
$s->toString();
?>
2), destruidor
O destruidor também possui uma nomenclatura uniforme, ou seja __destruct()
, . Os destruidores permitem que um código arbitrário seja executado depois que um objeto é usado para limpar a memória. Por padrão, apenas a memória ocupada pelas propriedades do objeto é liberada e os recursos relacionados ao objeto são excluídos. Ao contrário dos construtores, os destruidores não aceitam nenhum parâmetro.
<?php
class Counter{
private static $count = 0;
function __construct()
{
self::$count++;
}
function __destruct()
{
self::$count--;
}
function getCount()
{
return self::$count;
}
}
$num1 = new Counter(); // 实例化对象,触发构造方法,count的值+1,变为1
echo $num1->getCount()."<br>"; // 1
$num2 = new Counter(); // 实例化对象,count的值+1,变为2
echo $num2->getCount()."<br>"; // 2
$num2 = NULL; // 销毁对象$num2,count的值-1,变为1
echo $num1->getCount()."<br>"; // 1
?>
2. Conhecimento básico de serialização
1. O papel da serialização
A serialização é o processo de conversão das informações de estado de um objeto (atributos) em uma string que pode ser armazenada ou transmitida. Converta objetos ou arrays em strings que podem ser armazenadas/transmitidas
Use funções em php
serialize()
para serializar objetos ou arrays e retornar uma string contendo fluxos de bytes para representar
2. Expressão após a serialização
// 所有序列化之后的格式第一位都是数据类型的英文字母的简写
<?php
echo serialize(null); // N;
echo serialize(666); // i:666;
echo serialize(66.6); // d:66.599999999999994315658113919198513031005859375;
echo serialize(true); // b:1;
echo serialize(false); // b:0;
echo serialize("benben"); // s:6(长度):"benben";(如果字符串中有双引号“"”,序列化之后,被双引号闭合,正因为有前面字符串的长度,所以才可以区分哪个是字符串内容中的双引号)
echo serialize(array('benben','dazhuang','laoliu')) // a:3:{i:0;s:6:"benben";i:1;s:8:"dazhuang";i:2;s:6:"laoliu";}
?>
Tipos de dados comuns após a serialização:
a
:array
tipo de matrizb
:boolean
Booleanod
:double
flutuari
:integer
tipo inteiror
:objec reference
referência de objetos
:non-escaped binary string
string binária sem escapeS
:escaped binary string
string binária com escapeC
:custom object
objeto personalizadoO
:class
objetoN
:null
vazioR
:pointer reference
referência do ponteiroU
:unicode string Unicode
string codificada
3. Serialização de objetos
-
"Classe" não pode ser serializado, "objeto" pode ser serializado; apenas variáveis de membro são serializadas, funções de membro não são serializadas
<?php class test{ public $pub='benben'; function jineng(){ echo $this->pub; } } $a = new test(); echo serialize($a); // O:4:"test":1:{s:3:"pub";s:6:"benben";} ?>
Explicação após a serialização do "objeto":
O
:Object
4
: comprimento do nome da classe"test"
: Indica o nome da classe1
: número de atributos de membros
: O tipo da variável nome pub é uma string3
: o comprimento do nome da variável"pub"
:nome variávels
: O tipo do valor da variável é uma string6
: o comprimento do valor da variável"benben"
:variável
-
Depois que
private
a propriedade privada decorada com o modificador for serializada, adicione "%00类名%00
" antes do nome da propriedade privada (aqui%00
está a codificação de URL do caractere nulo (Null
), que na verdade é invisível).<?php class test{ private $pub='benben'; function jineng(){ echo $this->pub; } } $a = new test(); echo serialize($a); // O:4:"test":1:{s:9:"testpub";s:6:"benben";} echo urlencode(serialize($a)); // O%3A4%3A%22test%22%3A1%3A%7Bs%3A9%3A%22%00test%00pub%22%3Bs%3A6%3A%22benben%22%3B%7D ?>
Quando o atributo
$pub
éprivate
modificado por modificadores, depois que o "objeto" é serializado, a diferença do exemplo anterior é: ,s:9:"testpub"
se você usar codificação de URL para saída, verá quetest
haverá antes e depois%00
, portanto, o comprimento do membro nome do atributo é9
-
Após
protected
a serialização, os atributos do membro decorados com modificadores adicionarão "%00*%00
" antes do nome da variável (aqui%00
está a codificação de URL do caractere nulo (Null
), que na verdade é invisível).<?php class test{ protected $pub='benben'; function jineng(){ echo $this->pub; } } $a = new test(); echo serialize($a); // O:4:"test":1:{s:6:"*pub";s:6:"benben";} ?>
-
Quando serializamos um objeto, o valor da variável membro do objeto é outro objeto após a instanciação, após a serialização, o valor da variável é o valor serializado de outro objeto.
<?php class test1{ var $pub='benben'; function jineng(){ echo $this->pub; } } class test2{ var $ben; function __construct(){ $this->ben=new test1(); } } $a = new test2(); echo serialize($a); // O:5:"test2":1:{s:3:"ben";O:5:"test1":1:{s:3:"pub";s:6:"benben";}} ?>
3. Desserialização
1. O papel da desserialização
Restaurar a string serializada para um objeto instanciado
2. As características da desserialização
-
O conteúdo após a desserialização é um objeto
<?php class test { public $a = 'benben'; protected $b = 666; private $c = false; public function displayVar() { echo $this->a; } } $d = serialize(new test()); echo $d; // "对象"序列化:O:4:"test":3:{s:1:"a";s:6:"benben";s:4:"*b";i:666;s:7:"testc";b:0;} var_dump(unserialize($d)); // object(test)#1 (3) { ["a"]=> string(6) "benben" ["b":protected]=> int(666) ["c":"test":private]=> bool(false)} ?>
-
O valor no objeto gerado pela desserialização é fornecido pelo valor na desserialização; não tem nada a ver com o valor predefinido da classe original
<?php class test { public $a = 'benben'; protected $b = 666; private $c = false; public function displayVar() { echo $this->a; } } // 将序列化之后的字符串中变量a的值,改为dazhang,将私有属性c的值改为true $d = 'O:4:"test":3:{s:1:"a";s:8:"dazhuang";s:4:"%00*%00b";i:666;s:7:"%00test%00c";b:1;}'; $d = urldecode($d); // 反序列化之后对象的值与原有类中的值无关,而只与反序列化中的值有关 var_dump(unserialize($d)); // object(test)#1 (3) { ["a"]=> string(8) "dazhuang" ["b":protected]=> int(666) ["c":"test":private]=> bool(true)} ?>
-
A desserialização não aciona os métodos membros da classe (exceto o método mágico); ela precisa chamar o método antes que possa ser acionado (a classe original deve existir)
<?php class test { public $a = 'benben'; protected $b = 666; private $c = false; public function displayVar() { echo $this->a; } } $d = 'O:4:"test":3:{s:1:"a";s:8:"dazhuang";s:4:"%00*%00b";i:666;s:7:"%00test%00c";b:1;}'; $e = urldecode($d); $f = unserialize($e); $f->displayVar(); // 反序列化后,生成对象,调用displayVar(),输出:dazhuang ?>
O resumo de conhecimento acima vem do aprendizado de vulnerabilidade de desserialização php da Orange Technology , combinado com meu próprio entendimento.