Pular para o conteúdo

Ameaças e risco

Modelagem de ameaças com STRIDE, superfície de ataque, fronteiras de confiança e de segurança, gestão de risco e políticas.

Modelar ameaças é responder quatro perguntas, nesta ordem: o que estamos construindo, o que pode dar errado, o que vamos fazer, e fizemos um bom trabalho? Pular a primeira é o erro mais comum — sem o desenho do sistema, a lista de ameaças vira uma lista de medos.

STRIDE#

Seis categorias que cobrem praticamente tudo o que se faz contra um sistema. O valor delas é serem exaustivas o bastante para a reunião terminar.

A ameaçaA propriedade que ela violaA resposta aqui
Spoofingfingir ser outroautenticaçãohash_password com scrypt, TOTP, token assinado
Tamperingalterar dado em trânsito ou em repousointegridadeAEAD, HMAC, Seg.auditoria
Repudiationnegar ter feitonão-repúdiotrilha encadeada — e a ressalva sobre chave simétrica
Information disclosurever o que não deviaconfidencialidadeSeg.segredo, redigir, mascarar_pii
Denial of serviceimpedir o uso legítimodisponibilidadelimitador, json_seguro, limite de corpo
Elevation of privilegevirar admin sem serautorizaçãoRBAC por recurso, Arcane.Capacidade

Superfície de ataque#

É a soma de todos os pontos por onde um dado de fora entra no sistema. Reduzi-la é a única medida que melhora todas as outras ao mesmo tempo — o que não existe não pode ser atacado.

Ponto de entradaO que costuma escaparA peça
parâmetro de rota e queryfaixa não conferida, tipo assumidoSeg.numero_seguro
corpo do pedidoJSON fundo demais, corpo giganteSeg.json_seguro, Kiln.limite_de_corpo
cabeçalhoHost e X-Forwarded-For tratados como verdadeconferir contra uma lista
uploadnome com .., extensão, tamanhoKiln.salvar_upload, Seg.nome_de_arquivo_seguro
URL fornecida pelo usuárioSSRF para a rede internaSeg.url_segura
redirecionamento?proximo= para fora do siteSeg.redirecionamento_seguro
arquivo de configuraçãosegredo commitadodataforge seguranca
dependênciapacote trocado numa versão publicadaforge.lock com sha256
dataforge
adopt Arcane.Seguranca as Seg

// A superficie de uma rota, em quatro linhas. Cada uma fecha um
// ponto que um pedido de fora alcanca.
action listar(query):
    pagina := Seg.numero_seguro(query["pagina"] ?? "1", 1, 10000)
    por_pagina := Seg.numero_seguro(query["tamanho"] ?? "20", 1, 100)
    busca := Seg.sem_controle(query["q"] ?? "")
    yield {"pagina": pagina, "tamanho": por_pagina, "busca": busca}

assert listar({"pagina": "3"})["pagina"] is 3
assert listar({})["tamanho"] is 20

// '?tamanho=999999999' derruba a listagem, e passa por qualquer
// conversao que nao confira a faixa.
monitor:
    listar({"tamanho": "999999999"})
    assert no
handle UnsafeInputError as e:
    out "recusado antes de chegar ao banco"

Fronteira de confiança, fronteira de segurança#

São conceitos diferentes e a confusão entre eles custa caro. Uma fronteira de confiança é onde o nível de confiança muda — o dado atravessa e passa a ser suspeito. Uma fronteira de segurança é onde existe um mecanismo que obriga a separação.

FronteiraTipoO que ela garante
navegador → servidorconfiança e segurançaprocessos e máquinas diferentes
processo → processoambaso sistema operacional isola a memória
Arcane.Capacidadesó de confiançarecusa o adopt; não tira o que já foi entregue
thread → threadnenhumamemória compartilhada; nada isola
validação de entradasó de confiançadepende de quem escreveu chamar a função

Gestão de risco#

Risco é probabilidade × impacto, e o ponto de fazer a conta é ordenar — não há orçamento para tratar tudo. As quatro respostas possíveis são sempre as mesmas.

RespostaQuandoExemplo
Mitigaro controle custa menos que o dano esperadolimite de taxa no login
Transferiroutro faz melhor e responde por issoTLS no Caddy; pagamentos num PSP
Evitara funcionalidade não paga o risconão guardar o número do cartão
Aceitarresidual pequeno, e registradoo .deb não é assinado; está escrito

Políticas#

Uma política que ninguém consegue verificar é um documento. As que funcionam viram verificação automática — e o lugar delas é a esteira de CI.

dataforge
// Uma politica executavel: a esteira reprova o que a
// politica proibe, e ninguem precisa lembrar de conferir.

// 1. Nenhum segredo entra no repositorio.
//    $ dataforge seguranca . --strict

// 2. O analisador nao deixa passar erro.
//    $ dataforge check . --strict

// 3. Estilo e higiene.
//    $ dataforge lint .

// 4. A suite inteira, com piso de cobertura.
//    $ dataforge test tests/ --cobertura --minimo=80

// 5. A superficie nao quebrou sem o bump correspondente.
//    $ dataforge abi antes.df depois.df
PolíticaO comando que a cobra
segredo nunca entra no repositóriodataforge seguranca . --strict
nenhum erro do analisadordataforge check . --strict
cobertura mínimadataforge test --cobertura --minimo=80
a versão sobe quando a superfície quebradataforge abi
as dependências são as do lockfiledataforge install