Introdução à vulnerabilidade de desserialização php

índice

O que é serialização php?

serialize () instance

Instância de desserialização de matriz

Exemplos de objetos desserializados 

instância unserialize () 

Instância de serialização de array

Instância de serialização de objeto

Análise de formato de string serializado 

Tipo de variável

A diferença entre público, privado e protegido após a serialização

Método mágico

Métodos de magia comuns

Exemplo de chamada de método

__dormir()

__acorde()

__para sequenciar()

Princípio de vulnerabilidade de desserialização

Link de referência


O que é serialização php?

As duas funções usadas

serialize()     //函数用于序列化对象或数组,并返回一个字符串。
unserialize()   //函数用于将通过 serialize() 函数序列化后的对象或数组进行反序列化,并返回原始的对象结构。

 

serialize () instance

Instância de serialização de array

Após serializar um conjunto de matrizes, obtenha uma string de strings


<?php
    highlight_file(__FILE__);
    $a = array('a' => 'Apple' ,'b' => 'banana' , 'c' => 'Coconut');
    $s = serialize($a);
    echo $s;
    //a:3:{s:1:"a";s:5:"Apple";s:1:"b";s:6:"banana";s:1:"c";s:7:"Coconut";} 
?>

 

Instância de serialização de objeto 

Depois de serializar um objeto, obtenha uma string de strings

<?php
    highlight_file(__FILE__);
    class test_class{ //创建类
		var $test = '123'; //在类中新建一个test变量
	}
	
	$class1 = new test_class; //创建对象
	$class_str = serialize($class1);//序列化对象
	echo $class_str;//输出序列化后的字符串
//O:10:"test_class":1:{s:4:"test";s:3:"123";}
?>

instância unserialize () 

Instância de desserialização de matriz

Desserialize uma string serializada em um formato padrão e você obterá a seguinte matriz

<?php
    highlight_file(__FILE__);
    $str = 'a:3:{s:1:"a";s:5:"Apple";s:1:"b";s:6:"banana";s:1:"c";s:7:"Coconut";} ';
	$un_str=unserialize($str);	
	var_dump($un_str);	    
?>

 

Instância de desserialização de objeto

Desserialize uma string serializada em um formato padrão para obter um novo objeto

<?php
    highlight_file(__FILE__);
    $str = 'O:10:"test_class":1:{s:4:"test";s:3:"123";}';
    $un_str=unserialize($str);
    var_dump($un_str);  
?> 

Análise de formato de string serializado 

O: 10: "test_class" : 1 : {s: 4 : "teste" ; s : 3 : "123" ;}

Objecto tipo: comprimento nome de classe : nome de classe: número de variáveis na classe : {variável: variável comprimento nome: nome da variável; tipo variável : comprimento variável conteúdo : conteúdo variável }

 

a: 3 : {s: 1 : "a" ; s : 5 : "Maçã" ; s: 1: "b"; s: 6: "banana"; s: 1: "c"; s: 7: "Coco";}

Tipo de matriz: número de matrizes : {variável: variável comprimento do nome : nome da variável ; tipo de variável : comprimento de conteúdo variável : conteúdo variável ; ...}

 

  • Existem dois tipos de serialização:
    • Tipo de objeto
    • Tipo de matriz
  • Pode-se ver que nas chaves, dois pontos e vírgulas (;) formam um grupo, e os dois pontos e vírgulas representam o conteúdo de uma variável.
    • {s: 4 : "teste" ; s : 3 : "123" ;}

 

Tipo de variável

Diferentes tipos de armazenamento serão convertidos em diferentes letras após a serialização

a - array                  b - boolean  
d - double                 i - integer
o - common object          r - reference
s - string                 C - custom object
O - class                  N - null
R - pointer reference      U - unicode string

A diferença entre público, privado e protegido após a serialização

  • Público (público): pode ser acessado dentro desta classe, classes externas e subclasses
  • Privado (privado): disponível apenas dentro desta classe
  • Protegido (protegido): apenas esta classe ou subclasse ou pai pode acessar

Após serializar de acordo com os 3 modificadores acima, os seguintes resultados são obtidos:

O: 10: "test_class": 3: {

s: 6: "teste_1"; s: 3: "str";

s: 18: "test_classtest_3"; i: 123;

s: 9: "* teste_2"; i: 123;

}

 

  • público: basicamente nenhuma mudança após a serialização
  • privado: Após a serialização, o nome da classe será adicionado ao nome da variável, e o comprimento do nome da variável também aumentará
  • protegido: Após a serialização, haverá um * extra antes do nome da variável, mas por que o comprimento do nome da variável torna-se 9 bytes?
    • Na verdade, quando o atributo protegido é serializado, o formato é% 00 *% 00 nome do membro

 

Método mágico

Ao usar a desserialização do PHP, geralmente é necessário usar o método mágico na desserialização para verificar se há operações confidenciais no método.

O PHP reserva todos os métodos de classe começando com __ (dois sublinhados) como métodos mágicos.

Métodos de magia comuns

__construct()//创建对象时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__invoke() //当脚本尝试将对象调用为函数时触发
__sleep() //此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。
__wakeup() //经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。

documento oficial do método mágico php 

 

 

Exemplo de chamada de método

__dormir()

A função serialize () verifica se há um método mágico __sleep () na classe. Se existir, o método será chamado primeiro, antes que a operação de serialização seja executada. Esta função pode ser usada para limpar o objeto e retornar um array contendo os nomes de todas as variáveis ​​no objeto que devem ser serializadas. Se o método não retornar nada, NULL será serializado e um erro de nível E_NOTICE será gerado.

__acorde()

unserialize () irá verificar se existe um método __wakeup (). Se existir, o método __wakeup será chamado primeiro para preparar os recursos necessários para o objeto com antecedência.

__para sequenciar()

O método __toString () é usado para responder quando uma classe é tratada como uma string. Por exemplo echo $ obj; o que deve ser exibido. Este método deve retornar uma string, caso contrário, um erro fatal do nível E_RECOVERABLE_ERROR será emitido.

Princípio de vulnerabilidade de desserialização

Quando os parâmetros de desserialização unserialize () são controláveis, podemos construir uma string serializada para modificar as variáveis ​​internas e até funções do objeto.

Caso:

<?php
error_reporting(0);
show_source(__FILE__);
class c{
	public $str = 111;
	
	function __wakeup(){
		echo $this->str;
		
	}
}

$str = $_GET['str'];
if (isset($str)){
	unserialize($str);
	}
?>

Quando podemos controlar a desserialização, seremos capazes de modificar o conteúdo das variáveis ​​na classe

poc

?str=O:1:"c":1:{s:3:"str";s:3:"123";}

Claro que não é tão simples, apenas modifique o conteúdo do valor, também podemos digitar xss

poc

?str=O:1:"c":1:{s:3:"str";s:24:"<script>alert()</script>";}

Claro, este é apenas um caso simples, explicarei o conhecimento avançado de desserialização de php na próxima vez.

 

Link de referência

https://chybeta.github.io/2017/06/17/%E6%B5%85%E8%B0%88php%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C % 96% E6% BC% 8F% E6% B4% 9E /

https://xz.aliyun.com/t/3674

https://xz.aliyun.com/t/6753

https://xz.aliyun.com/t/7366

Acho que você gosta

Origin blog.csdn.net/weixin_41924764/article/details/113093719
Recomendado
Clasificación