A02 - Cryptographic Failures
Definisi dan Penjelasan
Cryptographic Failures (sebelumnya dikenal sebagai Sensitive Data Exposure di OWASP Top 10 2017) adalah kerentanan yang terjadi ketika aplikasi gagal melindungi data sensitif melalui enkripsi yang tepat. Ini mencakup tidak hanya data dalam perjalanan (data in transit) tetapi juga data yang disimpan (data at rest) serta data yang diproses di memori.
Kriptografi adalah fondasi keamanan data modern. Ketika kriptografi gagal - baik karena algoritma yang lemah, implementasi yang salah, atau manajemen kunci yang buruk - data sensitif seperti password, nomor kartu kredit, data medis, dan token autentikasi menjadi rentan terhadap pencurian dan penyalahgunaan.
Data sensitif yang perlu dilindungi meliputi:
- Data pribadi (PII): nama, alamat, nomor KTP, email
- Data keuangan: nomor kartu kredit, rekening bank, saldo
- Data autentikasi: password, token, session ID
- Data medis: riwayat kesehatan, diagnosa
- Data rahasia bisnis: source code, dokumentasi internal
Dampak Keamanan
| Dampak | Deskripsi |
|---|---|
| Kebocoran Data Massal | Data jutaan pengguna terekspos |
| Pencurian Identitas | Attacker menggunakan data PII untuk penipuan |
| Pelanggaran Regulasi | Denda GDPR, PCI DSS, UU PDP Indonesia |
| Kerusakan Reputasi | Kepercayaan pengguna hilang |
| Kerugian Finansial | Biaya kompensasi, denda, dan pemulihan |
Kerentanan Umum
1. Password Disimpan dalam Bentuk Plaintext
Ini adalah kesalahan paling mendasar. Jika database bocor, semua password pengguna langsung diketahui.
2. Algoritma Hash Lemah
Menggunakan MD5 atau SHA-1 untuk password - algoritma ini bisa di-crack dalam hitungan detik menggunakan GPU.
3. Algoritma Enkripsi Lemah
- DES: 56-bit key - bisa di-crack dalam waktu singkat
- RC4: Rentan terhadap berbagai serangan
- ECB mode: Tidak aman untuk data berulang (pola masih terlihat)
4. JWT dengan Algoritma none
Beberapa library JWT memungkinkan algoritma none, yang
berarti signature tidak diverifikasi.
5. Weak JWT Secret
Menggunakan secret yang lemah untuk HMAC (HS256), mudah ditebak dengan brute force.
6. HTTP (Tanpa HTTPS)
Semua data dikirim dalam plaintext, mudah disadap di jaringan publik (WiFi kafe, airport, dll).
7. Manajemen Kunci Buruk
- Kunci enkripsi hardcoded di source code
- Kunci disimpan di repository publik (GitHub)
- Kunci tidak pernah di-rotate
Contoh Kerentanan (Code Snippets)
Contoh 1: Password Plaintext (Rentan)
# RENTAN - Password disimpan dalam plaintext
def register_user(username, password):
cursor.execute(
"INSERT INTO users (username, password) VALUES (?, ?)",
(username, password) # Password langsung disimpan
)
db.commit()
Contoh 2: Password dengan Hash Kuat (Aman)
# AMAN - Menggunakan bcrypt
import bcrypt
def register_user(username, password):
# Generate salt dan hash password
salt = bcrypt.gensalt()
hashed = bcrypt.hashpw(password.encode('utf-8'), salt)
cursor.execute(
"INSERT INTO users (username, password) VALUES (?, ?)",
(username, hashed)
)
db.commit()
def verify_login(username, password):
cursor.execute("SELECT password FROM users WHERE username = ?", (username,))
stored_hash = cursor.fetchone()[0]
return bcrypt.checkpw(password.encode('utf-8'), stored_hash)
Contoh 3: Hash MD5 untuk Password (Rentan)
# RENTAN - MD5 sangat mudah di-crack
import hashlib
def hash_password(password):
return hashlib.md5(password.encode()).hexdigest()
# Dengan GPU modern, MD5 bisa di-crack ~10 miliar hash/detik
Contoh 4: JWT dengan Algoritma none (Rentan)
# RENTAN - Menerima algoritma 'none'
import jwt
def verify_jwt(token):
# Tanpa menentukan algoritma yang diizinkan
payload = jwt.decode(token, options={"verify_signature": False})
# Attacker bisa membuat token dengan alg: 'none'
return payload
// Attacker membuat token dengan alg: none
{
"alg": "none",
"typ": "JWT"
}
.
{
"sub": "admin",
"role": "admin",
"iat": 1516239022
}
.
(Signature dikosongkan)
Contoh 5: JWT dengan Secret Lemah (Rentan)
# RENTAN - Secret terlalu lemah
JWT_SECRET = "secret123" # Easy to brute force
token = jwt.encode({"role": "admin"}, JWT_SECRET, algorithm="HS256")
Contoh 6: JWT dengan RS256 (Aman)
# AMAN - Menggunakan RSA (RS256) dengan key pair
from cryptography.hazmat.primitives import serialization
import jwt
# Load private key
with open("private.pem", "rb") as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
# Load public key
with open("public.pem", "rb") as f:
public_key = serialization.load_pem_public_key(f.read())
def create_token(user_id, role):
payload = {
"sub": user_id,
"role": role,
"iat": datetime.utcnow(),
"exp": datetime.utcnow() + timedelta(hours=1)
}
return jwt.encode(payload, private_key, algorithm="RS256")
def verify_token(token):
try:
payload = jwt.decode(token, public_key, algorithms=["RS256"])
return payload
except jwt.InvalidTokenError:
return None
Contoh 7: HTTP vs HTTPS
# RENTAN - Tidak ada redirect HTTP ke HTTPS
server {
listen 80;
server_name example.com;
# Data dikirim dalam plaintext
}
# AMAN - Redirect HTTP ke HTTPS + HSTS
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
Cara Eksploitasi (Relevan ke Lab)
1. Crack JWT dengan Secret Lemah
# 1. Dapatkan JWT token dari lab
# 2. Gunakan hashcat atau John untuk crack secret
# 3. Atau gunakan tool jwt_tool
python3 jwt_tool.py <token> -C -d /usr/share/wordlists/rockyou.txt
Atau dengan hashcat:
hashcat -m 16500 jwt.txt /usr/share/wordlists/rockyou.txt
2. Eksploitasi JWT dengan Algoritma none
# Modifikasi JWT
python3 jwt_tool.py <token> -X a
# Atau manual: ubah header menjadi {"alg": "none"}, hapus signature
3. Decode Base64 - Bukan Enkripsi!
# Banyak developer salah mengira base64 adalah enkripsi
echo "dXNlcjpwYXNzd29yZDEyMw==" | base64 -d
# Output: user:password123
4. SSL Stripping (MITM)
Attacker berada di antara client dan server:
1. Client minta HTTPS → Attacker intercept
2. Attacker komunikasi dengan server via HTTPS
3. Attacker komunikasi dengan client via HTTP biasa
4. Client tidak sadar bahwa koneksinya tidak aman
5. Hash Collision / Rainbow Table Attack
MD5(password) → cari di rainbow table → dapat password asli
Solusi: gunakan salt unik per user + bcrypt/argon2
Cara Pencegahan
1. Enkripsi Data di Transit
- Gunakan HTTPS/TLS (TLS 1.2 atau 1.3) untuk semua komunikasi
- Implementasikan HSTS
- Gunakan sertifikat yang valid dari CA terpercaya
- Nonaktifkan protokol usang (SSLv2, SSLv3, TLS 1.0)
2. Enkripsi Data at Rest
- Enkripsi database dengan AES-256
- Enkripsi file backup
- Gunakan enkripsi disk penuh (FDE) untuk server
3. Password Storage yang Aman
# Minimum: bcrypt dengan cost factor >= 12
import bcrypt
password = b"super_secret_password"
salt = bcrypt.gensalt(rounds=12) # cost factor 12
hashed = bcrypt.hashpw(password, salt)
# Atau argon2 (lebih baik)
from argon2 import PasswordHasher
ph = PasswordHasher()
hash = ph.hash("super_secret_password")
ph.verify(hash, "super_secret_password")
4. JWT Best Practices
# Gunakan RS256 atau ES256, bukan HS256
# Set expiration time yang pendek (15-60 menit)
# Jangan simpan data sensitif di payload JWT
# Gunakan library yang secure (PyJWT, node-jsonwebtoken)
5. Manajemen Kunci
# Jangan hardcode kunci di source code!
# Gunakan environment variable atau vault service
env:
- ENCRYPTION_KEY=${ENCRYPTION_KEY}
- JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY}
# Rotasi kunci secara berkala (setiap 90 hari)
# Gunakan HSMs (Hardware Security Module) untuk level enterprise
6. Gunakan Parameterized Query untuk Mencegah SQL Injection
# AMAN: parameterized query mencegah SQLi
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
7. Implementasi CSP (Content Security Policy)
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'";
8. Checklist Keamanan Kriptografi
| Aspek | Rekomendasi |
|---|---|
| Hashing password | bcrypt (cost≥12) / argon2 / scrypt |
| Hashing data umum | SHA-256 / SHA-3 |
| Enkripsi simetris | AES-256-GCM |
| Enkripsi asimetris | RSA-4096 / ECC (Curve25519) |
| JWT signing | RS256 / ES256 |
| TLS | TLS 1.2 / 1.3 |
| Key exchange | ECDHE (Perfect Forward Secrecy) |
CWE Mapping
| CWE | Deskripsi |
|---|---|
| CWE-327 | Use of a Broken or Risky Cryptographic Algorithm |
| CWE-328 | Use of Weak Hash |
| CWE-311 | Missing Encryption of Sensitive Data |
| CWE-312 | Cleartext Storage of Sensitive Information |
| CWE-319 | Cleartext Transmission of Sensitive Information |
| CWE-326 | Inadequate Encryption Strength |
| CWE-522 | Insufficiently Protected Credentials |
| CWE-759 | Use of a One-Way Hash Without a Salt |
| CWE-916 | Use of Password Hash With Insufficient Computational Effort |
Lab Terkait
| Lab | Konsep | Tingkat Kesulitan |
|---|---|---|
| Login API | JWT manipulation, weak secret, alg none | Medium-Hard |
| Metasploitable 2 | Sensitive data exposure, weak encryption | Easy-Medium |
Contoh Konkret dari Lab
Login API (Lab Platform) - JWT Weak Secret
Langkah-langkah:
- Login dengan kredensial yang diberikan
- Capture JWT token dari response
- Buka jwt.io dan paste token
- Jika header menunjukkan
"alg": "HS256", coba crack secretnya - Gunakan tool seperti hashcat atau jwt_tool
# Contoh dengan jwt_tool
python3 jwt_tool.py eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... -C -d wordlist.txt
- Setelah secret ditemukan, buat token baru dengan payload yang dimodifikasi
Login API - JWT Algoritma none
Langkah-langkah:
- Dapatkan JWT token
- Decode header JWT
- Ubah
"alg": "HS256"menjadi"alg": "none" - Ubah payload sesuai keinginan (misal role menjadi admin)
- Buat token baru dengan signature kosong
- Kirim token baru ke server
Metasploitable 2 - Sensitive Data Exposure
- Akses halaman web di Metasploitable 2
- Cari form login atau halaman admin
- Cek view source code - kadang password/komentar sensitif ada di HTML comment
- Coba SQL injection untuk bypass login
- Cek direktori sensitif:
/phpmyadmin,/config,/backup
Kesimpulan
Cryptographic Failures adalah ancaman serius yang dapat mengakibatkan kebocoran data massal dan pelanggaran regulasi. Pencegahan yang efektif dimulai dari kesadaran bahwa kriptografi bukanlah fitur opsional - melainkan fondasi keamanan aplikasi modern. Setiap aplikasi web harus menggunakan HTTPS, password harus di-hash dengan algoritma kuat (bcrypt/argon2), JWT harus menggunakan algoritma asimetris (RS256/ES256), dan kunci kriptografi harus dikelola dengan aman. Ingatlah aturan emas: jangan pernah membuat algoritma kriptografi sendiri - gunakan library yang sudah teruji dan diakui industri.