Voltar para o Blog

Vulnerabilidade Critica no MongoDB Expoe Mais de 87 Mil Servidores

Olá HaWkers, uma notícia preocupante acaba de surgir no mundo da segurança: pesquisadores descobriram que mais de 87 mil servidores MongoDB estão expostos na internet com uma vulnerabilidade crítica que permite acesso não autorizado a dados sensíveis.

Se você usa MongoDB em produção, este artigo é essencial. Vamos entender o que aconteceu, como verificar se seu servidor está vulnerável, e principalmente como se proteger.

O Que Aconteceu

Pesquisadores de segurança identificaram uma combinação de configurações inseguras e uma nova CVE que afeta versões específicas do MongoDB. O mais alarmante é que muitos desses servidores estão completamente abertos, sem qualquer autenticação.

Números Alarmantes

Escala do problema:

  • 87.000+ servidores MongoDB expostos publicamente
  • 40% sem qualquer autenticação habilitada
  • 23.000+ contêm dados sensíveis (emails, senhas, PII)
  • Brasil está entre os 10 países mais afetados
  • 12.000+ já foram comprometidos por ransomware

Versões mais afetadas:

  • MongoDB 4.4.x (antes de 4.4.28)
  • MongoDB 5.0.x (antes de 5.0.24)
  • MongoDB 6.0.x (antes de 6.0.13)
  • MongoDB 7.0.x (antes de 7.0.5)

⚠️ Urgente: Se você usa MongoDB em produção, verifique imediatamente sua versão e configurações de segurança.

Verificando Se Seu Servidor Está Vulnerável

O primeiro passo é identificar se sua instalação está em risco. Aqui estão comandos e verificações essenciais:

Verificação Rápida de Exposição

// Conecte ao seu MongoDB e execute:
// Verificar versão
db.version()

// Verificar se autenticação está habilitada
db.adminCommand({ getParameter: 1, authenticationMechanisms: 1 })

// Listar usuários (se vazio, você está em risco!)
db.getUsers()

// Verificar bind IP
db.adminCommand({ getCmdLineOpts: 1 })

Script de Auditoria de Segurança

Crie um script para verificar múltiplas configurações:

// audit-mongodb-security.js
// Execute com: mongosh < audit-mongodb-security.js

print("=== MongoDB Security Audit ===\n");

// 1. Verificar versão
const version = db.version();
print(`MongoDB Version: ${version}`);

// Versões vulneráveis conhecidas
const vulnerableVersions = ["4.4.0", "4.4.27", "5.0.0", "5.0.23", "6.0.0", "6.0.12", "7.0.0", "7.0.4"];
if (vulnerableVersions.some(v => version.startsWith(v.split('.').slice(0, 2).join('.')))) {
    print("⚠️  ALERTA: Versão pode conter vulnerabilidades conhecidas!");
} else {
    print("✅ Versão parece estar atualizada");
}

// 2. Verificar autenticação
try {
    const authMechanisms = db.adminCommand({ getParameter: 1, authenticationMechanisms: 1 });
    print(`\nAuthentication Mechanisms: ${JSON.stringify(authMechanisms.authenticationMechanisms)}`);

    if (authMechanisms.authenticationMechanisms.length === 0) {
        print("⚠️  CRÍTICO: Nenhum mecanismo de autenticação configurado!");
    }
} catch (e) {
    print("ℹ️  Não foi possível verificar mecanismos de autenticação");
}

// 3. Verificar usuários
try {
    const users = db.getUsers();
    print(`\nTotal de usuários configurados: ${users.users.length}`);

    if (users.users.length === 0) {
        print("⚠️  CRÍTICO: Nenhum usuário configurado! Servidor aberto!");
    } else {
        print("✅ Usuários configurados encontrados");
    }
} catch (e) {
    print("ℹ️  Execute como admin para verificar usuários");
}

// 4. Verificar bind address
try {
    const cmdLineOpts = db.adminCommand({ getCmdLineOpts: 1 });
    const bindIp = cmdLineOpts.parsed?.net?.bindIp || "não especificado";
    print(`\nBind IP: ${bindIp}`);

    if (bindIp === "0.0.0.0" || bindIp.includes("0.0.0.0")) {
        print("⚠️  ALERTA: Servidor acessível de qualquer IP!");
    } else if (bindIp === "127.0.0.1" || bindIp === "localhost") {
        print("✅ Servidor acessível apenas localmente");
    }
} catch (e) {
    print("ℹ️  Execute como admin para verificar bind IP");
}

// 5. Verificar SSL/TLS
try {
    const sslInfo = db.adminCommand({ getParameter: 1, sslMode: 1 });
    print(`\nSSL Mode: ${sslInfo.sslMode || 'disabled'}`);

    if (!sslInfo.sslMode || sslInfo.sslMode === "disabled") {
        print("⚠️  ALERTA: SSL/TLS não está habilitado!");
    } else {
        print("✅ SSL/TLS está configurado");
    }
} catch (e) {
    print("ℹ️  Não foi possível verificar SSL/TLS");
}

print("\n=== Fim da Auditoria ===");

Configuração Segura do MongoDB

Se você identificou problemas, aqui está como corrigi-los corretamente:

1. Habilitar Autenticação

Primeiro, crie um usuário administrador:

// Conecte sem autenticação primeiro
// mongosh --host localhost

// Troque para o database admin
use admin

// Criar usuário administrador
db.createUser({
    user: "adminUser",
    pwd: passwordPrompt(), // Solicita senha de forma segura
    roles: [
        { role: "userAdminAnyDatabase", db: "admin" },
        { role: "readWriteAnyDatabase", db: "admin" },
        { role: "dbAdminAnyDatabase", db: "admin" },
        { role: "clusterAdmin", db: "admin" }
    ]
})

// Criar usuário para aplicação (privilégios mínimos)
use myAppDatabase

db.createUser({
    user: "appUser",
    pwd: passwordPrompt(),
    roles: [
        { role: "readWrite", db: "myAppDatabase" }
    ]
})

2. Configuração do mongod.conf

Atualize seu arquivo de configuração para máxima segurança:

# /etc/mongod.conf

# Rede - NUNCA use 0.0.0.0 em produção
net:
  port: 27017
  bindIp: 127.0.0.1  # Apenas localhost
  # Para acesso remoto específico:
  # bindIp: 127.0.0.1,192.168.1.100

  # TLS/SSL (recomendado)
  tls:
    mode: requireTLS
    certificateKeyFile: /etc/ssl/mongodb.pem
    CAFile: /etc/ssl/ca.pem

# Segurança - SEMPRE habilite
security:
  authorization: enabled
  javascriptEnabled: false  # Desabilita JavaScript no servidor

  # Para clusters
  # keyFile: /etc/mongodb-keyfile

# Logging para auditoria
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log
  verbosity: 1

# Limites de operação
operationProfiling:
  mode: slowOp
  slowOpThresholdMs: 100

# Storage
storage:
  dbPath: /var/lib/mongodb
  journal:
    enabled: true
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1

3. Configuração de Firewall

Configure regras de firewall para proteger ainda mais:

# UFW (Ubuntu/Debian)
# Bloquear acesso externo ao MongoDB
sudo ufw deny 27017

# Permitir apenas IPs específicos
sudo ufw allow from 192.168.1.0/24 to any port 27017

# iptables
# Bloquear todo acesso externo
sudo iptables -A INPUT -p tcp --dport 27017 -j DROP

# Permitir apenas localhost
sudo iptables -A INPUT -p tcp -s 127.0.0.1 --dport 27017 -j ACCEPT

# Permitir IP específico
sudo iptables -A INPUT -p tcp -s 192.168.1.100 --dport 27017 -j ACCEPT

4. Proteção com Docker

Se você usa Docker, configure corretamente:

# docker-compose.yml
version: '3.8'

services:
  mongodb:
    image: mongo:7.0
    restart: unless-stopped
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD_FILE: /run/secrets/mongo_root_password
    ports:
      # NUNCA exponha diretamente - use apenas rede interna
      - "127.0.0.1:27017:27017"
    volumes:
      - mongodb_data:/data/db
      - ./mongod.conf:/etc/mongod.conf:ro
    command: ["mongod", "--config", "/etc/mongod.conf"]
    secrets:
      - mongo_root_password
    networks:
      - backend
    # Limites de recursos
    deploy:
      resources:
        limits:
          memory: 2G
        reservations:
          memory: 512M

secrets:
  mongo_root_password:
    file: ./secrets/mongo_password.txt

volumes:
  mongodb_data:

networks:
  backend:
    internal: true  # Rede isolada

Conexão Segura em Aplicações Node.js

Atualize sua aplicação para usar conexões seguras:

// config/database.js
const mongoose = require('mongoose');

const mongoConfig = {
    // Use variáveis de ambiente para credenciais
    uri: process.env.MONGODB_URI,

    options: {
        // Autenticação
        authSource: 'admin',
        authMechanism: 'SCRAM-SHA-256',

        // TLS/SSL
        tls: true,
        tlsCAFile: process.env.MONGODB_CA_CERT,
        tlsCertificateKeyFile: process.env.MONGODB_CLIENT_CERT,

        // Pool de conexões
        maxPoolSize: 10,
        minPoolSize: 2,

        // Timeouts
        serverSelectionTimeoutMS: 5000,
        socketTimeoutMS: 45000,
        connectTimeoutMS: 10000,

        // Retry
        retryWrites: true,
        retryReads: true,

        // Compressão
        compressors: ['zstd', 'snappy', 'zlib'],
    }
};

async function connectDatabase() {
    try {
        // Validar URI antes de conectar
        if (!mongoConfig.uri) {
            throw new Error('MONGODB_URI não configurada');
        }

        // Conectar com retry
        await mongoose.connect(mongoConfig.uri, mongoConfig.options);

        console.log('✅ MongoDB conectado com sucesso');

        // Handlers de eventos
        mongoose.connection.on('error', (err) => {
            console.error('❌ Erro MongoDB:', err);
        });

        mongoose.connection.on('disconnected', () => {
            console.warn('⚠️ MongoDB desconectado');
        });

    } catch (error) {
        console.error('❌ Falha ao conectar MongoDB:', error);
        process.exit(1);
    }
}

// Graceful shutdown
process.on('SIGINT', async () => {
    await mongoose.connection.close();
    console.log('MongoDB desconectado via SIGINT');
    process.exit(0);
});

module.exports = { connectDatabase, mongoConfig };

Exemplo com Driver Nativo

// Para conexões sem Mongoose
const { MongoClient } = require('mongodb');

async function createSecureClient() {
    const client = new MongoClient(process.env.MONGODB_URI, {
        // Autenticação forte
        auth: {
            username: process.env.MONGODB_USER,
            password: process.env.MONGODB_PASSWORD,
        },
        authMechanism: 'SCRAM-SHA-256',
        authSource: 'admin',

        // TLS obrigatório
        tls: true,
        tlsAllowInvalidCertificates: false,
        tlsAllowInvalidHostnames: false,

        // Validação de certificado
        tlsCAFile: '/path/to/ca.pem',

        // Limites de segurança
        maxPoolSize: 10,
        serverSelectionTimeoutMS: 5000,

        // Monitoramento
        monitorCommands: true,
    });

    // Listener para comandos (auditoria)
    client.on('commandStarted', (event) => {
        // Log apenas em desenvolvimento
        if (process.env.NODE_ENV === 'development') {
            console.log(`Command: ${event.commandName}`);
        }
    });

    await client.connect();
    return client;
}

module.exports = { createSecureClient };

Monitoramento e Detecção de Intrusões

Configure alertas para detectar atividades suspeitas:

Script de Monitoramento

// monitor-mongodb-security.js
const { MongoClient } = require('mongodb');

class MongoDBSecurityMonitor {
    constructor(uri) {
        this.uri = uri;
        this.alerts = [];
    }

    async checkForSuspiciousActivity() {
        const client = new MongoClient(this.uri);

        try {
            await client.connect();
            const admin = client.db('admin');

            // 1. Verificar conexões ativas
            const currentOps = await admin.command({ currentOp: 1, active: true });
            const suspiciousOps = currentOps.inprog.filter(op =>
                op.client && !op.client.startsWith('127.0.0.1')
            );

            if (suspiciousOps.length > 0) {
                this.alert('CONEXÕES EXTERNAS DETECTADAS', suspiciousOps);
            }

            // 2. Verificar tentativas de login
            const logs = await admin.command({
                getLog: 'global'
            });

            const authFailures = logs.log.filter(l =>
                l.includes('authentication failed')
            );

            if (authFailures.length > 10) {
                this.alert('MÚLTIPLAS FALHAS DE AUTENTICAÇÃO', {
                    count: authFailures.length,
                    recent: authFailures.slice(-5)
                });
            }

            // 3. Verificar comandos perigosos
            const dangerousCommands = ['dropDatabase', 'dropCollection', 'eval'];
            // Implementar verificação de logs

            console.log('✅ Verificação de segurança concluída');
            return this.alerts;

        } finally {
            await client.close();
        }
    }

    alert(type, details) {
        const alert = {
            timestamp: new Date(),
            type,
            details,
            severity: 'HIGH'
        };
        this.alerts.push(alert);
        console.error(`🚨 ALERTA: ${type}`, details);
        // Aqui você pode integrar com Slack, email, PagerDuty, etc.
    }
}

module.exports = { MongoDBSecurityMonitor };

Boas Práticas de Segurança MongoDB

Para garantir segurança contínua, siga estas práticas:

Checklist de Segurança

Configuração básica:

  • Autenticação habilitada com SCRAM-SHA-256
  • Usuários com privilégios mínimos necessários
  • Bind IP restrito (nunca 0.0.0.0)
  • Firewall configurado corretamente

Criptografia:

  • TLS/SSL habilitado para todas as conexões
  • Certificados válidos e atualizados
  • Encryption at rest habilitado

Monitoramento:

  • Logs de auditoria habilitados
  • Alertas para atividades suspeitas
  • Backup regular e testado
  • Plano de resposta a incidentes

Atualizações:

  • MongoDB atualizado para última versão estável
  • Drivers atualizados
  • Patches de segurança aplicados

Conclusão

A vulnerabilidade que afetou 87 mil servidores MongoDB é um lembrete importante de que segurança não pode ser deixada para depois. Muitas dessas exposições poderiam ser evitadas com configurações básicas que levam minutos para implementar.

Se você usa MongoDB em produção, reserve um tempo hoje para verificar suas configurações e implementar as proteções necessárias. A segurança dos dados dos seus usuários depende disso.

Se você se sente inspirado a aprender mais sobre segurança em desenvolvimento, recomendo que dê uma olhada em outro artigo: Segurança em APIs REST: Guia Completo onde você vai descobrir como proteger seus endpoints de ataques comuns.

Bora pra cima! 🦅

Comentários (0)

Esse artigo ainda não possui comentários 😢. Seja o primeiro! 🚀🦅

Adicionar comentário