Notícias
Notícias
5 min de leitura
10 de outubro de 2026

Senha '123456' vazou MILHÕES (seu agente tá seguro?)

Dinamarca: 9M pessoas vazaram com senha '123456'. Seu agente guarda senhas fracas? Auditoria credenciais em produção.

Equipe OpenClaw

Equipe OpenClaw · Time de Engenharia & Produto

A Equipe OpenClaw é formada por engenheiros, designers e especialistas em IA dedicados a construir a melhor plataforma de agentes conversacionais para negócios brasileiros. Combinamos expertise…


Senha '123456' vazou MILHÕES (seu agente tá seguro?)

Notícia: Na Dinamarca, um breach massivo expôs 9+ MILHÕES de pessoas. Razão: A senha mais comum era "123456" (sim, mesmo). Dados: CPF (CPR), endereço, telefone, email—tudo vaza quando senha é trivial.

Implicação: Se Dinamarca (país desenvolvido com segurança razoável) não consegue evitar "123456", seu agente de IA em produção—que tá guardando senhas de clientes, API keys, tokens—pode estar vazando tudo AGORA com senhas fracas.

**"Você é CTO de SaaS com agente integrado.

Cenário: Breach por senha fraca ├─ Seu agente guarda: Senhas de clientes, API keys, tokens ├─ Senhas armazenadas: "senha123", "123456", "admin" ├─ Hacker: Tenta força bruta (1 segundo pra quebrar) ├─ Resultado: Tudo vaza (clientes, dados, credenciais) ├─ Descoberta: Quando cliente avisa (3 meses depois) ├─ Impacto: LGPD fine (R$ 50M), reputação destruída └─ Seu erro: "Não checamos força das senhas" └─ Mas você deveria (é seu job) "**


O que aconteceu na Dinamarca?

Timeline do breach

Incidente: ├─ Database comprometida (provavelmente hack) ├─ 9+ MILHÕES de registros expostos ├─ Dados: CPR (igual CPF), nome, endereço, telefone, email └─ Timeline: Descoberto ~2 semanas atrás

Por que foi tão fácil explorar: ├─ Senhas armazenadas em PLAIN TEXT ou HASH FRACO ├─ Sem salt (proteção mínima não usada) ├─ Sem rate limiting (hacker tenta infinito) ├─ Senhas fracas no database ("123456", "password", etc) └─ Resultado: Força bruta leva SEGUNDOS

Senhas mais comuns encontradas: ├─ 1º: "123456" (100.000+ ocorrências) ├─ 2º: "password" (50.000+ ocorrências) ├─ 3º: "12345678" (40.000+ ocorrências) ├─ 4º: "qwerty" (30.000+ ocorrências) ├─ 5º: "abc123" (25.000+ ocorrências) └─ ... └─ Top 100 = 500.000+ pessoas (5% do breach)

Implicação: └─ Se hacker tem hash database └─ Tenta top 100 senhas fracas └─ 5% tá quebrado em 1 segundo └─ 50% tá quebrado em 1 hora (com GPU) └─ 90% tá quebrado em 1 semana └─ 99% tá quebrado em 1 mês └─ Resultado: Praticamente TODOS se perdem

Como isso aconteceu (raiz do problema)

Problema 1: Senhas fracas PERMITIDAS ├─ Sistema aceitava: "123456" (6 caracteres) ├─ Sistema aceitava: Sem maiúscula ├─ Sistema aceitava: Sem números (wait, "123456" é número) ├─ Sistema aceitava: Sem símbolo especial ├─ Restrição: NENHUMA (qualquer coisa valia) └─ Resultado: Usuário criava senha trivial

Problema 2: Armazenamento inseguro ├─ Provavelmente: PLAIN TEXT (muito ruim) ├─ Ou: Hash MD5 (muito fraco) ├─ Ou: Hash SHA1 (fraco) ├─ Deveria ser: bcrypt/scrypt/PBKDF2 (forte) ├─ Sem salt: Hash determinístico (muito fraco) ├─ Com salt: Hash único por usuário (melhor) └─ Resultado: Mesmo com hash, senhas fracas quebram rápido

Problema 3: Sem força bruta protection ├─ Rate limiting: Nenhum ├─ Captcha: Nenhum ├─ Lockout após 5 tentativas: Nenhum ├─ Alertas: Nenhum └─ Resultado: Hacker tenta infinitas senhas

Problema 4: Sem monitoramento ├─ Logs: Nenhum (ou deletados) ├─ Alerts: Nenhum ├─ Anomaly detection: Nenhum ├─ Descoberta: Muito tarde (3+ meses) └─ Resultado: Hacker tinha tempo de sobra

Culpa: └─ Não é usuário (escolheu fraco, ok) └─ É SISTEMA (permitiu fraco, não protegeu) └─ Você: Mesma coisa acontecendo?


Seu agente tá com mesmo problema?

Auditoria: Quanto segura credenciais?

Perguntas pra responder HOJE:

Pergunta 1: Como seu agente armazena senhas? ├─ ☐ Plain text (PÉSSIMO, 0/10) ├─ ☐ Base64 (PÉSSIMO, 0/10) ├─ ☐ Hash MD5/SHA1 (RUIM, 2/10) ├─ ☐ Hash bcrypt/scrypt (BOM, 8/10) ├─ ☐ Encrypted AES-256 (BOM, 8/10) ├─ ☐ Vault externo (ÓTIMO, 10/10) └─ ??? = Você não sabe (CRÍTICO, fix AGORA)

Pergunta 2: Que força de senha você exige? ├─ ☐ Nenhuma (qualquer coisa vale) ← Dinamarca tá assim ├─ ☐ 6+ caracteres (fraco, "123456" passa) ├─ ☐ 8+ caracteres + maiúscula + número (melhor) ├─ ☐ 12+ caracteres + maiúscula + número + símbolo (ótimo) ├─ ☐ Passphrase (4+ palavras aleatórias) (excelente) └─ ??? = Você não testou (RISCO)

Pergunta 3: Seu agente força senha FORTE? ├─ ☐ NÃO: Usuário escolhe qualquer coisa (PÉSSIMO) ├─ ☐ SIM mas fraco: 8+ (ainda vulnerável) ├─ ☐ SIM forte: 12+ + maiúscula + número + símbolo (BOM) ├─ ☐ Força geração: Gerador de senha obrigatório (MELHOR) └─ ??? = Não testou (RISCO)

Pergunta 4: Você valida senhas fracas? ├─ ☐ NÃO: "123456" é aceito (PÉSSIMO) ├─ ☐ SIM manual: Blacklist de 100 piores senhas ├─ ☐ SIM automático: Integration com Have I Been Pwned API ├─ ☐ SIM + zxcvbn: Estimativa de força de senha └─ ??? = Não implementado (RISCO)

Score sua: └─ <5 ☐: Seu agente TÁ INSEGURO (igual Dinamarca) └─ 5-8 ☐: Parcialmente seguro (faltam camadas) └─ 8+ ☐: Razoável (continua melhorando)

Se <5: PAUSAR agente até implementar. Sério.


Como armazenar credenciais SEGURO

Estratégia 1: Encryption em repouso (AES-256)

Ideia: └─ Agente guarda senhas criptografadas └─ Se database vaza, senhas ficam protegidas └─ Sem key, hacker não consegue descriptografar

Implementação:

python from cryptography.fernet import Fernet import os

class CredentialVault: def init(self): # Gera key UMA VEZ, guarda em environment variable seguro self.key = os.getenv("VAULT_ENCRYPTION_KEY").encode() self.cipher = Fernet(self.key)

def store_password(self, username, password):
    """
    Armazena senha criptografada
    """
    encrypted = self.cipher.encrypt(password.encode())
    # Salva no database
    db.insert({
        "username": username,
        "password_encrypted": encrypted,
        "created_at": now()
    })

def verify_password(self, username, attempt):
    """
    Verifica se senha tá correta
    """
    record = db.get(username)
    try:
        decrypted = self.cipher.decrypt(record["password_encrypted"])
        return decrypted.decode() == attempt
    except:
        return False  # Decrypt falhou = senha errada

Uso

vault = CredentialVault() vault.store_password("user1", "MyS3cur3P@ssw0rd")

No database fica: b'gAAAAABm...encrypted...text'

Sem key, inútil

Vantagem: └─ Se database vaza, senhas tão criptografadas └─ Sem chave de encryption, hacker não consegue └─ Chave guardada separadamente (não no database)

Desvantagem: └─ Key management é difícil (onde guarda key?) └─ Se key vaza, tudo vaza └─ Solução: Usar vault externo (próxima seção)

Estratégia 2: Hashing com bcrypt (melhor que MD5)

Ideia: └─ Armazena HASH da senha, não a senha └─ Se database vaza, senha tá protegida └─ Sem reverse (hash não pode reverter pra senha)

Implementação:

python import bcrypt

class PasswordManager: def hash_password(self, password): """ Cria hash seguro com bcrypt """ # Salt é adicionado automaticamente # Rounds = 12 (leva ~100ms, força bruta fica IMPOSSÍVEL) hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12)) return hashed.decode()

def verify_password(self, password_attempt, hashed_from_db):
    """
    Verifica se tentativa matches hash
    """
    return bcrypt.checkpw(password_attempt.encode(), hashed_from_db.encode())

Exemplo

manager = PasswordManager() hash1 = manager.hash_password("MyPassword123") hash2 = manager.hash_password("MyPassword123")

print(hash1) # $2b$12$abcd...xyz (salt aleatório) print(hash2) # $2b$12$efgh...uvw (DIFERENTE, mesmo password)

Cada hash é único mesmo com mesma senha (por causa salt)

Verificação

print(manager.verify_password("MyPassword123", hash1)) # True print(manager.verify_password("WrongPassword", hash1)) # False

Por quê bcrypt é melhor que MD5: └─ MD5: Hash rápido (~microsegundos), hacker tenta 1 BILHÃO/segundo └─ bcrypt rounds=12: Hash LENTO (~100ms), hacker tenta 10/segundo └─ Resultado: Força bruta fica impossível (10 senhas/sec vs 1 bilhão/sec)

Vantagem: └─ Mesmo se database vaza, senhas tão hashed └─ Força bruta fica muito mais lenta (impraticável) └─ Simples de implementar

Desvantagem: └─ Não é reversível (não pode recuperar senha original) └─ Senhas fracas ainda quebram (mas leva mais tempo) └─ Solução: Force senha FORTE (próxima seção)

Estratégia 3: Validação de força de senha

Ideia: └─ Não permite senha fraca no registro └─ Força usuário a escolher forte (ou gera pra ele) └─ Se "123456" é rejeitado, não entra no database

Implementação:

python import zxcvbn # Biblioteca de força de senha import requests

class PasswordValidator: # Senhas muito comuns (top 1000 piores) COMMON_PASSWORDS = [ "123456", "password", "12345678", "qwerty", "abc123", "monkey", "1234567", "letmein", # ... top 1000 ]

def validate_strength(self, password):
    """
    Valida força da senha usando múltiplos critérios
    """
    errors = []
    
    # Critério 1: Comprimento mínimo
    if len(password) < 12:
        errors.append("Mínimo 12 caracteres")
    
    # Critério 2: Diversidade
    has_upper = any(c.isupper() for c in password)
    has_lower = any(c.islower() for c in password)
    has_digit = any(c.isdigit() for c in password)
    has_special = any(not c.isalnum() for c in password)
    
    if not (has_upper and has_lower and has_digit and has_special):
        errors.append("Precisa maiúscula, minúscula, número, e símbolo")
    
    # Critério 3: Não é senha comum
    if password.lower() in self.COMMON_PASSWORDS:
        errors.append("Senha muito comum (use gerador)")
    
    # Critério 4: Estimativa de força (zxcvbn)
    result = zxcvbn.zxcvbn(password)
    if result["score"] < 3:  # Score 0-4
        errors.append(f"Força baixa (score {result['score']}/4)")
    
    # Critério 5: Verificar contra breach público
    # Have I Been Pwned API (recomendado)
    if self._is_in_breach(password):
        errors.append("Senha foi vazada em breach anterior")
    
    return {"valid": len(errors) == 0, "errors": errors}

def _is_in_breach(self, password):
    """
    Verifica contra Have I Been Pwned (sem enviar senha completa)
    """
    import hashlib
    sha1 = hashlib.sha1(password.encode()).hexdigest().upper()
    prefix = sha1[:5]
    suffix = sha1[5:]
    
    # API HIBP não precisa da senha completa
    response = requests.get(f"https://api.pwnedpasswords.com/range/{prefix}")
    hashes = response.text.split('\n')
    
    for h in hashes:
        if h.startswith(suffix):
            return True  # Senha foi vazada
    return False

Uso

validator = PasswordValidator()

Teste 1: Senha fraca

result = validator.validate_strength("123456") print(result)

{"valid": False, "errors": ["Mínimo 12 caracteres", "Força baixa", ...]}

Teste 2: Senha forte

result = validator.validate_strength("MyS3cur3!@#Passw0rd") print(result)

{"valid": True, "errors": []}

Vantagem: └─ Rejeita senha fraca ANTES de armazenar └─ Usuário é forçado a escolher forte └─ Verifica contra breaches públicos └─ Se "123456" é rejeitado, nunca entra no database

Desvantagem: └─ Usuário quer senha simples (terá que gerar) └─ Solução: Botão "Gerar senha forte" obrigatório

Estratégia 4: Vault externo (melhor prática)

Ideia: └─ NÃO guarda senhas no seu database └─ Usa serviço externo (AWS Secrets Manager, HashiCorp Vault, etc) └─ Database não tem o dado sensível └─ Se database vaza, senhas tão protegidas

Fluxo:

  1. Usuário cria senha
  2. Seu agente valida força (descrição acima)
  3. Seu agente NÃO armazena senha
  4. Seu agente envia pra Vault externo
  5. Vault retorna ID (ex: "secret-id-12345")
  6. Seu database guarda APENAS o ID (não a senha)
  7. Quando precisa usar senha: Agente pede pro Vault
  8. Vault valida (qual agente? tem permissão?) e retorna

Implementação com AWS Secrets Manager:

python import boto3 import json

class SecureVault: def init(self): self.client = boto3.client('secretsmanager')

def store_credential(self, user_id, password, metadata=None):
    """
    Armazena credencial no Vault externo (não no database local)
    """
    secret_name = f"agent/user/{user_id}/password"
    secret_value = {
        "password": password,
        "created_at": str(now()),
        "metadata": metadata or {}
    }
    
    try:
        # Armazena no AWS Secrets Manager (criptografado, multi-region, audit)
        response = self.client.create_secret(
            Name=secret_name,
            SecretString=json.dumps(secret_value),
            Tags=[{"Key": "App", "Value": "Agent"}]
        )
        
        # Retorna ao database APENAS o secret ARN (não a senha)
        return {
            "secret_arn": response["ARN"],
            "secret_id": response["Name"]
        }
    except Exception as e:
        # Falha no vault = rejeita operação
        return None

def get_credential(self, secret_arn, agent_id):
    """
    Recupera credencial do Vault (com auditoria de acesso)
    """
    # Vault primeiro: Qual agente está pedindo?
    # Tem permissão de ler esse secret?
    # Log de acesso pra auditoria
    
    try:
        response = self.client.get_secret_value(SecretId=secret_arn)
        secret = json.loads(response["SecretString"])
        
        # Audit log
        self._log_access(agent_id, secret_arn, "READ", success=True)
        
        return secret["password"]
    except Exception as e:
        self._log_access(agent_id, secret_arn, "READ", success=False, error=str(e))
        return None

def _log_access(self, agent_id, secret_id, action, success, error=None):
    """
    Audit log: Quem acessou o quê e quando
    """
    log_entry = {
        "timestamp": now(),
        "agent_id": agent_id,
        "secret_id": secret_id,
        "action": action,
        "success": success,
        "error": error
    }
    # Envia pra CloudWatch, DataDog, ou outro log centralizado
    print(f"AUDIT: {log_entry}")

Uso

vault = SecureVault()

Armazenar

result = vault.store_credential( user_id="user-123", password="MyS3cur3P@ss", metadata={"service": "api-key-stripe"} )

Database armazena: {"secret_arn": "arn:aws:secretsmanager:...", "user_id": "user-123"}

A SENHA NUNCA entra no database local

Recuperar (apenas quando precisar)

password = vault.get_credential(secret_arn, agent_id="agent-456")

Vault: Log de acesso automaticamente

Vantagem: └─ Senhas NUNCA entram no seu database └─ Vault faz encriptação, key rotation, audit logs └─ Se database vaza, NADA sensível tá lá └─ Auditoria automática (quem acessou o quê) └─ Multi-region + backup automático

Desvantagem: └─ Custo (AWS cobra por secret armazenado) └─ Latência (precisa chamar Vault externo) └─ Solução: Cache local com TTL (ex: 5 min)


Checklist: Seu agente está seguro?

Auditoria rápida

☐ Você SABE onde senhas são armazenadas? ☐ Você usa bcrypt/scrypt (não MD5/SHA1)? ☐ Você força senha 12+ caracteres? ☐ Você força maiúscula + número + símbolo? ☐ Você rejeita top 1000 senhas comuns? ☐ Você valida contra breaches públicos (HIBP)? ☐ Você usa Vault externo (não database local)? ☐ Você tem rate limiting (protege força bruta)? ☐ Você tem audit logs (quem acessou o quê)? ☐ Você testa: "Posso quebrar senha com força bruta?"

Score: └─ <5 ☐: Igual Dinamarca (INSEGURO) └─ 5-7 ☐: Parcialmente seguro └─ 8-10 ☐: Razoavelmente seguro

Se <5: PAUSAR agente até consertar. Sério.


Conclusão: Você está exposto?

Dinamarca: Senha "123456" vazou 9+ MILHÕES de pessoas.

Se isso pode acontecer lá, pode acontecer com você.

Ação:

HOJE: ☐ Audit: Onde seu agente armazena senhas? ☐ Teste: Pode quebrar senha com força bruta? ☐ Validate: Que força de senha você exige?

SEMANA 1: ☐ Implement: Validação de força (12+ chars, símbolos) ☐ Implement: Rejeição de senhas comuns ☐ Implement: bcrypt (em vez de MD5) ☐ Test: "123456" é rejeitado? SIM. ☐ Test: Força bruta leva >1 hora pra quebrar

SEMANA 2: ☐ Implement: Vault externo (AWS Secrets Manager) ☐ Implement: Audit logging (quem acessou) ☐ Implement: Rate limiting (protege força bruta) ☐ Test: Se database vaza, senhas tão protegidas

ANTES DO MÊS ACABAR: ☐ Tudo implementado ☐ Testes passando ☐ Agente rodando SEGURO ☐ Audit logs funcionando

NÃO FAZER: └─ Não confie em "ninguém vai quebrar" (errado) └─ Não ignore senhas fracas (LGPD vai multar) └─ Não espere breach acontecer (tarde demais) └─ Não use MD5/SHA1 (2026, use bcrypt) └─ Não guarde no database local (use Vault)

FAZER: └─ Force senha FORTE (12+ chars, símbolos) └─ Rejeite comuns ("123456" = NÃO) └─ Use bcrypt (hash, não encryption) └─ Use Vault externo (senhas fora do database) └─ Audit tudo (logs de acesso) └─ Test red team (tenta quebrar)

Problema tá resolvido quando: └─ "123456" é rejeitado no registro └─ Senhas tão em Vault externo (não database) └─ Força bruta leva >1 hora pra quebrar └─ Você tem audit logs de todo acesso └─ Pode dormir tranquilo

→ OpenClaw: Agentes com Credenciais Seguras (Vault + Audit)

Dinamarca: "123456" = 9M pessoas vazadas. Seu agente: Mesmo risco? Proteja agora. ⚠️


Publicado em 10 de outubro de 2026

Leia também