Security ferramentas
As tarefas cotidianas de segurança na engenharia web — hashing, entropia de senhas, claims de JWT, redação de CSP e ocultação de capturas antes de compartilhá-las — e qual ferramenta serve para cada uma.
11 ferramentas
A camada de tarefas rotineiras da segurança web
A maior parte do trabalho de segurança em uma semana normal de engenharia não é
adversarial. É mecânica: escolher um algoritmo de digest, gerar uma credencial
que satisfaça a política de alguém, ler as claims de um token para descobrir por
que a autenticação falhou, escrever um Content-Security-Policy que não quebre o
site, limpar uma captura antes de colá-la em um ticket. Nada disso se parece com
um pentest, e é exatamente aí que os incidentes reais começam — o modo de falha é
um mau hábito, não uma habilidade ausente.
O modelo que previne a maioria desses hábitos é uma divisão em três que as
pessoas colapsam em uma só. Codificação — Base64, percent-encoding, Punycode
— é reversível e não envolve segredo algum; muda a forma dos dados, nunca a sua
confidencialidade. Hashing — SHA-256, SHA-512 — é de mão única e também
não envolve segredo; prova que duas sequências de bytes são idênticas, nada mais.
Operações com chave — HMAC, assinaturas de JWT, TLS — são as únicas que provam
quem produziu algo, e apenas enquanto a chave permanece secreta. Sem chave, sem
autenticação: um blob Base64, um digest nu e um payload de JWT decodificado são
afirmações legíveis sem nada por trás.
O segundo eixo é a direção. Tarefas que emitem política — diretivas de CSP, cabeçalhos, segredos gerados — só estão corretas depois que você verifica o artefato na resposta implantada. Tarefas que inspecionam algo que lhe foi entregue carregam o risco oposto: o que está dentro do artefato. A ocultação de dados pertence a este lado porque a forma usual de segredos saírem de uma empresa é um HAR anexado a um relatório de bug, não um exploit.
O que cada primitiva realmente garante
| Primitiva | Prova | Não fornece | Mau uso comum |
|---|---|---|---|
| Base64 / URL-encoding | Transporte seguro de bytes por canais de texto | Confidencialidade — qualquer um reverte | «Esconder» uma chave de API em um payload |
SHA-256 / SHA-512 | Integridade: mesma entrada, mesmo digest | Sigilo; custo de força bruta em entrada de baixa entropia | Armazenar hashes de senha |
SHA-1 | Compatibilidade com checksums legados | Resistência a colisões (praticamente quebrada) | Assinaturas; deduplicação de entrada hostil |
| HMAC (hash + chave secreta) | Autenticidade enquanto a chave permanece secreta | Confidencialidade — o payload continua legível | Enviar a chave para um navegador |
| Argon2id / bcrypt / scrypt | Armazenamento de senha com sal e deliberadamente lento | Velocidade — a lentidão é o recurso | Trocar por um hash rápido «por performance» |
Assinatura de JWT (HS256, RS256) | Autenticidade do emissor — só após a verificação | Nada, se você apenas decodificar | Confiar nas claims de um payload decodificado |
Content-Security-Policy | Lista de permissões imposta pelo navegador para carregamento de recursos | Uma correção para a injeção; clientes que não são navegadores | 'unsafe-inline' deixado em script-src |
TLS + Strict-Transport-Security | Confidencialidade do transporte; sem downgrade para http | Qualquer afirmação sobre a lógica da aplicação | Ler um cadeado como «o app é seguro» |
Quanta entropia é suficiente
Entropia é comprimento × log2(tamanho do conjunto), então o conjunto importa
tanto quanto o comprimento.
| Conjunto de caracteres | Bits por caractere | 8 caracteres | 14 caracteres | 20 caracteres |
|---|---|---|---|---|
a–z (26) | 4,70 | 38 | 66 | 94 |
a–z0–9 (36) | 5,17 | 41 | 72 | 103 |
a–zA–Z0–9 (62) | 5,95 | 48 | 83 | 119 |
| todos os quatro conjuntos (87) | 6,44 | 52 | 90 | 129 |
Abaixo de 40 bits está quebrado; 80 é o piso para uma conta que importa; um UUID v4 aleatório carrega 122 bits.
Escolher a ferramenta certa
Para impressões digitais, o Gerador de Hash calcula SHA-1,
SHA-256, SHA-384 e SHA-512 de uma vez via Web Crypto, então um digest bate
com echo -n "text" | shasum -a 256 byte por byte — o caminho rápido para
reconciliar um checksum cujo algoritmo ninguém anotou. O MD5 está ausente porque
o Web Crypto não o implementa.
Para segredos que você cria, a pergunta é quem guarda o valor. O
Gerador de Senha serve quando quem guarda é um humano ou um
gerenciador de senhas e um site impõe uma política de comprimento ou de conjunto
de caracteres; ele reporta a entropia ao vivo para o conjunto que você habilitou.
O Gerador UUID serve quando o consumidor é uma máquina e você
quer um identificador opaco sem negociação de conjunto de caracteres. Os dois são
apoiados em CSPRNG — o gerador de senha usa crypto.getRandomValues, o de UUID
usa crypto.randomUUID() — então nenhum recorre a Math.random.
Para tokens, o Decodificador JWT divide
header.payload.signature, formata as duas primeiras partes e renderiza iat,
exp e nbf como ISO 8601 com um veredito de expiração — o suficiente para
resolver «isto está vencido, ou as claims estão erradas?» em uma colagem. Use o
Base64 quando tudo o que você resgatou de um log foi um único
segmento; o Base64url usa - e _, então troque-os por + e / primeiro.
Para política, mantenha a redação e a verificação separadas. O
Gerador CSP monta o cabeçalho a partir de 14 campos, um por
diretiva, sobre uma base endurecida — default-src 'self', object-src 'none',
base-uri 'self', frame-ancestors 'none' — e o hub de CSP vai
diretiva por diretiva. Depois prove que a resposta implantada carrega o cabeçalho
com os Cabeçalhos HTTP, que buscam do lado do servidor e
mostram os cabeçalhos brutos como a origem os enviou. CDNs reescrevem cabeçalhos,
e uma tag <meta> não consegue carregar frame-ancestors.
Antes de compartilhar, o Visualizador HAR lê a sua própria
captura — método, status, tipo MIME, tamanho, tempo por entrada — enquanto o
Sanitizador HAR prepara a cópia que sai da sua máquina,
substituindo cookie, authorization, x-api-key e cabeçalhos semelhantes por
[REDACTED], esvaziando corpos e mascarando parâmetros de consulta que parecem
tokens. Quando o suspeito é uma única URL, o
Parseador de URL decodifica a query string para mostrar se um
token assinado está ali dentro, e o Conversor IDN revela se
um domínio sósia é realmente cirílico na forma xn--.
Tudo isso roda localmente, exceto o verificador de cabeçalhos, que envia a sua
URL para api.sitekits.dev. A seleção para segurança reúne
a maior parte destes em uma página — os de uso geral (UUID, Base64, o
visualizador de HAR) ficam em outros conjuntos por papel; o
hub de privacidade cobre o que o seu navegador vaza.
Pegadinhas que causam incidentes de verdade
Um token decodificado não é um token verificado
Decodificar prova apenas que o Base64url está bem formado. A verificação precisa
da chave do emissor, de um algoritmo fixado e de checagens de exp / nbf /
iss / aud no servidor. Nunca tire o algoritmo do próprio cabeçalho alg do
token — é assim que funcionam o alg: none e a confusão de RS256 para HS256.
Um hash rápido não é armazenamento de senha
Um SHA-256 nu de uma senha é um benchmark de GPU, não uma defesa; sem sal, uma
única rainbow table quebra todos os usuários. Fazer hash para comparar arquivos é
o caso oposto — ali um digest rápido é o correto.
'unsafe-inline' cancela a maior parte do CSP
Ele volta a permitir exatamente o script inline injetado que o CSP existe para
bloquear. Use nonces ou hashes. Um connect-src com curinga é a mesma armadilha
pelo outro lado: a exfiltração continua aberta mesmo com a execução de script
trancada.
Ocultar dados é casamento de padrões, não compreensão
O sanitizador casa com uma lista fixa de cabeçalhos e com nomes de parâmetro que
contenham token, key, secret, password, passwd, pwd, auth,
session, sig ou signature. Uma credencial em um segmento de caminho de
URL, ou chamada de t, sobrevive — e uma contagem de ocultações igual a zero em
uma sessão autenticada é um sinal, não uma aprovação.
A entropia descreve o gerador, não a string
A fórmula só vale quando cada caractere foi sorteado aleatoriamente. P@ssw0rd!2024
tem 13 caracteres e todas as quatro classes, e ainda assim está em toda lista de
palavras de quebra de senha. Só a forma como uma string foi gerada decide se a
pontuação de um medidor significa alguma coisa.