🛡️ Sesi 13 dari 16 — QA Cerdas

Security Testing Cerdas
OWASP, SAST/DAST & AI Fuzzing

Keamanan bukan sekadar patch rutin — ini tentang membangun sistem yang resisten terhadap serangan sejak hari pertama. AI mempercepat dan memperkuat setiap lapisan security testing.

🚫 OWASP Top 10 2021
🔍 SAST & DAST Otomatis
🤖 AI-Powered Fuzzing
3 × 50 menit
🚫 Bagian 1 — Mengapa Security Testing Kritis?

Biaya Melindungi vs Biaya Diserang

💡 ANALOGI — Gembok vs Biaya Kemalingan

Memasang gembok pintu rumah mungkin biaya Rp100.000. Jika rumah dibobol dan barang senilai Rp50 juta dicuri, ditambah trauma dan reputasi, biayanya ribuan kali lipat. Security testing seperti memasang gembok, alarm, kamera — mahal dibanding tidak ada, tapi murah dibanding akibat pencurian.

Rata-rata biaya data breach global tahun 2023: USD 4.45 juta per insiden (IBM Cost of Data Breach Report). Bandingkan dengan biaya investasi security testing tahunan yang jauh lebih kecil.

4.45M
USD rata-rata biaya data breach 2023 (IBM)
277
hari rata-rata waktu untuk mendeteksi dan menghentikan breach
82%
breach yang melibatkan elemen human error atau rekayasa sosial
📋 Bagian 2 — OWASP Top 10 2021

Sepuluh Kategori Kerentanan Paling Berbahaya

💡 ANALOGI — Daftar 10 Penyakit Paling Mematikan

WHO menerbitkan daftar penyakit paling mematikan agar rumah sakit memprioritaskan pencegahan dan penanganannya. OWASP Top 10 adalah "daftar penyakit paling mematikan" untuk aplikasi web — diterbitkan setiap beberapa tahun berdasarkan data serangan nyata dari ribuan organisasi. Setiap developer wajib mengenal dan tahu cara mencegah kerentanan ini.

A01
Broken Access Control
Pengguna bisa mengakses resource yang bukan haknya. Naik dari #5 ke #1 di 2021.
GET /api/users/1234/data → user lain bisa akses dengan ID 1235
A02
Cryptographic Failures
Password disimpan plaintext, data sensitif tidak dienkripsi, algoritma lemah (MD5, SHA1).
password = "admin123" disimpan di DB tanpa hash
A03
Injection (SQL, Command, LDAP)
Input user disertakan langsung dalam query atau command tanpa sanitasi. Bisa merusak/bocorkan seluruh database.
SELECT * FROM users WHERE id = '{user_input}'
A04
Insecure Design
Kelemahan fundamental di level arsitektur dan desain — tidak bisa diperbaiki hanya dengan patch kode.
Reset password hanya via pertanyaan keamanan yang mudah ditebak
A05
Security Misconfiguration
Default credentials aktif, error messages terlalu verbose, port tidak perlu terbuka, debug mode aktif di production.
X-Powered-By: PHP/7.4.3 — mengekspos versi dengan CVE
A06
Vulnerable & Outdated Components
Library, framework, OS dengan CVE yang diketahui tapi tidak di-update. Log4Shell menyerang A06.
log4j 2.14.1 — vulnerable to Log4Shell (CVE-2021-44228)
A07
Identification & Authentication Failures
Brute force tidak diblokir, session tidak expire, JWT tidak divalidasi dengan benar.
Tidak ada rate limiting di /api/login — bisa brute force tanpa batas
A08
Software & Data Integrity Failures
CI/CD pipeline tidak divalidasi, auto-update tanpa verifikasi signature, insecure deserialization.
SolarWinds attack: update software yang sudah terinfeksi backdoor
A09
Security Logging & Monitoring Failures
Login gagal tidak di-log, alert tidak dikonfigurasi, log mudah dihapus attacker setelah intrusi.
277 hari rata-rata breach tidak terdeteksi karena logging buruk
A10
Server-Side Request Forgery (SSRF)
Attacker membuat server melakukan request ke internal network yang tidak seharusnya diakses dari luar.
url=http://169.254.169.254/metadata → akses AWS metadata internal
🔍 Bagian 3 — SAST, DAST, dan IAST

Tiga Pendekatan Analisis Keamanan Kode

💡 ANALOGI — Inspeksi Bangunan

SAST seperti insinyur yang memeriksa blueprint dan struktur bangunan di atas kertas sebelum dibangun — menemukan kelemahan tanpa perlu masuk ke dalam. DAST seperti penyusup yang mencoba masuk ke gedung yang sudah jadi — menguji pertahanan nyata dengan serangan simulasi. IAST seperti sensor di dalam gedung yang merekam semua pergerakan saat bangunan digunakan — menemukan kelemahan dari dalam saat runtime.

AspekSAST (Static)DAST (Dynamic)IAST (Interactive)
Kapan berjalanSaat coding / commit, tanpa menjalankan aplikasiSaat aplikasi berjalan di staging/test envSaat integration/QA testing (runtime)
Apa yang dianalisisSource code, bytecode, binaryHTTP request/response, live applicationData flow internal aplikasi saat runtime
False positiveTinggi — tidak tahu runtime contextRendah — hanya lapor kerentanan yang benar-benar bisa dieksploitasiSangat rendah — tahu persis konteks eksekusi
Cakupan OWASPA02, A03, A05, A06 sangat bagusA01, A03, A07 sangat bagusA03, A04, A08 sangat bagus
Tools populerSonarQube, Semgrep, Bandit (Python), CheckmarxOWASP ZAP, Burp Suite, Nikto, NucleiContrast Security, Seeker, Hdiv
Kapan gunakanDi setiap commit — integrasi ke CI/CD pipelineSebelum release, pentest regulerSaat QA testing berlangsung

SAST dengan Semgrep (Python)

Semgrep menggunakan pattern matching berbasis AST (Abstract Syntax Tree) untuk mendeteksi pola kode berbahaya. Sangat cepat, bisa dikustomisasi dengan rules sendiri.

# Contoh rule Semgrep: deteksi SQL injection
rules:
- id: sql-injection-risk
  pattern: |
    cursor.execute("..." + $VAR + "...")
  message: SQL injection risk
  severity: ERROR

DAST dengan OWASP ZAP

ZAP (Zed Attack Proxy) adalah tool DAST open source paling populer. Bisa dijalankan dalam mode headless via API untuk integrasi CI/CD.

# Jalankan ZAP headless scan
docker run -t owasp/zap2docker-stable \
  zap-baseline.py \
  -t https://siakad.istn.ac.id \
  -r zap-report.html \
  -I —auto-detect-vulnerability
🤖 Bagian 4 — AI-Powered Security Fuzzing

Fuzzing yang Belajar dari Setiap Serangan

💡 ANALOGI — Pencuri yang Makin Pintar

Fuzzing tradisional: Seperti pencuri yang mencoba ribuan kunci secara acak satu per satu — cepat jika kunci yang dicari sederhana, tapi lambat untuk kunci yang kompleks.

AI fuzzing: Seperti pencuri yang belajar — setiap kunci yang hampir berhasil dieksplorasi lebih lanjut, setiap kunci yang jelas salah dibuang. AI fuzzer seperti AFL++ dan LibFuzzer menggunakan code coverage sebagai feedback untuk secara cerdas memilih input berikutnya yang paling mungkin menemukan bug baru.

LANGKAH 1
Seed Corpus — Input Awal
Kumpulkan contoh input valid dari traffic produksi, dokumentasi API, atau dibuat manual. Ini menjadi titik awal mutasi.
LANGKAH 2
Mutation Strategy — Variasikan Input
Mutasi: flip bits, insert/delete bytes, inject payload SQL/XSS, ubah angka ke boundary values. AI belajar mutasi mana yang "menarik" berdasarkan coverage.
LANGKAH 3
Coverage Feedback — Evaluasi Efektivitas
Setelah setiap input dijalankan, ukur branch coverage baru yang dicapai. Input yang membuka cabang baru dimasukkan ke corpus — input yang tidak ada cabang baru dibuang.
LANGKAH 4
Crash & Bug Detection
Jika program crash, hang, atau berperilaku abnormal — input tersebut disimpan sebagai "interesting case" untuk dianalisis dan dijadikan regression test.

🤖 AI Fuzzing Tools Modern

AFL++ (American Fuzzy Lop)
Coverage-guided fuzzer paling populer. Menggunakan genetic algorithm. Untuk C/C++ programs.
LibFuzzer (LLVM)
In-process fuzzer dari Google/LLVM. Sangat cepat, digunakan di Chrome, Firefox, OpenSSL.
Atheris (Google)
Coverage-guided fuzzer untuk Python. Menemukan bug di library Python dan native extensions.
RESTler (Microsoft)
Fuzzer untuk REST API. Membaca OpenAPI spec dan membuat test sequences yang valid tapi edge-case.
OSS-Fuzz (Google)
Platform fuzzing gratis untuk open source projects. Sudah menemukan 10.000+ bugs di 500+ proyek.
🛡️ Bagian 5 — DevSecOps: Security di Setiap Tahap

Security Bukan Gerbang Akhir, tapi Benang yang Menyulam Pipeline

💡 ANALOGI — Bahan Makanan vs Pemeriksaan Akhir

DevOps tanpa security: Seperti restoran yang memeriksa keamanan makanan hanya di meja kasir — terlambat, mahal untuk diperbaiki, dan sering terlewat.

DevSecOps: Seperti memeriksa kualitas bahan di pasar, kebersihan dapur saat memasak, standar sajian sebelum ke meja, dan feedback dari tamu — keamanan ada di setiap langkah. Masalah ditemukan lebih awal = biaya perbaikan jauh lebih murah.

📝
Plan
Threat Modeling, STRIDE
🔍
Code + SAST
Semgrep, Bandit, SonarQube
📦
Build + SCA
Snyk, OWASP Dep-Check
💥
Test + DAST
ZAP, Burp Suite, Nuclei
🔗
Deploy + IaC Scan
Checkov, TFSec, Trivy
📊
Monitor + WAF
AWS WAF, ModSecurity, RASP

SCA (Software Composition Analysis): Analisis dependensi open source untuk menemukan CVE yang diketahui. Tools seperti Snyk dan OWASP Dependency-Check secara otomatis mengecek apakah library yang digunakan memiliki kerentanan yang sudah dipublikasi.

🥷 Bagian 6 — Threat Modeling dengan STRIDE

Berpikir Seperti Penyerang sebelum Mereka Menyerang

Framework STRIDE

STRIDE (Microsoft) membantu mengidentifikasi ancaman secara sistematis dengan memetakan setiap komponen sistem ke 6 kategori ancaman.

S — Spoofing Identity
Attacker berpura-pura jadi pengguna lain. Mitigasi: MFA, JWT yang kuat, session validation.
T — Tampering
Modifikasi data di transit atau storage. Mitigasi: HTTPS, HMAC signature, database integrity constraints.
R — Repudiation
Pengguna menyangkal melakukan tindakan. Mitigasi: audit log yang tidak bisa dimodifikasi, digital signature.
I — Information Disclosure
Kebocoran data sensitif. Mitigasi: enkripsi at-rest dan in-transit, masking PII, principle of least privilege.
D — Denial of Service
Buat layanan tidak tersedia. Mitigasi: rate limiting, auto-scaling, CDN, circuit breaker.
E — Elevation of Privilege
Mendapatkan akses lebih tinggi dari yang seharusnya. Mitigasi: RBAC, principle of least privilege, input validation.
🐍 Bagian 7 — Praktik: Security Scanner Sederhana

Implementasi SAST Ringan & SQL Injection Detector

Mini Security Scanner — SAST Pattern Detection + Secure Coding Demo Python · re · ast · bandit-style
# ================================================================
# S11409 - Sesi 13: Security Testing Cerdas
# Mini SAST Scanner + Secure Coding Patterns
# Dosen: Riadi Marta Dinata, S.Ti., M.Kom. | ISTN Jakarta
# ================================================================

import re, ast, hashlib, hmac, secrets
from dataclasses import dataclass
from typing import List, Tuple

# ── BAGIAN 1: MINI SAST SCANNER ──────────────────────────────
@dataclass
class SecurityFinding:
    severity: str   # CRITICAL / HIGH / MEDIUM / LOW
    rule_id:  str
    message:  str
    line:     int
    code:     str

class MiniSASTScanner:
    """
    Scanner SAST ringan berbasis pattern matching.
    Mendeteksi pola kode berbahaya sesuai OWASP Top 10.
    """
    RULES = [
        # A03: SQL Injection
        ("CRITICAL", "A03-SQLi",
         r'(execute|query)\s*\(["\'][^"\']*["\'\+]\s*\w',
         "SQL query dengan string concatenation — risiko SQL Injection"),
        # A02: Hardcoded credentials
        ("CRITICAL", "A02-HardCred",
         r'(password|passwd|secret|api_key)\s*=\s*["\'][^"\']{6,}["\']',
         "Hardcoded credential — jangan commit ke repository!"),
        # A02: Weak hashing
        ("HIGH", "A02-WeakHash",
         r'\b(md5|sha1)\s*\(',
         "Algoritma hash lemah (MD5/SHA1) — gunakan bcrypt atau SHA-256+"),
        # A05: Debug mode
        ("HIGH", "A05-Debug",
         r'DEBUG\s*=\s*True',
         "Debug mode aktif — jangan di production!"),
        # A03: Command injection
        ("CRITICAL", "A03-CMDi",
         r'(os\.system|subprocess\.call|eval|exec)\s*\([^)]*\+',
         "Potensi command/code injection"),
        # A05: Sensitive data in URL
        ("MEDIUM", "A09-URLParam",
         r'(password|token|secret)=["\']?\w',
         "Data sensitif di URL parameter — gunakan body/header"),
        # A02: No SSL verification
        ("MEDIUM", "A02-NoSSL",
         r'verify\s*=\s*False',
         "SSL verification dinonaktifkan — rentan MITM attack"),
        # A07: No rate limiting hint
        ("LOW", "A07-NoLimit",
         r'def\s+(login|authenticate|signup)\s*\(',
         "Fungsi auth terdeteksi — pastikan ada rate limiting"),
    ]

    def scan_code(self, code: str, filename="") -> List[SecurityFinding]:
        findings = []
        lines = code.split('\n')
        for line_num, line in enumerate(lines, 1):
            for severity, rule_id, pattern, message in self.RULES:
                if re.search(pattern, line, re.IGNORECASE):
                    findings.append(SecurityFinding(
                        severity=severity, rule_id=rule_id,
                        message=message, line=line_num,
                        code=line.strip()
                    ))
        return findings

    def report(self, findings: List[SecurityFinding], filename: str):
        if not findings:
            print(f"  [OK] {filename}: No security issues found!")
            return
        sev_order = {"CRITICAL": 0, "HIGH": 1, "MEDIUM": 2, "LOW": 3}
        findings.sort(key=lambda f: sev_order.get(f.severity, 9))
        print(f"\n  Security scan: {filename}")
        print(f"  Found {len(findings)} issue(s)\n")
        for f in findings:
            icon = {"CRITICAL":"!!","HIGH":"! ","MEDIUM":"* ","LOW":"- "}
            print(f"  [{icon.get(f.severity,'?')}] [{f.severity:<8}] Line {f.line} | {f.rule_id}")
            print(f"      {f.message}")
            print(f"      Code: {f.code[:70]}")
            print()

# ── BAGIAN 2: VULNERABLE CODE CONTOH ─────────────────────────
VULNERABLE_CODE = '''
import sqlite3, hashlib, os

DEBUG = True
API_KEY = "sk-prod-abc123xyz789secret"

def login(username, password):
    conn = sqlite3.connect("siakad.db")
    # VULNERABLE: SQL Injection!
    query = "SELECT * FROM users WHERE username = '" + username + "'"
    result = conn.execute(query)

    # VULNERABLE: MD5 hash yang lemah!
    hashed = hashlib.md5(password.encode()).hexdigest()
    return result.fetchone()

def reset_password(token, new_password):
    # VULNERABLE: SSL verification off!
    import requests
    requests.post("https://api.istn.ac.id/reset",
                  data={"token": token, "password": new_password},
                  verify=False)
'''

# ── BAGIAN 3: SECURE CODE YANG BENAR ─────────────────────────
def secure_login_demo(username: str, password: str) -> dict:
    """
    Demonstrasi secure coding practices:
    1. Parameterized query (anti SQL injection)
    2. bcrypt / hashlib.pbkdf2 (secure password hashing)
    3. Constant-time comparison (anti timing attack)
    """
    import sqlite3, hashlib, os

    # SECURE: Parameterized query — tidak bisa di-inject
    # conn.execute("SELECT * FROM users WHERE username = ?", (username,))

    # SECURE: PBKDF2 dengan salt acak — jauh lebih kuat dari MD5
    salt   = os.urandom(32)
    key    = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100_000)
    stored = salt + key   # simpan keduanya bersama

    # SECURE: Verifikasi dengan hmac.compare_digest (constant-time)
    # Mencegah timing attack yang bisa menebak password karakter per karakter
    test_key = hashlib.pbkdf2_hmac('sha256', password.encode(),
                                    stored[:32], 100_000)
    is_valid = hmac.compare_digest(key, test_key)

    # SECURE: Generate secure token untuk session
    session_token = secrets.token_urlsafe(32)

    return {
        "authenticated": is_valid,
        "session_token": session_token,
        "note": "Token hanya berlaku 30 menit, rotasi setelah digunakan"
    }

def validate_input_demo(user_input: str) -> Tuple[bool, str]:
    """Input validation untuk mencegah injection"""
    # Whitelist approach: hanya izinkan karakter yang diharapkan
    import re
    if not re.match(r'^[a-zA-Z0-9._@-]{3,50}$', user_input):
        return False, "Input tidak valid — hanya huruf, angka, . _ @ - diperbolehkan"
    # Sanitize: escape karakter HTML untuk mencegah XSS
    sanitized = (user_input
                 .replace('&', '&')
                 .replace('<', '<')
                 .replace('>', '>')
                 .replace('"', '"'))
    return True, sanitized


# ── MAIN ──────────────────────────────────────────────────────
print("=" * 60)
print("    SECURITY TESTING DEMO")
print("    S11409 ISTN Jakarta | Sesi 13")
print("=" * 60)

scanner = MiniSASTScanner()

print("\n[1] SAST Scan — Vulnerable Code:")
findings = scanner.scan_code(VULNERABLE_CODE, "siakad_auth.py")
scanner.report(findings, "siakad_auth.py")

print("[2] Secure Coding Demo:")
result = secure_login_demo("mahasiswa@istn.ac.id", "P@ssw0rd123")
print(f"  Authenticated : {result['authenticated']}")
print(f"  Session token : {result['session_token'][:20]}...")

print("\n[3] Input Validation:")
test_inputs = [
    "riadi.marta@istn.ac.id",
    "'; DROP TABLE users; --",
    "",
    "NIM_2024001",
]
for inp in test_inputs:
    valid, result = validate_input_demo(inp)
    status = "SAFE" if valid else "BLOCKED"
    print(f"  [{status}] {inp[:40]:<40} -> {result[:30]}")

print("\nDone! Security scan selesai.")
KUIS SESI 13

Uji Pemahaman Anda

Soal 1 — OWASP Identification

Identifikasi kategori OWASP Top 10 untuk setiap skenario berikut: (a) SIAKAD menampilkan stack trace PHP lengkap saat error, (b) mahasiswa bisa akses nilai mahasiswa lain dengan mengubah angka di URL, (c) library Symfony versi lama yang punya CVE terkenal masih digunakan, (d) form login tidak memiliki CAPTCHA atau rate limiting sama sekali.

Soal 2 — SQL Injection

Kode PHP berikut: $query = "SELECT * FROM mahasiswa WHERE nim = '" . $_GET['nim'] . "'"; (a) Jelaskan bagaimana attacker bisa mengeksploitasi ini untuk mengeluarkan semua data tabel, (b) Tulis versi yang aman menggunakan prepared statement, (c) Bagaimana SAST tool mendeteksi pattern ini tanpa menjalankan kode?

Soal 3 — SAST vs DAST

Tim dev SIAKAD berencana menambahkan security testing ke pipeline CI/CD. Buat rekomendasi: (a) Tool SAST apa yang cocok untuk codebase PHP dan Python? (b) Di tahap mana CI/CD pipeline SAST dan DAST dijalankan? (c) Bagaimana menangani false positive SAST yang tinggi tanpa mengabaikan peringatan penting?

Soal 4 — Threat Modeling STRIDE

Lakukan threat modeling STRIDE untuk fitur "Upload Foto Profil Mahasiswa" di SIAKAD: untuk setiap 6 kategori STRIDE, identifikasi (a) ancaman yang relevan, (b) dampak jika berhasil dieksploitasi, dan (c) mitigasi yang harus diimplementasikan.

Soal 5 — Python Challenge

Perluas MiniSASTScanner di atas: (a) Tambahkan rule untuk mendeteksi XSS — output HTML tanpa escaping, (b) Tambahkan rule untuk mendeteksi hardcoded IP address atau URL production di kode, (c) Implementasikan severity scoring — hitung risk score total file (CRITICAL=10, HIGH=7, MEDIUM=4, LOW=1) dan tentukan apakah file "PASS", "WARN", atau "FAIL" berdasarkan skor.

Rangkuman Kunci Sesi 13

OWASP Top 10 adalah referensi wajib — A01 Broken Access Control, A03 Injection, dan A02 Cryptographic Failures adalah prioritas utama untuk sistem akademik

SAST menemukan bug lebih awal dan murah; DAST membuktikan kerentanan yang bisa dieksploitasi — gunakan keduanya, bukan pilih salah satu

AI fuzzing menggunakan coverage feedback untuk secara cerdas mengeksplorasi state space program — jauh lebih efektif dari random fuzzing

DevSecOps bukan "security di akhir" — setiap tahap pipeline punya tanggung jawab security: SAST di commit, SCA di build, DAST di test, IaC scan di deploy

STRIDE framework membantu berpikir sistematis seperti attacker: Spoofing, Tampering, Repudiation, Information Disclosure, DoS, Elevation of Privilege

Parameterized queries + PBKDF2 + constant-time comparison adalah tiga secure coding practice paling penting untuk sistem autentikasi

⚠️ Etika Security Testing: Semua teknik yang dipelajari di sesi ini (fuzzing, injection testing, DAST) hanya boleh diterapkan pada sistem yang Anda miliki izin eksplisit untuk mengujinya. Menguji sistem orang lain tanpa izin adalah tindakan ilegal dan melanggar UU ITE.