Daftar OWASP Top 10 ada di mana-mana, tetapi sebagian besar liputan memperlakukannya sebagai kategori abstrak daripada masalah rekayasa konkret. Saya mendekati keamanan secara berbeda setelah berpartisipasi dalam kompetisi Capture the Flag PwC pada 2023, di mana saya melihat langsung bagaimana kerentanan teoretis diterjemahkan ke eksploitasi aktual. Saya menjalankan infrastruktur VPS produksi yang diprobing setiap hari (fail2ban memblokir ratusan upaya per hari), dan saya membangun sistem ERP API-first di mana kegagalan keamanan berarti paparan data keuangan nyata.
Kerentanan #1 untuk tiga siklus OWASP berturut-turut. Broken access control berarti pengguna dapat bertindak di luar izin yang dimaksudkan — mengakses catatan pengguna lain, melakukan tindakan admin, atau melihat data yang seharusnya tidak mereka lihat. Bentuk paling umum yang saya temui dalam sistem ERP adalah IDOR (Insecure Direct Object Reference): endpoint API seperti GET /invoices/:id yang tidak memverifikasi pengguna yang meminta memiliki faktur tersebut.
Pola yang saya gunakan di setiap endpoint NestJS ERP: ekstrak pengguna dari JWT dalam guard, lampirkan pengguna ke request, dalam metode layanan selalu filter berdasarkan user_id (atau tenant_id untuk multi-tenant). Jangan pernah mempercayai ID sumber daya dari request body tanpa memverifikasi kepemilikan. Untuk operasi admin, gunakan guard admin terpisah yang memeriksa peran secara eksplisit.
// NestJS: Ownership check decorator pattern
@Injectable()
export class OwnershipGuard implements CanActivate {
constructor(private readonly invoiceService: InvoiceService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest()
const user = request.user
const resourceId = request.params.id
// Always query with user filter — never trust raw ID
const resource = await this.invoiceService.findOne({
where: { id: resourceId, userId: user.id }
})
if (!resource) {
throw new ForbiddenException('Resource not found or access denied')
}
request.resource = resource
return true
}
}
// Security headers in Next.js (next.config.js)
const securityHeaders = [
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
{
key: 'Content-Security-Policy',
value: [
"default-src 'self'",
"script-src 'self' 'unsafe-inline'", // adjust for your needs
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: https:",
"connect-src 'self' https://api.yourdomain.com",
].join('; ')
},
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubDomains; preload'
},
]Dari pengalaman saya mengamankan sistem ERP: implementasikan layanan otorisasi terpusat daripada menyebar pemeriksaan kepemilikan di seluruh metode layanan. Setiap tipe sumber daya (Invoice, Order, Employee) harus memiliki metode canAccess(user, resource) yang memusatkan logika. Ini membuat audit keamanan menjadi mudah — Anda meninjau logika otorisasi di satu tempat.
Kegagalan kriptografi mencakup enkripsi yang tidak memadai, algoritma yang lemah, dan kegagalan manajemen kunci. Dalam praktik: selalu gunakan bcrypt (faktor biaya 12+) untuk hashing password, jangan pernah MD5 atau SHA1. Gunakan TLS 1.2+ di mana-mana. Simpan rahasia dalam variabel lingkungan atau manajer rahasia, jangan pernah dalam kode atau file konfigurasi yang di-commit.
HTTP security header gratis dan membutuhkan 10 menit untuk dikonfigurasi tetapi mencegah seluruh kelas serangan. Header yang saya konfigurasikan di setiap deployment: Content-Security-Policy (mencegah XSS), X-Frame-Options: DENY (mencegah clickjacking), X-Content-Type-Options: nosniff (mencegah MIME sniffing), Strict-Transport-Security (menegakkan HTTPS), Referrer-Policy: strict-origin-when-cross-origin.
Di salah satu server VPS produksi saya, saya menemukan melalui log fail2ban bahwa penyerang telah menemukan file .env yang terekspos di direktori publik. Konfigurasi Nginx memiliki document root yang tidak diatur dengan benar yang menyajikan direktori induk. File .env berisi kredensial database dan kunci API. Untungnya, saya menangkapnya melalui log akses sebelum kredensial disalahgunakan. Segera rotasi semua rahasia.
Miskonfigurasi keamanan adalah temuan paling umum dalam deployment nyata. Dalam daftar periksa pengerasan VPS saya: nonaktifkan login SSH root, gunakan autentikasi kunci SSH saja (PasswordAuthentication no di sshd_config), jalankan fail2ban dengan aturan SSH yang agresif (3 kegagalan = ban 1 jam), nonaktifkan port yang tidak digunakan, hapus blok server nginx default yang mengekspos versi server.
# VPS hardening checklist (Ubuntu 22.04)
# 1. Disable root SSH login
sudo sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo systemctl reload sshd
# 2. Install and configure fail2ban
sudo apt install -y fail2ban
sudo tee /etc/fail2ban/jail.local > /dev/null <<'EOF'
[sshd]
enabled = true
port = ssh
maxretry = 3
bantime = 3600
findtime = 600
[nginx-limit-req]
enabled = true
port = http,https
maxretry = 20
bantime = 86400
EOF
sudo systemctl enable --now fail2ban
# 3. UFW firewall
sudo ufw default deny incoming
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
# 4. Audit with lynis
sudo apt install -y lynis
sudo lynis audit system
# 5. Check for exposed .env files
curl -s https://yourdomain.com/.env | head -3
# Should return 403 or 404, never file contentsKegagalan autentikasi mencakup kata sandi lemah, MFA yang hilang, manajemen sesi yang rusak, dan kerentanan credential stuffing. Yang saya implementasikan: rate limiting pada endpoint login (5 upaya per menit per IP, kemudian lockout 15 menit), bcrypt dengan biaya 12 untuk semua kata sandi, JWT dengan kedaluwarsa access token 15 menit dan refresh token 7 hari disimpan dalam cookie httpOnly.
A09 Kegagalan Logging dan Pemantauan Keamanan: Anda membutuhkan log untuk mendeteksi pelanggaran. Log semua peristiwa autentikasi (sukses dan gagal dengan IP), semua kegagalan otorisasi, semua tindakan admin, dan semua kegagalan validasi input. A10 SSRF: jika aplikasi Anda mengambil URL yang disediakan pengguna, validasi URL terhadap allowlist domain yang diizinkan dan blokir permintaan ke rentang IP privat.
Sumber & Bacaan Lanjutan