Code Fighters

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

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.

Você também pode ouvir a versão em áudio desse blogpost:

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 deserialization

Ataques a websites surgem para exploração ilegal de Cripto-Mineração

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

New call-to-action

About author

Articles

Estudante do técnico em eletrônica no Instituto Federal de Brasília, estagiário na Conviso e apaixonado por segurança da informação.
Related posts
Code FightersSegurança de Aplicação

Como integrar o Semgrep no CI/CD e enviar os resultados para a Conviso Platform

Atualmente, é uma prática muito comum integrar verificações de segurança durante a fase de…
Read more
Code FightersSegurança de Aplicação

Escrevendo código seguro - Um guia de boas práticas

Escrever código seguro envolve a adoção de um conjunto de boas práticas de desenvolvimento de…
Read more
Code FightersSegurança de Aplicação

Como o Subresource Integrity pode ajudar a proteger aplicações na web

O Subresource Integrity (SRI) é uma técnica que pode ajudar a proteger aplicações na web contra…
Read more

Deixe um comentário