
MikroTik remote jailbreak for v6.x.x
| / __ _ |/ | | | | | | | | | || | | ( | | ___ | | | || | | || | _ | / _ / _` | | | | || || | ) | || __/ (| | || _/|/ __|_,|
FOISted é um exploit para duas vulnerabilidades pós-autenticação no RouterOS da MikroTik. Ele pode ser usado para fazer jailbreak remotamente no RouterOS das versões 6.34 (2016) a 6.49.6 (última versão v6 lançada).
Este repositório inclui um script de exploit para dispositivos que executam x86. A vulnerabilidade também existe em outras versões de dispositivos; escrever a ropchain fica como exercício para o leitor :)
Para mais informações, confira nossa postagem no blog sobre os internals do RouterOS: https://margin.re/blog/pulling-mikrotik-into-the-limelight.aspx
Automágico:
$ python3 exploit.py -H <router_ip> -u <username> -p <password>
Em seguida:
$ nc <router_ip> 1337
O script de exploit detectará a versão do RouterOS e implantará a ropchain correta automaticamente. Observação: atualmente, apenas RouterOS x86 é suportado.
Se a sua versão não for identificada por algum motivo, você pode passá-la explicitamente com:
-v <version> # e.g. 6.49.6
Se você estiver executando isto em versões do RouterOS mais novas que a 6.49.6 (a mais recente na época do lançamento público), a sua versão do RouterOS pode não estar no banco de gadgets (./db). Em vez disso, você pode passar o caminho para /nova/bin/www e o script de exploit tentará automaticamente encontrar os gadgets corretos para a ropchain:
-f /path/to/nova/bin/www
O FOISted explora duas vulnerabilidades no RouterOS v6 para permitir execução remota de código. Nesta seção, revisamos alguns conhecimentos básicos sobre o IPC do RouterOS e discutimos as duas vulnerabilidades.
Observação: esta seção é, em sua maior parte, uma versão resumida da nossa postagem completa no blog. Com certeza confira para mais detalhes!
Dentro do RouterOS da MikroTik, os programas se comunicam entre si usando um protocolo IPC personalizado.
Os pacotes de dados reais são Nova Messages (nv::message internamente). Elas existem em um formato pseudo-JSON (antes da 6.38) e em um formato binário serializado:

Cada processo tem um endereço fixo dentro do sistema RouterOS; por exemplo, /nova/bin/user está no endereço 13 e /nova/bin/www está no endereço 70. Além disso, cada programa pode registrar handlers que implementam alguma funcionalidade específica em um sub-namespace. Por exemplo, /nova/bin/user tem um handler no endereço 4 que atua como o endpoint de "login" e realiza autenticação para outros serviços:

A comunicação IPC é uma parte crucial da operação do RouterOS. Ela é usada para:
Durante nossos esforços de engenharia reversa, escrevemos uma ferramenta interna de rastreamento de mensagens que nos permite visualizar todas as mensagens trocadas durante a operação do roteador.
Na demonstração a seguir, você pode ver todas as mensagens trocadas enquanto navegamos pelas páginas da interface web: https://youtu.be/Em1hVWnbzQ4
A interface web do RouterOS é implementada pelo binário /nova/bin/www. No entanto, páginas específicas podem ser tratadas por bibliotecas "Servlet" separadas, que implementam funcionalidades em bibliotecas compartilhadas separadas.
Por exemplo, o servlet jsproxy.p trata requisições para /jsproxy e o servlet winbox.p trata requisições para /winbox, etc...
Esses servlets são bibliotecas que são carregadas no /nova/bin/www na primeira vez em que são necessárias. Por exemplo, na primeira vez em que carregamos /jsproxy, a biblioteca jsproxy.p será carregada no espaço de memória.
Durante esse processo de carregamento de biblioteca, notamos um tráfego interessante no rastreador de mensagens:

Especificamente, encontramos uma mensagem que estava sendo enviada do binário www para o handler #2 do www. Isso já é suspeito porque o IPC do RouterOS é destinado à comunicação inter-processos, não à comunicação dentro do mesmo processo...
Além disso, notamos que dois dos argumentos pareciam ser ponteiros virtuais (x86 de 32 bits), o que despertou nosso interesse porque era muito incomum.
Ao inspecionar as funções reais dentro do handler #2 do /nova/bin/www, encontramos uma função chamada FoisHandler::cmdUnknown que é executada quando esses tipos de mensagens são recebidos.
Surpreendentemente, essa função extrai o parâmetro 0x11 da mensagem e o invoca como uma função usando dois dos outros parâmetros como argumentos!
Então, claramente, se conseguirmos enviar uma mensagem controlada que atinja esse handler, podemos invocar qualquer função que quisermos. E a partir daí, é bem fácil pivotar para uma ropchain e fazer algo mais sofisticado.
Existem várias maneiras de enviar mensagens IPC internas como usuário do RouterOS. Na verdade, todos os clientes externos permitem que você envie mensagens arbitrárias após se autenticar:
8291) -- usado pelo cliente winbox.exeEssas interfaces variam na forma como realizam o handshake inicial de autenticação, mas, uma vez autenticadas, permitem que um usuário faça proxy de Nova Messages arbitrárias para o sistema interno. Veja nossa postagem no blog e repositório para engenharia reversa dos protocolos criptográficos do Winbox e do MAC Telnet!
Nesta implementação do exploit, usamos o endpoint WebFig como nosso principal mecanismo de comunicação. Veja webfig.py para a nossa implementação de cliente com engenharia reversa.
No entanto, há um problema quando tentamos invocar nosso endpoint vulnerável FoisHandler:
Todo handler no RouterOS pode definir uma máscara de bits de política que especifica quais usuários têm permissão para invocá-lo. Acontece que FoisHandler tem uma política de 0x80000000, que indica acesso apenas interno (ou seja, mensagens originadas de outros processos do sistema).
Como usuário admin, a máscara de bits de permissão máxima que podemos definir com a GUI é apenas 0x7fffe, o que não é suficiente.
Isso nos leva ao nosso segundo bug: uma escalação de privilégios de admin para "super-admin".
Embora a GUI só nos permita definir uma máscara de bits de permissão de 0x7fffe, internamente ela está, na verdade, apenas enviando uma mensagem IPC com um dos campos contendo o valor da máscara de bits:

Então podemos simplesmente forjar nossa própria mensagem com o valor da máscara de bits de permissão definido como 0xffffffff!
Assim que fazemos isso, temos acesso irrestrito para atingir qualquer endpoint do sistema!
Nosso exploit começa enviando dois arquivos para o sistema via FTP:
stage2: contendo um spawner de reverse shell escutando na porta 1337busybox: fornecendo um ambiente de shell adequadoNosso exploit então realiza a escalação de privilégios para nos permitir atingir o endpoint FoisHandler.
Por fim, enviamos uma mensagem forjada para pivotar para uma ropchain embutida na mensagem. A ropchain calcula o endereço de chmod e execve na uClibc e executa:
chmod 0777 stage2execve stage2Assim que stage2 estiver em execução, você pode se conectar à porta 1337 e obter um shell!
Não, ambas as vulnerabilidades exigem credenciais de administrador para serem exploradas.
As vulnerabilidades existem desde pelo menos a 6.27 (o software mais antigo que conseguimos baixar) até a v6 mais recente: 6.49.6. A interface web foi refatorada no RouterOS v7 e o handler vulnerável foi removido por completo. Nosso POC é escrito para x86.
O script de exploit funciona (testado!) contra todas as versões do RouterOS de 6.34 a 6.49.6.