Voltar ao Blog

Certificados TLS Não Autorizados em Servidores de Jogos: Como os Logs de Certificate Transparency Capturam o que os Firewalls Perdem

Publicado em 14 de agosto de 2026
Certificados TLS Não Autorizados em Servidores de Jogos: Como os Logs de Certificate Transparency Capturam o que os Firewalls Perdem Gerada com a ajuda de IA

Em resumo

Aprenda a monitorar logs de Certificate Transparency e detecte certificados TLS não autorizados nos seus servidores de jogos de forma eficaz.

Neste exato momento, existe um log público e somente de acréscimo de todo certificado TLS emitido para cada domínio na internet — incluindo o seu. Se alguém for a uma Autoridade Certificadora amanhã e convencê-la a emitir um certificado TLS válido para a sua API de jogo em api.yourgame.com, esse certificado aparecerá nos logs de Certificate Transparency (CT) em poucos minutos. A única pergunta é se você vai notar.

A maioria dos desenvolvedores de jogos não vai notar. Eles descobrem quando os jogadores relatam erros de SSL, quando um testador de penetração sinaliza o problema ou, pior — quando tokens de autenticação roubados começam a aparecer em mercados secundários porque um certificado malicioso permitiu um proxy de homem no meio entre os jogadores e o endpoint de login.

Este post é um runbook para monitorar logs de Certificate Transparency nos domínios do seu backend de jogo. Ele cobre o que os logs de CT realmente são, como consultá-los programaticamente, como filtrar o ruído das suas próprias renovações de rotina e como construir um pipeline de alertas que detecte emissões de certificados não autorizadas antes que se tornem violações.

O Que Quebra: Emissão Não Autorizada de Certificados TLS em Backends de Jogos

Todo certificado TLS emitido por uma Autoridade Certificadora (CA) de confiança pública deve ser registrado em pelo menos dois logs públicos de Certificate Transparency. Isso é efetivamente obrigatório desde abril de 2018, quando o Chrome começou a exigir a inclusão de CT em todos os certificados novos. O Apple Safari seguiu com requisitos semelhantes. Qualquer certificado que não esteja registrado não será confiável para os principais navegadores.

O ecossistema de CT existe para detectar emissão indevida — situações em que uma CA emite um certificado para um domínio que o solicitante não controla. Para backends de jogos, o modelo de ameaça é o seguinte:

  • Interceptação de credenciais: um invasor obtém um certificado válido para auth.yourgame.com, configura um proxy entre os jogadores e seu servidor de autenticação real e coleta tokens de login. Para o jogador, a conexão parece legítima porque o navegador confia no certificado.
  • Personificação de API: um certificado para matchmaking.yourgame.com permite que uma parte mal-intencionada encerre conexões TLS e injete lógica de jogo falsa ou redirecione jogadores para um servidor falsificado.
  • Ataques de repetição e downgrade: com um certificado válido em mãos, um invasor pode remover o TLS e retransmitir o tráfego, permitindo ataques de repetição de sessão ou downgrade de protocolo que, de outra forma, falhariam contra um endpoint criptografado configurado corretamente.

Isso não é teórico. O monitoramento de CT detectou o incidente de MITM da CNNIC em 2015 e várias emissões indevidas da Symantec que levaram o Chrome a desconfiar de todos os certificados da Symantec. O mesmo mecanismo que detecta comprometimentos de CAs de estados-nação funciona para o servidor de API do seu jogo indie.

O Que É Certificate Transparency (e o Que Não É)

Certificate Transparency não é uma ferramenta de segurança que você instala. É um conjunto de servidores de log publicamente auditáveis e criptograficamente auditáveis que registram todos os certificados emitidos por CAs participantes. Veja o que acontece quando um certificado é emitido:

  1. A CA gera um pré-certificado e o envia para um ou mais logs de CT.
  2. Cada log retorna um Signed Certificate Timestamp (SCT) — uma promessa criptográfica de que o log registrou o certificado.
  3. A CA incorpora esses SCTs no certificado final e o emite para o solicitante.
  4. Os navegadores verificam se há SCTs válidos antes de confiar no certificado.

Cada uma dessas entradas de log é publicamente consultável. Serviços como o crt.sh fornecem uma interface de busca gratuita sobre os logs. Qualquer pessoa — inclusive você — pode pesquisar todos os certificados já emitidos para um determinado domínio.

O que o CT NÃO faz: ele não impede a emissão indevida. Ele não revoga certificados ruins. Ele fornece detecção, não prevenção. Isso significa que alguém precisa estar monitorando os logs e agindo sobre o que encontrar. Esse alguém é você.

Como Detectar: Consultando Logs de CT Programaticamente

A maneira mais acessível de consultar logs de Certificate Transparency é através do crt.sh, o Certificate Search, operado pela Sectigo. Ele fornece uma API JSON que não requer autenticação. Aqui está um script Python pronto para produção que consulta logs de CT para o seu domínio e sinaliza emissões de certificados inesperadas:

import requests
import json
from datetime import datetime, timedelta

# Domains to monitor — your game's API, auth, and matchmaker endpoints
MONITORED_DOMAINS = [
    "api.yourgame.com",
    "auth.yourgame.com",
    "match.yourgame.com",
]

# Issuers you expect and trust (adjust to your CDN/infrastructure provider)
TRUSTED_ISSUERS = {
    "C=US, O=Let's Encrypt, CN=R3",
    "C=US, O=Let's Encrypt, CN=E1",
    "C=US, O=Let's Encrypt, CN=R10",
    "C=US, O=Cloudflare, Inc., CN=Cloudflare Inc ECC CA-3",
}

def query_ct_logs(domain: str, check_hours: int = 72) -> list[dict]:
    """Query crt.sh for certificates issued for a domain in the last N hours."""
    url = f"https://crt.sh/?q=%25.{domain}&output=json"
    headers = {"User-Agent": "GameBackend-CT-Monitor/1.0"}

    try:
        resp = requests.get(url, headers=headers, timeout=60)
        resp.raise_for_status()
        certificates = resp.json()
    except requests.RequestException as e:
        print(f"[ERROR] Failed to query crt.sh for {domain}: {e}")
        return []

    cutoff = datetime.utcnow() - timedelta(hours=check_hours)
    results = []
    for cert in certificates:
        # crt.sh returns not_before as "2024-01-15T09:00:00" UTC
        try:
            not_before = datetime.strptime(cert["not_before"], "%Y-%m-%dT%H:%M:%S")
        except (ValueError, KeyError):
            continue
        if not_before > cutoff:
            results.append({
                "id": cert.get("id"),
                "domain": cert.get("common_name"),
                "issuer": cert.get("issuer_name"),
                "not_before": cert.get("not_before"),
                "not_after": cert.get("not_after"),
                "serial_number": cert.get("serial_number"),
            })
    return results

def run_monitor():
    """Check all monitored domains and return unauthorized certificates."""
    all_alerts = []
    for domain in MONITORED_DOMAINS:
        recent_certs = query_ct_logs(domain, check_hours=72)
        for cert in recent_certs:
            issuer = cert["issuer"]
            # Normalize: crt.sh sometimes adds whitespace variants
            issuer_normalized = issuer.strip()
            is_trusted = any(
                trusted in issuer_normalized for trusted in TRUSTED_ISSUERS
            )
            if not is_trusted:
                all_alerts.append(cert)
                print(
                    f"⚠️  ALERT: Unexpected certificate for {cert['domain']}\n"
                    f"   Issuer:    {issuer}\n"
                    f"   Valid:     {cert['not_before']} → {cert['not_after']}\n"
                    f"   Serial:    {cert['serial_number']}\n"
                    f"   crt.sh ID: https://crt.sh/?q={cert['serial_number']}\n"
                )
    if not all_alerts:
        print("✅ No unexpected certificates found across all monitored domains.")
    return all_alerts

if __name__ == "__main__":
    run_monitor()

Execute isso com um cron job a cada 12 horas e você terá um sistema de monitoramento de CT rudimentar, porém eficaz:

0 */12 * * * /usr/bin/python3 /opt/monitor/ct_monitor.py >> /var/log/ct_monitor.log 2>&1

O Que Este Script Faz Bem

  • Consulta o crt.sh (gratuito, sem chave de API, ilimitado para taxas de polling razoáveis)
  • Filtra por horário de emissão para que você veja apenas certificados das últimas 72 horas
  • Verifica o emissor em uma lista de permissões conhecida para sinalizar certificados de CAs inesperadas
  • Emite saída estruturada que você pode encaminhar para Slack, Discord, PagerDuty ou e-mail

Onde Este Script Fica Aquém

A abordagem de lista de permissões só funciona se você conhecer todos os emissores antecipadamente. Se você mudar do Let's Encrypt para o ZeroSSL, terá um falso alarme. E o crt.sh tem latência — normalmente de 15 minutos a algumas horas entre a emissão e o aparecimento no log, além de tempo adicional para o crt.sh indexar a entrada. Alertas em tempo real exigem monitoramento direto dos logs de CT, o que é substancialmente mais complexo.

Há também o problema do ruído, que quase quebrou o modelo de monitoramento por completo.

O Problema do Ruído: Fadiga de Alertas dos Seus Próprios Certificados

Aqui está a parte que derruba a maioria das configurações de monitoramento de CT: o ruído dos seus próprios certificados legítimos.

Certificados TLS têm vida curta por design. Um certificado padrão do Let's Encrypt é válido por 90 dias e renova automaticamente por volta do dia 60. Certificados Cloudflare Universal SSL podem renovar a cada 60 dias — cerca de seis vezes por ano. O CA/Browser Forum votou para reduzir o tempo máximo de vida do certificado para 47 dias até 2029, o que quase dobrará a cadência de renovação.

Cada uma dessas renovações aparece nos logs de CT. Cada entrada de log aciona seu script de monitoramento. Se você estiver executando três domínios de backend de jogos com renovação automática de certificados, estará olhando para 18 alertas por ano por domínio da sua própria infraestrutura — cada um aparecendo como um certificado "novo" nos logs.

Um cliente da Cloudflare descreveu a desativação do monitoramento de CT em todos os seus sites porque estava cansado de "receber spam com toneladas de renovações de certificados completamente normais", acrescentando: "No final, eu nem estava mais lendo".

Quando o sinal que importa é um único certificado anômalo enterrado em um fluxo de renovações automatizadas que você não consegue distinguir de fora, o sistema para de funcionar. Você precisa de uma maneira de identificar e suprimir alertas para certificados que você mesmo emitiu.

A Solução: Impressão Digital SPKI para Separar Seus Certificados dos Desconhecidos

A Cloudflare resolveu isso recentemente em escala usando hashes de SubjectPublicKeyInfo (SPKI) como um identificador consistente em seus sistemas de emissão de certificados e alertas de CT. A abordagem se generaliza para qualquer infraestrutura, e desenvolvedores de jogos que mantêm seu próprio gerenciamento de certificados podem adotar a mesma técnica.

Por Que uma Simples Consulta Não Funciona

O primeiro instinto é rastrear certificados emitidos em um banco de dados e cruzar seus números de série ou impressões digitais com as entradas do log de CT. O problema é o timing:

  1. Uma CA gera um pré-certificado e o envia para os logs de CT.
  2. O log de CT registra o pré-certificado.
  3. A CA incorpora os Signed Certificate Timestamps (SCTs) no certificado final.
  4. A CA registra o certificado final.
  5. A CA entrega o certificado final para você.

Uma impressão digital com hash do pré-certificado e do certificado final diferem ligeiramente, porque o certificado final contém os SCTs incorporados que o pré-certificado não tinha. Se o seu sistema de monitoramento vir a entrada do pré-certificado no log de CT antes de a CA entregar o certificado final ao seu sistema de pedidos, não há registro para corresponder. Você tem um falso alarme.

O Hash SPKI: Um Identificador que Aparece em Todas as Etapas

O hash SPKI resolve o problema de timing porque a chave pública é idêntica no pré-certificado e no certificado final. Ela é gerada no momento da criação da chave — antes de qualquer certificado ser emitido — e não muda.

O identificador é: spki_sha256 = SHA-256(DER-encoded SubjectPublicKeyInfo)

Veja como calculá-lo:

from cryptography import x509
from cryptography.hazmat.primitives import hashes, serialization
import hashlib

def compute_spki_sha256_from_pem(pem_data: str) -> str:
    """Compute spki_sha256 from any PEM-encoded certificate (pre-cert or final)."""
    cert = x509.load_pem_x509_certificate(pem_data.encode("utf-8"))
    spki_der = cert.public_key().public_bytes(
        encoding=serialization.Encoding.DER,
        format=serialization.PublicFormat.SubjectPublicKeyInfo,
    )
    return hashlib.sha256(spki_der).hexdigest()

def compute_spki_sha256_from_csr(csr_pem: str) -> str:
    """Compute spki_sha256 from a Certificate Signing Request (earliest possible point)."""
    csr = x509.load_pem_x509_csr(csr_pem.encode("utf-8"))
    spki_der = csr.public_key().public_bytes(
        encoding=serialization.Encoding.DER,
        format=serialization.PublicFormat.SubjectPublicKeyInfo,
    )
    return hashlib.sha256(spki_der).hexdigest()

O Fluxo de Monitoramento com Filtragem SPKI

A arquitetura de monitoramento atualizada funciona assim:

Do seu lado (emissão de certificados):

  1. Gere um novo par de chaves para cada pedido de certificado.
  2. Calcule o spki_sha256 a partir do CSR ou da chave pública.
  3. Armazene o hash no seu banco de dados de rastreamento imediatamente — antes mesmo de a CA iniciar a emissão.
  4. Mantenha os hashes pelo tempo de vida do certificado mais uma margem de segurança (por exemplo, 30 dias após a expiração).

No lado do monitoramento (varredura de logs de CT):

  1. Analise novas entradas de log de CT para seus domínios.
  2. Extraia a chave pública de cada entrada de log e calcule o spki_sha256.
  3. Consulte o hash no seu banco de dados de rastreamento.
  4. Correspondência encontrada → este certificado veio da sua infraestrutura. Suprima o alerta.
  5. Nenhuma correspondência → este certificado não foi emitido pelo seu sistema. Levante um alerta.

Isso elimina falsos positivos das suas próprias renovações sem perder certificados genuinamente suspeitos de CAs externas.

Runbook Completo: Configurando o Monitoramento de Certificate Transparency para Servidores de Jogos

Pré-requisitos

  • Uma lista de todos os domínios e subdomínios usados pelo seu backend de jogo (incluindo CDN, autenticação, matchmaking, telemetria, entrega de ativos)
  • Python 3.9+ com as bibliotecas requests e cryptography
  • Um endpoint de alerta (webhook do Slack, webhook do Discord, e-mail SMTP ou PagerDuty)
  • Acesso ao seu sistema de gerenciamento de certificados para registrar hashes SPKI no momento da emissão

Passo 1: Enumere Sua Superfície de Ataque

Antes de monitorar, você precisa de um inventário completo dos domínios. Se esquecer um, ele fica sem monitoramento. Domínios comuns de backend de jogos incluem:

  • api.yourgame.com — API principal do jogo
  • auth.yourgame.com / login.yourgame.com — endpoints de autenticação
  • match.yourgame.com / lobby.yourgame.com — servidores de matchmaking e lobby
  • cdn.yourgame.com / assets.yourgame.com — entrega de ativos estáticos
  • telemetry.yourgame.com — análise e relatórios de falhas
  • status.yourgame.com — página de status (muitas vezes um serviço separado)

Domínios curinga (ex.: *.yourgame.com) expandem ainda mais a superfície. Todo certificado curinga que cobre seu domínio é um vetor de ataque se for emitido indevidamente.

Passo 2: Configure o Rastreamento de Hash SPKI

Integre o registro de hash ao seu pipeline de implantação de certificados. Sempre que um certificado for solicitado ou gerado, calcule e armazene o hash SPKI. Uma abordagem simples é um banco de dados SQLite local ou uma chave Redis compartilhada:

import sqlite3
from datetime import datetime, timezone

DB_PATH = "/opt/monitor/spki_hashes.db"

def init_db():
    conn = sqlite3.connect(DB_PATH)
    conn.execute("""
        CREATE TABLE IF NOT EXISTS known_hashes (
            spki_hash TEXT PRIMARY KEY,
            domain TEXT NOT NULL,
            recorded_at TEXT NOT NULL,
            expires_at TEXT
        )
    """)
    conn.commit()
    conn.close()

def register_certificate(spki_hash: str, domain: str, expires_at: str):
    conn = sqlite3.connect(DB_PATH)
    conn.execute(
        "INSERT OR REPLACE INTO known_hashes (spki_hash, domain, recorded_at, expires_at) VALUES (?, ?, ?, ?)",
        (spki_hash, domain, datetime.now(timezone.utc).isoformat(), expires_at),
    )
    conn.commit()
    conn.close()

def is_known_certificate(spki_hash: str) -> bool:
    conn = sqlite3.connect(DB_PATH)
    row = conn.execute(
        "SELECT 1 FROM known_hashes WHERE spki_hash = ?", (spki_hash,)
    ).fetchone()
    conn.close()
    return row is not None

Passo 3: Construa o Pipeline de Alertas

Combine o script de consulta de CT com a verificação do banco de dados SPKI. Quando um novo certificado aparecer nos logs de CT:

  1. Calcule seu hash SPKI.
  2. Verifique no seu banco de dados de hashes conhecidos.
  3. Se desconhecido, alerte imediatamente.
  4. Inclua o link do crt.sh, emissor, janela de validade e nome do host no payload do alerta.

Roteirizar alertas para um webhook do Slack ou Discord é rápido de configurar e dá à sua equipe visibilidade imediata:

import os
import requests

SLACK_WEBHOOK_URL = os.environ.get("SLACK_CT_WEBHOOK_URL")

def send_slack_alert(cert: dict):
    if not SLACK_WEBHOOK_URL:
        print("[WARN] No Slack webhook configured; alert not sent.")
        return
    payload = {
        "text": (
            f"🚨 *Unauthorized TLS Certificate Detected*\n"
            f"*Domain:* {cert['domain']}\n"
            f"*Issuer:* {cert['issuer']}\n"
            f"*Valid:* {cert['not_before']} → {cert['not_after']}\n"
            f"*CT Log Entry:* https://crt.sh/?q={cert['serial_number']}\n"
            f"_Investigate immediately._"
        )
    }
    requests.post(SLACK_WEBHOOK_URL, json=payload, timeout=10)

Passo 4: Defina Seu Playbook de Resposta a Incidentes

Quando um alerta dispara, você precisa de uma sequência de resposta documentada. Um falso alarme custa 5 minutos de investigação. Uma emissão indevida real que é ignorada custa as credenciais dos seus jogadores.

Ações imediatas (dentro de 1 hora do alerta):

  1. Abra o link do crt.sh e verifique os detalhes do certificado (domínio, emissor, tipo de chave, datas de validade).
  2. Verifique se o emissor é um que você reconhece. CAs desconhecidas, como uma autoridade regional obscura emitindo certificados para seu domínio .com, são um sinal de alerta.
  3. Verifique se o certificado ainda é válido e acessível na porta 443 em relação aos registros DNS do seu domínio (openssl s_client -connect yourgame.com:443 -servername yourgame.com).
  4. Compare a impressão digital da chave pública do certificado com suas chaves conhecidas.

Se o certificado for não autorizado:

  1. Envie um Certificate Problem Report para a CA emissora (a maioria das CAs tem um contato abuse@ ou security@).
  2. Simultaneamente, entre em contato com a CA por meio da interface web ou do canal direto de escalonamento.
  3. Se a CA não responder em 24 horas, encaminhe para o CA/Browser Forum ou para os programas de raiz dos navegadores (contato de Segurança do Chromium do Chrome, Reclamações de CA da Mozilla).
  4. Se a emissão indevida foi uma falha de validação de domínio (alguém provou propriedade que não tinha), audite todos os seus registros DNS e WHOIS em busca de sinais de comprometimento.
  5. Considere implantar registros DNS CAA (Certificate Authority Authorization) para restringir quais CAs podem emitir certificados para seu domínio:
yourgame.com.  IN  CAA  0 issue "letsencrypt.org"
yourgame.com.  IN  CAA  0 issuewild "letsencrypt.org"
yourgame.com.  IN  CAA  0 iodef "security@yourgame.com"

Registros CAA são verificados por CAs em conformidade antes da emissão. Eles não impedem uma CA não conforme, mas reduzem significativamente a superfície de ataque e tornam impossível a emissão indevida de CAs que honram registros CAA.

Passo 5: Automatize a Prevenção de Recorrência

Depois de lidar com um incidente, reforce sua postura:

  • Implante registros CAA para todos os domínios de backend de jogos (se ainda não estiverem em vigor).
  • Habilite a Autenticação de Entidades Nomeadas baseada em DNS (DANE) com registros TLSA onde seu provedor de DNS suportar — isso vincula chaves de certificado específicas ao seu domínio no nível do DNS.
  • Reduza sua própria janela de renovação de certificados. Certificados com vida mais curta significam que o raio de impacto de uma chave privada comprometida é menor.
  • Registre todos os eventos de emissão de certificados da sua própria infraestrutura como entradas de trilha de auditoria com carimbos de data/hora e hashes SPKI.

Melhores Práticas: Reforçando o Gerenciamento de Certificados TLS para Servidores de Jogos

  1. Monitore todos os domínios usados pelo seu jogo, não apenas a API principal. Endpoints de telemetria, origens de CDN, beacons de análise e servidores de homologação representam superfície de ataque. Um certificado emitido para um subdomínio esquecido como old-matchmaking.yourgame.com ainda pode ser usado para interceptação se esse domínio resolver para algo acessível.

  2. Implante registros DNS CAA para cada domínio que você controla. Um único registro CAA 0 issue "letsencrypt.org" diz a CAs em conformidade que recusem solicitações de emissão de qualquer outra autoridade. Esta é uma alteração de DNS de cinco minutos que bloqueia uma classe inteira de emissão indevida. Adicione iodef para receber notificações por e-mail quando uma CA rejeitar uma solicitação de emissão por causa da sua política de CAA.

  3. Armazene hashes SPKI dos seus próprios certificados no momento da emissão, não após a implantação. A janela entre o registro do pré-certificado pela CA e o recebimento do certificado final pelo seu sistema é onde vivem os falsos alarmes. Registrar o hash SPKI no momento da geração da chave — antes mesmo de o CSR ser enviado — elimina essa lacuna por completo.

  4. Defina sua cadência de monitoramento para ser mais rápida que seu ciclo de renovação de certificados. Se seus certificados renovam a cada 60 dias, verificar os logs de CT uma vez ao dia dá a você uma latência máxima de detecção de 24 horas. Para backends de jogos em produção, onde tokens de autenticação são o alvo de maior valor, isso é aceitável, mas não ideal. A cada 6 a 12 horas é um ponto ideal prático, dada a latência de indexação do crt.sh.

  5. Integre alertas de CT ao seu canal existente de resposta a incidentes. Monitoramento de CT que envia e-mails para uma caixa de entrada compartilhada que ninguém verifica é pior que inútil — cria falsa confiança. Roteie alertas para o mesmo canal do Slack ou Discord que sua equipe de plantão já monitora para alertas de saúde do servidor. (Isso é distinto dos protocolos gerais de falha de servidor, mas a cadência de resposta deve ser semelhante — sensível ao tempo, documentada e com responsabilidade definida.)

Como o horizOn Lida com o Gerenciamento de Certificados

Rastrear manualmente hashes SPKI, consultar logs de CT, implantar registros CAA e manter um playbook de resposta a incidentes é trabalho de verdade — tipicamente de 2 a 3 semanas de engenharia de infraestrutura para um time pequeno. O horizOn lida com provisionamento e renovação de certificados TLS como parte de sua plataforma de backend para desenvolvedores de jogos, o que significa que certificados emitidos pela plataforma já são rastreados internamente. O lado do monitoramento (ler logs de CT para emissores inesperados) ainda exige ferramentas externas, mas metade do quebra-cabeça — saber quais certificados são seus — é resolvida automaticamente.

Se você está construindo um backend de jogos e quer evitar configurar gerenciamento de certificados, automação de renovação e rastreamento SPKI você mesmo, o horizOn oferece uma base pré-construída para que você possa focar na lógica do jogo em vez de encanamento de PKI.

Próximos Passos

Comece com o script deste post. Aponte-o para os domínios do seu jogo hoje e execute-o manualmente para ver o que já está nos logs de CT da sua infraestrutura. Você pode se surpreender com o volume de certificados históricos — e pelo menos saberá como é sua linha de base antes de começar a automatizar alertas. Em seguida, adicione o rastreamento de hash SPKI para filtrar suas próprias renovações, e você terá um sistema de monitoramento que realmente traz à tona o que importa: certificados que você não esperava, emitidos por CAs que você não escolheu.


Fonte: O monitoramento de Certificate Transparency agora está geralmente disponível