Bypass de disable_functions - função dl
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
dl() permite ao PHP carregar uma extensão compartilhada em tempo de execução. Se você conseguir fazê-lo carregar um módulo controlado pelo atacante, você pode registrar uma nova função PHP que internamente chama execve, system, ou qualquer outro primitivo nativo e, portanto, contornar disable_functions.
Este é um primitivo real, mas em alvos modernos é muito menos comum do que escritos antigos sugerem.
Por que esse bypass é incomum hoje
Os principais bloqueios são:
dl()deve existir e não deve estar desabilitadaenable_dlainda deve permitir carregamento dinâmico- A SAPI alvo deve suportar
dl() - O payload deve ser uma extensão PHP válida compilada para o mesmo ABI alvo
- A extensão deve ser acessível a partir do
extension_dirconfigurado
O manual oficial do PHP é a verificação de realidade mais importante aqui: dl() está disponível apenas para as SAPIs CLI e embed, e para a SAPI CGI quando executada a partir da linha de comando. Isso significa que a técnica é geralmente não está disponível em requisições web normais PHP-FPM/mod_php, então verifique a SAPI antes de gastar tempo construindo um payload.
Observe também que enable_dl é uma configuração INI_SYSTEM e, desde PHP 8.3.0, o PHP documenta-a como deprecated, então normalmente você não pode alterá-la em tempo de execução a partir de código PHP controlado pelo atacante.
Se dl() não for viável, volte para a lista mais ampla de module/version dependent bypasses.
Triagem rápida a partir de um foothold
Antes de construir qualquer coisa, colete os parâmetros exatos que o módulo deve corresponder:
<?php
phpinfo();
echo "PHP_VERSION=" . PHP_VERSION . PHP_EOL;
echo "PHP_SAPI=" . php_sapi_name() . PHP_EOL;
echo "ZTS=" . (PHP_ZTS ? "yes" : "no") . PHP_EOL;
echo "INT_BITS=" . (PHP_INT_SIZE * 8) . PHP_EOL;
echo "enable_dl=" . ini_get("enable_dl") . PHP_EOL;
echo "extension_dir=" . ini_get("extension_dir") . PHP_EOL;
echo "disabled=" . ini_get("disable_functions") . PHP_EOL;
?>
O que importa:
PHP_SAPI: se isto forfpm-fcgiouapache2handler,dl()geralmente é um beco sem saída para exploração webextension_dir: o payload deve ser carregado a partir daquiPHP Version, arquitetura, debug/non-debug, e ZTS/non-ZTS: seu módulo deve corresponder a elesdisable_functions: confirme sedlestá ausente porque foi desabilitado ou porque a SAPI não o suporta
Restrições práticas de exploração
1. Normalmente é necessário acesso de escrita em extension_dir
Este é o maior gargalo.
dl() recebe o nome do arquivo da extensão, e o PHP o carrega a partir de extension_dir. Na prática, isso significa que um upload arbitrário normal para /var/www/html/uploads não é suficiente. Você ainda precisa de um caminho para colocar um .so/.dll onde o PHP realmente carregue extensões.
Situações realistas em que isso se torna explorável:
- CTFs ou labs intencionalmente fracos onde
extension_diré gravável - Shared-hosting ou erros em containers que expõem um caminho de extensão gravável
- Um mecanismo separado de escrita arbitrária de arquivos que já alcança
extension_dir - Cenários de post-exploitation onde você já escalou privilégios o suficiente para colocar arquivos lá
2. O módulo deve corresponder ao build alvo
Corresponder apenas a PHP_VERSION não é suficiente. A extensão também precisa corresponder a:
- OS e arquitetura da CPU
- expectativas do libc/toolchain
ZEND_MODULE_API_NO- build com debug vs sem debug
- ZTS vs NTS
Se esses itens não corresponderem, dl() falhará ou causará crash no processo.
3. open_basedir não é a principal defesa aqui
Uma vez que você pode colocar o módulo em extension_dir e chamar dl(), o código da extensão é executado dentro do processo PHP. Nesse ponto, a barreira relevante não era open_basedir, mas a capacidade de colocar um objeto compartilhado válido no caminho de carregamento de extensões.
Construindo a extensão maliciosa
A rota clássica ainda é válida:
- Recrie o build da vítima o mais fielmente possível
- Use
phpize,./configureemakepara compilar uma extensão compartilhada - Exporte uma função PHP como
bypass_exec($cmd)que encapsula a execução nativa de comandos - Envie o módulo compilado para
extension_dir - Carregue-o com
dl()e chame a função exportada
O ataque é antigo, mas ainda relevante porque os changelogs do PHP 8.x continuam a incluir correções de crash específicas para dl(). A primitiva ainda existe; a parte difícil é encontrar uma implantação onde ela seja alcançável e onde você possa colocar um módulo compatível.
Fluxo de trabalho mínimo
Na máquina do atacante
mkdir bypass && cd bypass
phpize
./configure
make
O objeto compartilhado resultante geralmente ficará em modules/.
Se você estiver compilando em um ambiente diferente do alvo, trate o arquivo produzido como um rascunho até verificar que o ABI corresponde ao da vítima.
Carregando e usando a extensão
Se o alvo realmente suporta dl() e o módulo estiver dentro de extension_dir, a parte em tempo de execução é simples:
<?php
if (!extension_loaded('bypass')) {
dl('bypass.so'); // use the correct filename for the target platform
}
echo bypass_exec($_GET['cmd']);
?>
No Windows o nome do arquivo normalmente será um .dll, enquanto em alvos tipo Unix geralmente será um .so.
Notas do atacante
- Não assuma que isso funciona remotamente apenas porque
function_exists("dl")retorna true em alguma documentação ou writeup antigo; valide o SAPI em execução - Uma tentativa de
dl()que falha pode matar o worker PHP se o módulo for incompatível - A partir do PHP 8, funções desabilitadas são removidas da tabela de funções, então a enumeração em userland pode diferir de posts antigos
- Se você não pode escrever em
extension_dir, esta técnica geralmente é menos prática do que FPM/FastCGI,LD_PRELOAD, ou bypasses específicos de módulos já cobertos nesta seção
Referências
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.


