◇ OpenCyber Academy
Engenharia · Capítulo 36 · Português

Capítulo 36 — Segurança ofensiva autorizada e red team: desempenho e escala

Ensino gratuito e aberto para quem deseja proteger pessoas e tecnologias. Não é preciso criar uma conta para estudar ou consultar as respostas.

Capítulo 36 — Segurança ofensiva autorizada e red team: desempenho e escala

Mapa da aula

Aula 36 publicada. Mapa, exemplo, EX106.

flowchart TD
  N0["36.2 Token buckets"]
  N1["36.3 Canários"]
  N2["36.2b Justiça entre métodos"]
  N3["36.3b Orçamentos de latência"]
  N4["36.1b Aquecimento e resfriamento"]
  N5["Nota de prática"]
  N6["36.4b Testes de carga que respeitam o cliente"]
  N7["Síntese"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
  N7 --> EX["Exemplo resolvido"]
  EX --> Q["Exercício EX106"]

Desenho lógico

flowchart LR
  N0["36.2 Token buckets"]
  N1["36.3 Canários"]
  N2["36.2b Justiça entre métodos"]
  N3["36.3b Orçamentos de latência"]
  N4["36.1b Aquecimento e resfriamento"]
  N5["Nota de prática"]
  N6["36.4b Testes de carga que respeitam o cliente"]
  N7["Síntese"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX106"]
[36.2 Token buckets]
    |
    v
[36.3 Canários]
    |
    v
[36.2b Justiça entre métodos]
    |
    v
[36.3b Orçamentos de latência]
    |
    v
[36.1b Aquecimento e resfriamento]
    |
    v
[Nota de prática]
    |
    v
[36.4b Testes de carga que respeitam o cliente]
    |
    v
[Síntese]
    |
    v
[Exemplo resolvido] --> [Exercício EX106]

Objetivos de aprendizagem

Você vai (1) dimensionar scanners sob os limites de taxa da ROE; (2) aplicar token buckets; (3) medir o impacto no cliente com um canário.

36.1 Limites de taxa são de primeira classe

Metas de vazão que ignoram a ROE são bugs. Dimensione os pools de workers para que o token bucket seja o gargalo, não uma tempestade surpresa de 429.

"""Lab R: token-bucket limits against unbounded consumption (synthetic).
Simulates 60 seconds of requests from a normal client and a flooding client
against a model endpoint with a per-client token bucket."""
import random
rng = random.Random(4)
def simulate(rate_per_s, burst, reqs):
    tokens, last, ok = burst, 0.0, 0
    for t in reqs:
        tokens = min(burst, tokens + (t - last) * rate_per_s); last = t
        if tokens >= 1: tokens -= 1; ok += 1
    return ok
normal = sorted(rng.uniform(0, 60) for _ in range(90))
flood = sorted(rng.uniform(0, 60) for _ in range(3000))
for rate, burst in ((5, 20), (2, 10), (1, 5)):
    print(f"limit={rate}/s burst={burst:2d} normal_served={simulate(rate, burst, normal):3d}/90 "
          f"flood_served={simulate(rate, burst, flood):4d}/3000")

Saída esperada:

limit=5/s burst=20 normal_served= 90/90 flood_served= 319/3000
limit=2/s burst=10 normal_served= 90/90 flood_served= 129/3000
limit=1/s burst= 5 normal_served= 62/90 flood_served=  64/3000

Se o pool de workers puder enviar mais rápido do que a ROE permite, a primeira manhã movimentada vai derrubar a API de tarifas do cliente. Fazer do token bucket o gargalo significa que um bug que crie workers extras ainda não consegue ultrapassar a taxa assinada. Sam dimensiona os pools a partir do bucket e depois prova isso com uma inundação sintética que continua cortada enquanto um cliente normal segue em frente. O tamanho do pool fica guardado ao lado das taxas do bucket, para que um engenheiro depois não possa aumentar os workers sem ver os números da ROE.

36.2 Token buckets

Capacidade = rajada; reposição = taxa sustentada. O laboratório mostra que clientes que inundam são cortados enquanto clientes normais seguem. A capacidade de rajada cobre picos legítimos curtos; a taxa de reposição é a promessa sustentada na ROE. O cliente de inundação do laboratório batendo no corte enquanto um cliente normal segue é o comportamento que Sam quer no enlace da garagem. Ele imprime os dois números no slide do kickoff, ao lado dos valores de 5/s e rajada de 20 do caso Riverstone. Mudar qualquer um dos números exige o mesmo caminho de autorização de uma edição da ROE, não um envio silencioso de configuração.

36.3 Canários

Uma requisição canário sintética a cada minuto acompanha a latência/taxa de erros; as condições de parada disparam no limite (Capítulo 33). Um canário a cada minuto é um sensor para o laço de parada, não um troféu de desempenho. Quando a latência ou os erros cruzam o limite, a parada dispara antes que os passageiros percebam uma compra de passagem lenta. Sam amarra o limite do canário às mesmas condições de parada já codificadas para listas de exclusão e arquivos de interruptor de emergência.

Caso sintético — Riverstone Transit. O bucket de 5/s com rajada de 20 manteve a API de tarifas abaixo de 5% da capacidade durante a janela.

36.4 Erros e limites

Scanners distribuídos precisam de um bucket global coordenado, ou multiplicam o limite por N. Cinco scanners, cada um obedecendo a um limite local de 5/s, são um ataque de 25/s do ponto de vista do cliente. Um bucket global, ou um único agendador que distribui os tokens, é obrigatório quando os métodos rodam em mais de um host. Sam reprova uma revisão de desenho que não saiba dizer onde fica o contador global. O desenho do ano passado, que confiava em arquivos por host, foi rejeitado quando cinco jump hosts entraram no pool.

36.2b Justiça entre métodos

Quando vários métodos compartilham um bucket, um enumerador barulhento pode deixar sem recursos uma revisão de configuração silenciosa. Dê pesos aos buckets ou separe-os por classe de método, para que o trabalho silencioso autorizado ainda termine dentro da janela. Um enumerador barulhento que esvazia um bucket compartilhado deixa a revisão de configuração autenticada sem recursos até o fim da janela. Buckets separados por classe de método, ou pesos que reservam um mínimo para o trabalho silencioso, impedem que as verificações silenciosas autorizadas pela ROE sejam vítimas da varredura de outra pessoa. O agendador de Sam mostra os tokens restantes por classe no painel do líder.

36.3b Orçamentos de latência

Distribua os milissegundos entre DNS, TCP, TLS, predicado e escrita do evento. Quando o orçamento estoura, descarte trabalho; não pule o predicado. Publique o orçamento no runbook, para que as otimizações tenham uma régua. Pular o predicado para "caber no orçamento" é como a falha aberta volta sob um ticket de desempenho. Descartar trabalho de descoberta é permitido; descartar a decisão de permitir/negar, não. Sam publica a divisão em milissegundos no runbook, para que uma mudança guiada por profiler tenha uma régua e um veto. Um pull request que tirou do orçamento o tempo de escrita do evento para "parecer mais rápido" foi fechado com um link para esta regra.

36.1b Aquecimento e resfriamento

Aumente o tráfego aos poucos no início da janela e drene antes da parada definitiva. Inícios instantâneos em taxa máxima parecem inundações para os defensores e disparam alertas não relacionados. Codifique a rampa no agendador, não como conhecimento tribal. Taxa máxima instantânea no minuto zero dispara detectores de inundação que o engajamento nunca pretendeu testar. Fazer a rampa no agendador, e drenar antes da parada definitiva, impede que os defensores da Riverstone acionem alertas numa janela assinada. Sam codifica a rampa como configuração ao lado das taxas do bucket, não como uma nota no chat.

Nota de prática

Publique uma nota sobre a economia dos limites de taxa: custo de esperar versus custo de uma queda no cliente. A maioria dos argumentos para aumentar os limites da ROE se dissolve quando o custo da queda é escrito. Mantenha a nota ao lado da configuração do token bucket, para que o próximo debate de otimização comece com números.

Buckets separados para métodos silenciosos e barulhentos, para que um enumerador faminto não deixe sem recursos o trabalho de revisão de configuração.

36.4b Testes de carga que respeitam o cliente

Os testes de desempenho do TrackScope e dos executores de métodos usam só alvos sintéticos. As taxas medidas ali viram o teto permitido nos engajamentos, sempre abaixo do limite acordado com o cliente, para que ganhos de velocidade nunca se traduzam em mais tráfego nos sistemas do cliente do que foi assinado. Uma construção do TrackScope que ficou mais rápida não pode, em silêncio, mandar mais pacotes contra a API de tarifas do que a ROE de segunda-feira permitia. O relatório de teste de carga de Sam lista os dois números lado a lado antes de qualquer aumento do tamanho do pool. Se os dois números chegarem a se cruzar, o teto fica no limite do cliente e a velocidade extra fica sem uso.

Exercícios

Síntese

Bucket primeiro, escala depois, canário sempre.

Continue estudando — capítulo 36 de 50

← Capítulo 35 (rascunho) · Índice de capítulos do curso · Capítulo 37 (rascunho) →