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 › 11_timing_oracle.sh

11_timing_oracle.sh 181 lines
1 #!/bin/bash
2 # 11 - Timing Oracle Tests
3 # Methodology: 30-sample mean + stddev per group; signal is real if |diff| > 3*stddev
4 # Covers HTTP/1.1, HTTP/2, constant-time auth, padding oracle
5
6 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7 source "$SCRIPT_DIR/../config.sh"
8 OUT_FILE="$OUT/11_timing_oracle.txt"
9
10 # --local flag: tighten threshold when running inside same datacenter/VPN
11 # Remote internet jitter is ~20-50ms; local jitter is ~1-5ms
12 # Default threshold = 3ฯƒ with min 15ms floor
13 # --local threshold = 3ฯƒ with min 3ms floor (catches subtle constant-time violations)
14 LOCAL_MODE="${LOCAL_MODE:-0}"
15 if [ "$LOCAL_MODE" = "1" ]; then
16 TIMING_FLOOR=3
17 echo "Mode: LOCAL โ€” timing floor 3ms (tight, for same-datacenter runs)" | tee -a "$OUT_FILE"
18 else
19 TIMING_FLOOR=15
20 echo "Mode: REMOTE โ€” timing floor 15ms (guards against internet jitter)" | tee -a "$OUT_FILE"
21 fi
22 echo "=== 11. Timing Oracle Tests ===" | tee "$OUT_FILE"
23 echo "Methodology: 50 samples per group, mean ยฑ stddev, signal threshold = 3ฯƒ" | tee -a "$OUT_FILE"
24 echo "" | tee -a "$OUT_FILE"
25
26 # โ”€โ”€ timing harness โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
27 # Returns space-separated list of ms timings
28 sample_times() {
29 local n="$1"; shift
30 local times=""
31 for i in $(seq 1 "$n"); do
32 T=$(python3 -c "import time; print(int(time.time()*1000))")
33 curl -sk -o /dev/null --max-time 15 "$@" 2>/dev/null
34 E=$(python3 -c "import time; print(int(time.time()*1000))")
35 times="$times $((E - T))"
36 done
37 echo "$times"
38 }
39
40 # Compute mean and stddev from space-separated ms list
41 stats() {
42 python3 -c "
43 import sys, math, statistics
44 vals = [int(x) for x in sys.stdin.read().split() if x]
45 if not vals: print('N=0 mean=0 stddev=0'); sys.exit()
46 m = statistics.mean(vals)
47 s = statistics.pstdev(vals) if len(vals) > 1 else 0
48 print(f'N={len(vals)} mean={m:.1f}ms stddev={s:.1f}ms min={min(vals)}ms max={max(vals)}ms')
49 "
50 }
51
52 compare_groups() {
53 # compare_groups "label_a" times_a "label_b" times_b
54 local la="$1" ta="$2" lb="$3" tb="$4"
55 python3 -c "
56 import sys, math, statistics
57 la,ta,lb,tb = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]
58 a = [int(x) for x in ta.split() if x]
59 b = [int(x) for x in tb.split() if x]
60 if not a or not b: print(' [SKIP] insufficient data'); sys.exit()
61 ma, mb = statistics.mean(a), statistics.mean(b)
62 sa = statistics.pstdev(a) if len(a)>1 else 1
63 sb = statistics.pstdev(b) if len(b)>1 else 1
64 diff = abs(ma - mb)
65 import os
66 floor = int(os.environ.get("TIMING_FLOOR", "15"))
67 threshold = 3 * max(sa, sb, floor)
68 verdict = 'TIMING-LEAK' if diff > threshold else 'OK'
69 print(f' [{verdict}] {la}: {ma:.1f}msยฑ{sa:.1f} vs {lb}: {mb:.1f}msยฑ{sb:.1f} diff={diff:.1f}ms threshold={threshold:.1f}ms')
70 " "$la" "$ta" "$lb" "$tb"
71 }
72
73 SAMPLES=50
74
75 # โ”€โ”€ 1. API Key Timing Oracle โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
76 echo "--- API Key Timing Oracle (HTTP/2, $SAMPLES samples each) ---" | tee -a "$OUT_FILE"
77 echo " Sampling invalid key..." | tee -a "$OUT_FILE"
78 T_INVALID=$(sample_times $SAMPLES \
79 -X POST --http2 \
80 -H 'Authorization: Bearer INVALID_KEY_XXXXXXXXXXX' \
81 -H 'Content-Type: application/json' \
82 -d '{"data":"test","algorithm":"classical"}' \
83 "$API_TARGET/encrypt")
84 echo " Invalid key: $(echo "$T_INVALID" | stats)" | tee -a "$OUT_FILE"
85
86 echo " Sampling no-key (missing header)..." | tee -a "$OUT_FILE"
87 T_NOKEY=$(sample_times $SAMPLES \
88 -X POST --http2 \
89 -H 'Content-Type: application/json' \
90 -d '{"data":"test","algorithm":"classical"}' \
91 "$API_TARGET/encrypt")
92 echo " No key: $(echo "$T_NOKEY" | stats)" | tee -a "$OUT_FILE"
93
94 echo " Sampling malformed key (wrong prefix)..." | tee -a "$OUT_FILE"
95 T_MALFORMED=$(sample_times $SAMPLES \
96 -X POST --http2 \
97 -H 'Authorization: Basic INVALID_BASE64==' \
98 -H 'Content-Type: application/json' \
99 -d '{"data":"test","algorithm":"classical"}' \
100 "$API_TARGET/encrypt")
101 echo " Malformed: $(echo "$T_MALFORMED" | stats)" | tee -a "$OUT_FILE"
102
103 compare_groups "invalid-key" "$T_INVALID" "no-key" "$T_NOKEY" | tee -a "$OUT_FILE"
104 compare_groups "invalid-key" "$T_INVALID" "malformed-key" "$T_MALFORMED" | tee -a "$OUT_FILE"
105 echo "" | tee -a "$OUT_FILE"
106
107 # โ”€โ”€ 2. Admin Login Username Enumeration โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
108 echo "--- Admin Login Timing Oracle ($SAMPLES samples each) ---" | tee -a "$OUT_FILE"
109 echo " Sampling likely-valid username 'admin'..." | tee -a "$OUT_FILE"
110 T_ADMIN=$(sample_times $SAMPLES \
111 -X POST --http2 \
112 -H 'Content-Type: application/x-www-form-urlencoded' \
113 -d 'username=admin&password=wrongpassword_xyz_pentest' \
114 "$TARGET/admin/")
115 echo " 'admin': $(echo "$T_ADMIN" | stats)" | tee -a "$OUT_FILE"
116
117 echo " Sampling nonexistent username..." | tee -a "$OUT_FILE"
118 T_NOUSER=$(sample_times $SAMPLES \
119 -X POST --http2 \
120 -H 'Content-Type: application/x-www-form-urlencoded' \
121 -d 'username=nonexistent_user_xyz_1234&password=wrongpassword_xyz_pentest' \
122 "$TARGET/admin/")
123 echo " nonexistent: $(echo "$T_NOUSER" | stats)" | tee -a "$OUT_FILE"
124
125 compare_groups "admin" "$T_ADMIN" "nonexistent" "$T_NOUSER" | tee -a "$OUT_FILE"
126 echo "" | tee -a "$OUT_FILE"
127
128 # โ”€โ”€ 3. Decrypt Padding Oracle โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
129 echo "--- Decrypt Padding Oracle ($SAMPLES samples each) ---" | tee -a "$OUT_FILE"
130 SHORT_B64="aGVsbG8=" # "hello" โ€” too short, invalid ciphertext
131 LONG_B64=$(python3 -c "import base64; print(base64.b64encode(b'X'*512).decode())")
132
133 echo " Sampling short invalid ciphertext..." | tee -a "$OUT_FILE"
134 T_SHORT=$(sample_times $SAMPLES \
135 -X POST --http2 \
136 -H 'Content-Type: application/json' \
137 -d "{\"data\":\"$SHORT_B64\",\"algorithm\":\"classical\"}" \
138 "$API_TARGET/decrypt")
139 echo " Short (8b): $(echo "$T_SHORT" | stats)" | tee -a "$OUT_FILE"
140
141 echo " Sampling long invalid ciphertext..." | tee -a "$OUT_FILE"
142 T_LONG=$(sample_times $SAMPLES \
143 -X POST --http2 \
144 -H 'Content-Type: application/json' \
145 -d "{\"data\":\"$LONG_B64\",\"algorithm\":\"classical\"}" \
146 "$API_TARGET/decrypt")
147 echo " Long (512b): $(echo "$T_LONG" | stats)" | tee -a "$OUT_FILE"
148
149 compare_groups "short-ciphertext" "$T_SHORT" "long-ciphertext" "$T_LONG" | tee -a "$OUT_FILE"
150 echo "" | tee -a "$OUT_FILE"
151
152 # โ”€โ”€ 4. HTTP/1.1 vs HTTP/2 Timing Baseline โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
153 echo "--- Protocol Timing Baseline (HTTP/1.1 vs HTTP/2, $SAMPLES samples) ---" | tee -a "$OUT_FILE"
154 echo " HTTP/1.1..." | tee -a "$OUT_FILE"
155 T_H1=$(sample_times $SAMPLES --http1.1 "$TARGET/")
156 echo " HTTP/1.1: $(echo "$T_H1" | stats)" | tee -a "$OUT_FILE"
157
158 echo " HTTP/2..." | tee -a "$OUT_FILE"
159 T_H2=$(sample_times $SAMPLES --http2 "$TARGET/")
160 echo " HTTP/2: $(echo "$T_H2" | stats)" | tee -a "$OUT_FILE"
161
162 compare_groups "HTTP/1.1" "$T_H1" "HTTP/2" "$T_H2" | tee -a "$OUT_FILE"
163 echo "" | tee -a "$OUT_FILE"
164
165 # โ”€โ”€ 5. WAF Timing โ€” blocked vs clean โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
166 echo "--- WAF Timing Oracle (blocked vs clean, $SAMPLES samples) ---" | tee -a "$OUT_FILE"
167 echo " Clean request..." | tee -a "$OUT_FILE"
168 T_CLEAN=$(sample_times $SAMPLES --http2 -A "$BROWSER_UA" "$TARGET/")
169 echo " Clean: $(echo "$T_CLEAN" | stats)" | tee -a "$OUT_FILE"
170
171 echo " Blocked (SQLi) request..." | tee -a "$OUT_FILE"
172 T_BLOCKED=$(sample_times $SAMPLES --http2 -A "$BROWSER_UA" \
173 "$TARGET/?q=$(python3 -c "import urllib.parse; print(urllib.parse.quote(\"' OR 1=1--\"))")")
174 echo " Blocked: $(echo "$T_BLOCKED" | stats)" | tee -a "$OUT_FILE"
175
176 compare_groups "clean" "$T_CLEAN" "waf-blocked" "$T_BLOCKED" | tee -a "$OUT_FILE"
177 echo " (significant diff = WAF adds measurable latency โ€” timing side-channel)" | tee -a "$OUT_FILE"
178 echo "" | tee -a "$OUT_FILE"
179
180 echo "=== 11. Timing Oracle COMPLETE ===" | tee -a "$OUT_FILE"
181