blog conviso

Desserialização Insegura em PHP: uma introdução

June 21, 2021

By

Antony

Leite

Desserialização-Insegura-em-PHP

Desde o início do ano em minha jornada no time de Penetration Testing as a Service (PTaaS) da Conviso, venho acompanhando as operações referentes às realizações de pentests. Com isso, escolhi alguns temas para realizar uma pesquisa e me aprofundar melhor. Hoje trago uma introdução ao tema de Desserialização Insegura em PHP.

Processo de Serialização

O processo de serialização tem como objetivo transformar o objeto em um formato que possa ser armazenado e transferido mais facilmente e que seja restaurado quando necessário, sem sofrer qualquer alteração em seus atributos e valores. A serialização simplifica e facilita alguns processos como:

  • Armazenamento de dados em arquivos ou em bancos de dados.
  • Envios de dados por uma rede ou em uma chamada de API.

Segue um diagrama que demonstra como acontece a serialização e a desserialização - que é o processo inverso da serialização.

Serialização em PHP

O Hypertext Preprocessor - conhecido conhecido como PHP - tem por padrão suporte aos processos de serialização e desserialização. Quando julgar necessário a utilização do processo de serialização, utilize serialize(), e unserialize()para realizar uma desserialização. Segue um exemplo de serialização do objeto ConvisoPeople .

<?php
Class ConvisoPeople
{
public $username = 'Antony';
public $team = 'PTaaS';
public $age = 17;
public $office = 'Estagiário';
public $accountAdmin = False;
public function validateAdmin(){
if ($this->accountAdmin){
echo ' [+] ' . $this->username . ' tem uma conta administrativa\n';
} else {
echo ' [+] ' . $this->username . ' NÃO tem uma conta administrativa\n';
}
}
}
$convisoPeople = new ConvisoPeople();
echo serialize($convisoPeople);
?>

Executando este código você terá uma String - uma cadeia de caracteres - que representa o objeto ConvisoPeople:

O:13:"ConvisoPeople":5:{s:8:"username";s:6:"Antony";s:4:"team";s:5:"PTaaS";s:3:"age";i:17;s:6:"office";s:11:"Estagiário";s:12:"accountAdmin";b:0;}

Confira também: Um caso de estudo sobre a CVE-2021-22204 – Exiftool RCE

Entendendo objeto serializado

Vamos dividir o output do código acima. A estrutura do objeto serializado em PHP é “TIPO_DO_DADO, DADO”.

  • O -> Representa um objeto

O:13:"ConvisoPeople":5:
O: QUANTIDADE_DE_CARACTERES: “NOME_DA_CLASSE”: NÚMERO_DE_PROPRIEDADES:

  • s -> Representa uma string

s:8:"username";
s: QUANTIDADE_DE_CARACTERES: NOME_STRING;

  • b -> Representa um booleano

b:0;
b: VALOR_BOOLEANO;

A estrutura do objeto serializado contém 5 propriedades. A Primeira dela é “username” com o valor “Antony”, a segunda “team” com o valor “PTaaS”, a terceira “age” com o valor 17, a quarta “office” com o valor "Estagiário" e a última “accountAdmin” com o valor 0.

Desserialização

Para realizar a desserialização basta utilizar unserialize() em um objeto serializado. O objetivo dessa função é realizar a restauração do objeto que foi serializado com todas as suas propriedades.

<?php
Class ConvisoPeople
{
public $username = 'Antony';
public $team = 'PTaaS';
public $age = 17;
public $office = 'Estagiário';
public $accountAdmin = False;
public function validateAdmin(){
if ($this->accountAdmin){
echo ' [+] ' . $this->username . ' tem uma conta administrativa';
} else {
echo ' [+] ' . $this->username . ' NÃO tem uma conta administrativa';
}
}
}

$admin = new ConvisoPeople();
$admin_serialize = serialize($admin);

$admin_unserialize = unserialize($admin_serialize);
echo $admin_unserialize->validateAdmin();

?>

Métodos mágicos PHP

Métodos mágicos são algumas funções especiais que são precedidas por __. Elas sobrescrevem alguns comportamentos padrões do PHP quando realizadas em um objeto. Saiba mais sobre esses métodos em:

Alguns métodos interessantes para nós nesse momento são o __sleep() e o __wakeup().

A função __sleep() é chamada de forma implícita quando realizamos a serialização utilizando a função serialize(), esse método deve retornar um array com o nome das propriedades do objeto que serão serializados.

A função __wakeup() é usada para restabelecer uma possível comunicação com o banco de dados que pode ter sido perdida devido ao processo de serialização e realizar demais tarefas de reinicialização.

Explorando a desserialização em PHP

Um cenário potencialmente perigoso é quando o usuário possui controle sobre o objeto serializado. Isso permite que um invasor utilize o código da aplicação existente de maneira prejudicial, resultando em várias vulnerabilidades, como execução de código, elevação de privilégios, acesso arbitrário a arquivos, manipulação de variáveis e ataques de negação de serviço.

Um exemplo de exploração através da manipulação de variáveis, onde o objetivo é adquirir o privilégio de administrador é o laboratório da PortSwigger Modifying Serialized Objects. Neste laboratório quando você efetuar o login com as credenciais que são disponibilizadas no enunciado do laboratório, você receberá um cookie de nome session encodado em base64.

Quando você realizar o decode desse base64 (podemos utilizar o CyberChef para realizar esse decode) teremos a seguinte string:

O:4:"User":2:{s:8:"username";s:6:"wiener";s:5:"admin";b:0;}

Podemos perceber que trata-se de um objeto serializado. Um campo interessante para ser manipulado é o admin, que é um campo com o valor booleano.

No primeiro momento, vamos realizar a alteração deste campo para valor 1

  • O:4:"User":2:{s:8:"username";s:6:"wiener";s:5:"admin";b:1;}

Em seguida, vamos pegar a nossa string modificada e encodar em base64

  • Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjY6IndpZW5lciI7czo1OiJhZG1pbiI7YjoxO30=

Depois que você estiver com a modificação do objeto serializado em base64, basta retirar o antigo valor do cookie session e colocar o que você alterou e atualizar a página.

E pronto! A aplicação aceitou e você já está com os privilégios de um usuário administrador, podemos conferir esses privilégios com a opção de Admin panel que apareceu no canto superior direito.

Referências

A8 - Insecure Deserialization

Intro to PHP Deserialization/Object Injection

Insecure deserialization

Serialização: como funciona o processo no PHP

O que é serialização/serialization?

O que é serialização de objeto?

Exploiting PHP deserializatio

Diving into unserialize(): Magic Methods

Construtores e Destrutores

Métodos Mágicos PHP

PHP Object Injection

Mergulhando em unserialize ()

PHP: serializando e desserializando de maneira simples

[hubspot type=cta portal=5613826 id=b5248429-e4f0-4871-bb67-be08b6fd238e]

Sobre o autor

Antony
Leite

Bachelor's degree in Computer Science from the Federal University of Alagoas. He has spoken at events such as the NullByte Security Conference and Hackers to Hackers Conference, and presented research projects at national and international events. He has experience in application security, exploit development, and vulnerability research in both userland and kernel land, having discovered vulnerabilities for companies like Microsoft, AMD, and Intel. His interests include operating system internals, compilers, malware development, vulnerability research, and EDR evasion.

Saiba mais