A04 Cryptographic Failures
A criptografia raramente é quebrada; ela é pulada, mal configurada ou mal usada. Transporte em texto puro, hashes de senha rápidos e chaves no código são como os dados realmente vazam.
O que é
Uma falha criptográfica é qualquer coisa que expõe dados sensíveis porque a criptografia estava ausente, fraca ou foi usada de forma incorreta: dados enviados sem TLS, senhas armazenadas com um hash rápido, segredos no código-fonte, tokens "aleatórios" previsíveis, algoritmos caseiros ou chaves que nunca são rotacionadas.
É o A04 no :2025. A primeira pergunta é sempre: quais dados são sensíveis, por onde viajam e onde ficam em repouso, e quem pode lê-los ali?
Como o ataque funciona
- Sniffing de rede ou um ataque de downgrade lê o tráfego que não está protegido por TLS moderno.
- O vazamento de um banco de dados entrega senhas com hash MD5 ou SHA-1 (ou sem salt); uma GPU quebra a maioria em horas.
- Tokens construídos a partir de um timestamp ou de um gerador aleatório não criptográfico são previstos e forjados.
- Uma chave commitada em um repositório, ou compartilhada por todos os clientes, decifra tudo de uma vez.
- Modo ECB, nonces reutilizados ou criptografia sem autenticação permitem que o atacante identifique padrões ou modifique o texto cifrado.
Código vulnerável
Um hash rápido e sem salt para senhas e um gerador previsível para um token de redefinição.
import hashlib, random
def store_password(pw):
return hashlib.md5(pw.encode()).hexdigest() # rápido e sem salt
def reset_token():
return str(random.randint(100000, 999999)) # previsívelconst crypto = require("crypto");
const storePassword = (pw) => crypto.createHash("sha1").update(pw).digest("hex");
const resetToken = () => Math.random().toString(36).slice(2);String hash = DigestUtils.md5Hex(password);
String token = String.valueOf(new Random().nextInt(999999));A correção
Use um hash de senha lento, com salt e feito para esse fim (, scrypt ou bcrypt) por meio de uma biblioteca mantida, e obtenha os tokens da fonte aleatória criptográfica do sistema operacional. Não invente algoritmos; não gerencie chaves brutas à mão se uma biblioteca ou um puder fazê-lo.
import secrets
from argon2 import PasswordHasher
ph = PasswordHasher()
def store_password(pw):
return ph.hash(pw) # salt e parâmetros já estão incluídos
def verify_password(stored, pw):
try:
return ph.verify(stored, pw)
except Exception:
return False
def reset_token():
return secrets.token_urlsafe(32) # 256 bits do CSPRNG do SOconst crypto = require("crypto");
const argon2 = require("argon2");
const storePassword = (pw) => argon2.hash(pw, { type: argon2.argon2id });
const verifyPassword = (stored, pw) => argon2.verify(stored, pw);
const resetToken = () => crypto.randomBytes(32).toString("base64url");PasswordEncoder encoder = Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8();
String hash = encoder.encode(password);
boolean ok = encoder.matches(password, hash);
byte[] raw = new byte[32];
new SecureRandom().nextBytes(raw);
String token = Base64.getUrlEncoder().withoutPadding().encodeToString(raw);func ResetToken() (string, error) {
b := make([]byte, 32)
if _, err := rand.Read(b); err != nil { // crypto/rand
return "", err
}
return base64.RawURLEncoding.EncodeToString(b), nil
}Prove a correção
Teste propriedades, não algoritmos: dois hashes da mesma senha são diferentes (salt), o valor armazenado não é um simples hash rápido, os tokens são longos e únicos, e o transporte exige TLS moderno.
def test_hashes_are_salted_and_slow_format():
a, b = store_password("correct horse"), store_password("correct horse")
assert a != b # salt aleatório por hash
assert a.startswith("$argon2id$") # não é hex de md5/sha1
assert verify_password(a, "correct horse")
assert not verify_password(a, "wrong")
def test_reset_tokens_are_long_and_unique():
tokens = {reset_token() for _ in range(1000)}
assert len(tokens) == 1000
assert all(len(t) >= 43 for t in tokens) # 32 bytes, base64url# falhar se o servidor ainda aceitar protocolos legados
testssl.sh --protocols --quiet https://staging.example.com | tee tls.txt
! grep -E 'TLS 1(\.0|\.1)? .*offered' tls.txtChecklist
- Classifique os dados: saiba o que é sensível antes de escolher os controles.
- TLS em todo lugar, apenas versões modernas, HSTS ligado; nenhum dado sensível em URLs.
- Senhas: Argon2id, scrypt ou bcrypt com uma biblioteca mantida; nunca um hash rápido.
- A aleatoriedade para segurança vem do do SO, nunca de Math.random ou random.
- Use (AES-GCM, ChaCha20-Poly1305); nunca reutilize um nonce com a mesma chave.
- As chaves ficam em um KMS ou gerenciador de segredos, são rotacionadas e nunca estão no repositório.
- Não armazene o que não precisa; apague quando terminar.
conexões no mapa
- A04 Cryptographic Failuresprotege as credenciais deA07 Authentication Failures
atualizado em 14/10/2026 · fontes para aprofundar · reportar erro
em outros domínios
- KMS & crypto - chaves e envelopescloudsecchaves e criptografia gerenciadas, sem código próprio
Estude antes
Desbloqueia
teste o que entendeu
Carregando perguntas…