
Writeup de laboratório passo a passo demonstrando o bypass de autenticação do InfluxDB CVE-2019-20933 por meio de tokens JWT forjados, incluindo exploração, pós-exploração e orientações de remediação.
Começando pelo que está em execução no ambiente. Listo todos os contêineres ativos:
docker ps

A vítima expõe uma única porta: 8086.
Atualmente, não tenho informações detalhadas sobre o alvo. A partir da saída do docker ps, o sistema expõe externamente apenas um serviço notável na porta 8086, que é mapeado para o serviço dentro do contêiner. Esta é a principal superfície de ataque a ser analisada.
Em vez de acessá-lo imediatamente pelo navegador, prosseguimos com a identificação do serviço usando o Nmap para determinar qual serviço está sendo executado na porta 8086:
nmap -sV -sC -p 8086 192.168.3.137

Os resultados da varredura mostram que a porta 8086 é o serviço HTTP do InfluxDB OSS 1.6.6. Este é um banco de dados de séries temporais exposto por meio de uma API HTTP, não um aplicativo web típico.
InfluxDB é um banco de dados de séries temporais (TSDB) de código aberto escrito em Go. Diferente de RDBMS (otimizado para transações precisas) ou Elasticsearch (otimizado para busca de texto), o InfluxDB foi criado com um único propósito: Lidar com grandes volumes de escrita (alta taxa de gravação) e consultar dados ao longo do eixo do tempo com baixa latência.

Como o serviço foi identificado como InfluxDB, o próximo passo é consultar como o InfluxDB se comunica com os clientes. De acordo com a documentação da API HTTP do InfluxDB v1, a porta 8086 é a porta padrão da API HTTP. Os endpoints importantes incluem:
/ping: verifica o status operacional do servidor./query: envia consultas InfluxQL para ler metadados ou dados./write: grava dados de séries temporais no banco de dados.⇒ Raciocínio: Após o Nmap identificar o serviço como InfluxDB http admin 1.6.6, não continuamos testando-o como um site padrão. Para aplicativos web, normalmente procuramos rotas, formulários de login ou diretórios. No entanto, com InfluxDB, a superfície de ataque está dentro da API HTTP. Portanto, precisamos mudar para testar os endpoints padrão da API do InfluxDB para determinar se a API exige autenticação. Consequentemente, a próxima direção de teste não é acessar / pelo navegador, mas enviar requisições diretamente aos endpoints da API do InfluxDB.
/pingApós identificar a porta 8086 como a API HTTP do InfluxDB, verifique o endpoint /ping para confirmar que o serviço está operacional:
curl -i <http://192.168.3.137:8086/ping>

Resposta 204 No Content confirma que InfluxDB está operando normalmente. Os cabeçalhos confirmam ainda a versão do serviço como InfluxDB OSS 1.6.6
/querycurl -i -s "http://192.168.3.137:8086/query?q=SHOW+DATABASES"

O endpoint /query não permite consultas diretas sem credenciais de autenticação. Isso confirma que o InfluxDB tem a autenticação habilitada e bloqueia todas as consultas anônimas enviadas ao sistema.
Passo a pensar: o InfluxDB versão 1.6.6 possui alguma vulnerabilidade que permita contornar o mecanismo de autenticação?

Consultando bancos de dados públicos de vulnerabilidades, as versões do InfluxDB anteriores a 1.7.6 são afetadas pela CVE-2019-20933. Esta é uma vulnerabilidade de bypass de autenticação na função de autenticação do InfluxDB, relacionada ao tratamento de tokens JWT com um segredo compartilhado vazio.
Como o alvo está executando InfluxDB 1.6.6, que é inferior à versão corrigida 1.7.6, o serviço está dentro da faixa de versões afetadas.
Pode-se concluir:
Service: InfluxDB OSS
Version: 1.6.6
Authentication: Enabled
CVE mapping: CVE-2019-20933
Impact: Authentication Bypass
Status: Version vulnerable
⇒ Raciocínio: Inicialmente, o endpoint /query retorna 401 Unauthorized, indicando que o mecanismo de autenticação está ativo. No entanto, ter a autenticação habilitada não significa segurança absoluta. Quando a versão é identificada como 1.6.6, precisamos correlacioná-la com CVEs conhecidas. Os resultados indicam que essa versão está dentro da faixa afetada pela CVE-2019-20933, o que significa que é possível contornar o mecanismo de autenticação que protege o endpoint /query. Com base nesses resultados de identificação, a fase de exploração se concentrará em verificar a CVE-2019-20933 gerando um token JWT apropriado para contornar a autenticação e executar consultas no endpoint /query.
A vulnerabilidade CVE-2019-20933 ocorre na função authenticate dentro do arquivo services/httpd/handler.go do InfluxDB anterior à versão 1.7.6.
InfluxDB suporta autenticação usando JSON Web Tokens (JWT) para requisições à API HTTP. Ao receber uma requisição com o cabeçalho:
Authorization: Bearer <token>
InfluxDB executará os seguintes passos:
shared-secret do arquivo influxdb.conf para atuar como chave secreta na verificação da assinatura do token.username das claims para determinar o usuário que está executando a consulta.Nas versões afetadas, se a autenticação JWT estiver habilitada, mas o parâmetro shared-secret não estiver configurado, o valor do segredo pode ser processado como uma string vazia ("").
O sistema não valida adequadamente a força do segredo antes de verificar a assinatura do JWT. Isso permite que um atacante construa um JWT personalizado, assine-o com um segredo vazio e, em seguida, defina a claim username para uma conta válida no sistema, como admin, se essa conta existir no laboratório.
Quando esse token é enviado por meio do cabeçalho Authorization: Bearer <token>, o InfluxDB usa o mesmo segredo vazio para verificar a assinatura. Se a assinatura corresponder e o nome de usuário existir, a requisição será autorizada sem exigir a senha real do usuário.
O fluxo de processamento pode ser resumido da seguinte forma:
| Etapa | Processamento Normal | Falha na CVE-2019-20933 |
|---|---|---|
| 1 | O cliente envia Authorization: Bearer <token> | O atacante cria um JWT ele mesmo |
| 2 | O servidor lê shared-secret da configuração | shared-secret não está definido |
| 3 | O servidor usa o segredo para verificar a assinatura do JWT | O segredo é processado como uma string vazia "" |
| 4 | Se o token for válido, recupera username da claim | O atacante define username=admin se o usuário existir |
| 5 | O servidor concede permissões com base no usuário da claim | A requisição é aceita sem exigir senha |
Fluxo de exploração no nível lógico: