Como Derrubei o Core de uma Rede Móvel 4G com um Único Pacote: Anatomia de uma Vulnerabilidade Zero-Click no Open5GS

Como Derrubei o Core de uma Rede Móvel 4G com um Único Pacote: Anatomia de uma Vulnerabilidade Zero-Click no Open5GS

Um pesquisador detalha uma vulnerabilidade crítica no Open5GS, um core de rede móvel open-source, que permite a queda do sistema com um pacote malformado. A análise explora a codificação ASN.1 APER e o impacto em redes privadas e futuras soluções nacionais.

MundiX News·09 de junho de 2026·7 min de leitura·👁 7 views

O mundo da segurança em telecomunicações pode parecer um clube fechado para muitos profissionais de TI, protegido por fornecedores proprietários, equipamentos caros e milhares de páginas de especificações 3GPP. No entanto, às vezes, para derrubar o core de uma rede móvel de uma região inteira, não é necessária física quântica, mas sim um entendimento básico de protocolos binários e um único byte removido de forma estratégica.

Neste artigo, detalharei como investiguei vulnerabilidades no popular core de rede móvel open-source Open5GS e por que a fé cega nos padrões pode levar a falhas no código. Desenvolveremos um exploit elegante, manipulando bits na codificação ASN.1 APER. Há um tempo, a comunidade de segurança da informação foi agitada pela pesquisa RANsacked, na qual pesquisadores da Universidade da Flórida e da Universidade Estadual da Carolina do Norte realizaram fuzzing em cores de rede móvel populares e identificaram 119 vulnerabilidades. Naquela época, eu ainda não havia mergulhado tão profundamente no assunto, mas é sempre melhor tarde do que nunca, não é mesmo? Fui particularmente interessado por um vetor na parte 4G do core – o componente MME (Mobility Management Entity). A vulnerabilidade CVE-2023-37017 (VULN-F16) é notável porque não precisamos emular um assinante ou um cartão SIM. O core será atacado em nome da estação base e cairá com o primeiro pacote de boas-vindas.

Anatomia do Erro Vamos analisar por que isso é possível. Nas redes LTE, as estações base se comunicam com o core através do protocolo S1AP. Quando uma estação base é ligada, ela envia um pacote S1SetupRequest. Pelos rigorosos padrões 3GPP, este pacote deve conter obrigatoriamente um elemento informativo com um identificador único da estação base – o Global-ENB-ID. Vamos ver como os desenvolvedores do Open5GS (versões <= 2.6.4) tratam este pacote no código-fonte:

c
void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message)
{
    // ...

    ogs_debug("S1SetupRequest");

    for (i = 0; i < S1SetupRequest->protocolIEs.list.count; i++) {
        ie = S1SetupRequest->protocolIEs.list.array[i];
        switch (ie->id) {
        case S1AP_ProtocolIE_ID_id_Global_ENB_ID:
            Global_ENB_ID = &ie->value.choice.Global_ENB_ID;
            break;
        case S1AP_ProtocolIE_ID_id_SupportedTAs:
            SupportedTAs = &ie->value.choice.SupportedTAs;
            break;
        case S1AP_ProtocolIE_ID_id_DefaultPagingDRX:
            PagingDRX = &ie->value.choice.PagingDRX;
            break;
        default:
            break;
        }
    }

    // Erro fatal aqui:
    ogs_assert(Global_ENB_ID);

    // ...
            }

Os programadores fizeram uma suposição incorreta: "Já que o padrão exige este elemento e o parser aceitou o pacote, então este elemento certamente está lá." No entanto, se um invasor enviar um pacote do qual este bloco foi intencionalmente removido, a variável Global_ENB_ID permanecerá NULL. O loop será encerrado, ogs_assert(NULL) será chamado, e o processo MME será encerrado abruptamente. O core está morto.

Ambiente de Teste Para o ambiente de teste, utilizei um Ubuntu 22.04 LTS limpo e comecei a compilar a versão vulnerável do Open5GS v2.6.4 a partir do código-fonte. A primeira surpresa não foi na compilação ou execução, mas na etapa de instalação do banco de dados. O core Open5GS armazena perfis de assinantes no MongoDB, mas a partir da versão Ubuntu 20.04, o pacote mongodb-server foi removido dos repositórios oficiais devido a uma mudança de licença, o que me forçou a configurar chaves GPG manualmente e baixar o mongodb-org diretamente do fornecedor. Sem isso, os componentes simplesmente se recusavam a funcionar. A arquitetura do core 4G exige que o banco de dados de assinantes – HSS (Home Subscriber Server) – esteja ativo antes de iniciar o MME, com o qual o MME se comunica via protocolo Diameter. Portanto, primeiro compilei o Open5GS e, em seguida, em duas janelas de terminal, executei sequencialmente: ./install/bin/open5gs-hssd e ./install/bin/open5gs-mmed. Após a inicialização bem-sucedida e a conexão com o banco de dados, obtive um servidor MME local funcional, escutando na porta 36412 via protocolo SCTP, aguardando as estações base.

Com um Bisturi em APER Como compilar um exploit e por que não se pode simplesmente baixar um arquivo pcap com tráfego, remover um pedaço em um editor hexadecimal e executá-lo via tcpreplay? Primeiro, SCTP é um protocolo stateful. Ele gera tags de verificação únicas para cada sessão. Um arquivo pcap antigo não será reproduzido, então precisamos de um script ativo que abra um socket. Segundo, a codificação. S1AP usa ASN1.APER – Aligned Packet Encoding Rules. Este é um formato binário extremamente rigoroso. O que isso significa? Se simplesmente cortarmos um pedaço de bytes, o parser asn1c no core notará uma incompatibilidade de comprimento e descartará o pacote com um erro de decodificação antes que ele atinja a lógica de negócios vulnerável. Portanto, utilizei os próprios testes integrados do Open5GS para gerar tráfego de conexão de estação base e assinante válido e legítimo. Capturando-o no Wireshark, extraí o pacote de referência S1SetupRequest. A string hexadecimal original se parece com isto: 0011001f000003003b00080099f9070054f640... Analisando o cabeçalho 00 11 00 1f. No protocolo S1AP, tudo começa com a estrutura raiz S1AP-PDU. 00 – Choice Index. Indica que é uma initiatingMessage – uma requisição. 11 – Procedure Code. Código da procedimento 17, que corresponde a id-S1Setup. 00 – Flag de criticidade 0 – reject. 1f – Comprimento da estrutura aninhada S1SetupRequest, que vem a seguir. 31 bytes. Em seguida, vem a própria estrutura S1SetupRequest. Ela começa com os bytes 00 00 03: 00 – Este é o bit de extensão + preenchimento para alinhar o comprimento. APER exige que o primeiro bit indique se há extensões não padrão no pacote. 0 significa que não há. Os 7 bits restantes são preenchidos com zeros para alinhamento na fronteira do byte. 00 03 – Este é o comprimento do contêiner de elementos, indicando que haverá 3 elementos dentro. Como, de acordo com o padrão, o pacote pode conter até 65535 elementos, APER aloca exatamente 2 bytes para este contador. Em seguida, procuramos o elemento obrigatório Global-ENB-ID, cujo ID de acordo com a especificação é 59, e em hexadecimal 3b. Aqui está ele: 00 3b 00 08 00 99 f9 07 00 54 f6 40 – exatamente 12 bytes. Agora pegamos o bisturi e removemos esses 12 bytes. Mas agora precisamos recalcular o comprimento para que o parser aceite o pacote: 31 bytes – 12 bytes = 19 bytes, que em hexadecimal é 13. Substituímos 1f por 13. Recalculamos o número de elementos: eram 3, e agora são 2. Substituímos 00 00 03 por 00 00 02. O resultado é o payload assassino: 00110013000002004000070000004099f9070089400120.

Escrevendo o PoC em Python Para a entrega, usaremos a biblioteca pysctp. Ela realizará o handshake correto com o MME, após o qual enviaremos o pacote resultante. A execução de um script – e o processo open5gs-mmed cai. O resultado da execução do script PoC: o core MME recebe o pacote modificado, não encontra o elemento obrigatório e encerra abruptamente o trabalho. E se como...

Antevejo seu ceticismo: "E se eu enviar tal pacote para um MME comercial das operadoras móveis da 'Big Four'?" Na verdade, não será possível derrubar uma rede federal com este script. Os cores comerciais passam por anos de testes e fuzzing. Lá, a verificação de ponteiros NULL é básica. Mas isso significa que a vulnerabilidade não representa uma ameaça? De forma alguma. Enquanto as grandes operadoras utilizam soluções comerciais protegidas, o mercado de Private LTE também não para de evoluir. Na minha opinião pessoal, o uso de forks do Open5GS para criar soluções prontas para pequenas empresas é uma prática existente. E com a possível obtenção de certificados FSTEC, tal software se torna extremamente inflexível em termos de atualizações, o que torna as vulnerabilidades 1-day encontradas uma arma ideal para ataques a redes tecnológicas industriais. Outro ponto: devido à saída de fornecedores ocidentais, núcleos de comunicação móvel nacionais estão sendo ativamente desenvolvidos. E como o código está sendo escrito praticamente do zero, os desenvolvedores inevitavelmente tropeçarão nas mesmas armadilhas com o parsing ASN.1 e as suposições de padrões. Mas como alcançar a porta?

Como um invasor enviaria este pacote, se a interface S1-MME está escondida profundamente na rede de transporte da operadora? O vetor mais realista é a invasão de femtocells. As operadoras frequentemente instalam mini-torres em escritórios. Tal torre constrói um túnel IPsec seguro até o gateway da operadora. Se obtivermos privilégios de root em tal femtocell e extrairmos os certificados, poderemos estabelecer um túnel VPN direto do laptop e obter roteamento direto para a porta SCTP 36412 do servidor MME.

📤 Compartilhar & Baixar