@feardread/fear 1.0.1
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/FEAR.js +459 -0
- package/FEARServer.js +280 -0
- package/controllers/agent.js +438 -0
- package/controllers/auth/index.js +345 -0
- package/controllers/auth/token.js +50 -0
- package/controllers/blog.js +105 -0
- package/controllers/brand.js +10 -0
- package/controllers/cart.js +425 -0
- package/controllers/category.js +9 -0
- package/controllers/coupon.js +63 -0
- package/controllers/crud/crud.js +508 -0
- package/controllers/crud/index.js +36 -0
- package/controllers/email.js +34 -0
- package/controllers/enquiry.js +65 -0
- package/controllers/events.js +9 -0
- package/controllers/order.js +125 -0
- package/controllers/payment.js +31 -0
- package/controllers/product.js +147 -0
- package/controllers/review.js +247 -0
- package/controllers/tag.js +10 -0
- package/controllers/task.js +10 -0
- package/controllers/upload.js +41 -0
- package/controllers/user.js +401 -0
- package/index.js +7 -0
- package/libs/agent/index.js +561 -0
- package/libs/agent/modules/ai/ai.js +285 -0
- package/libs/agent/modules/ai/chat.js +518 -0
- package/libs/agent/modules/ai/config.js +688 -0
- package/libs/agent/modules/ai/operations.js +787 -0
- package/libs/agent/modules/analyze/api.js +546 -0
- package/libs/agent/modules/analyze/dorks.js +395 -0
- package/libs/agent/modules/ccard/README.md +454 -0
- package/libs/agent/modules/ccard/audit.js +479 -0
- package/libs/agent/modules/ccard/checker.js +674 -0
- package/libs/agent/modules/ccard/payment-processors.json +16 -0
- package/libs/agent/modules/ccard/validator.js +629 -0
- package/libs/agent/modules/code/analyzer.js +303 -0
- package/libs/agent/modules/code/jquery.js +1093 -0
- package/libs/agent/modules/code/react.js +1536 -0
- package/libs/agent/modules/code/refactor.js +499 -0
- package/libs/agent/modules/crypto/exchange.js +564 -0
- package/libs/agent/modules/net/proxy.js +409 -0
- package/libs/agent/modules/security/cve.js +442 -0
- package/libs/agent/modules/security/monitor.js +360 -0
- package/libs/agent/modules/security/scanner.js +300 -0
- package/libs/agent/modules/security/vulnerability.js +506 -0
- package/libs/agent/modules/security/web.js +465 -0
- package/libs/agent/modules/utils/browser.js +492 -0
- package/libs/agent/modules/utils/colorizer.js +285 -0
- package/libs/agent/modules/utils/manager.js +478 -0
- package/libs/cloud/index.js +228 -0
- package/libs/config/db.js +21 -0
- package/libs/config/validator.js +82 -0
- package/libs/db/index.js +318 -0
- package/libs/emailer/imap.js +126 -0
- package/libs/emailer/info.js +41 -0
- package/libs/emailer/smtp.js +77 -0
- package/libs/handler/async.js +3 -0
- package/libs/handler/error.js +66 -0
- package/libs/handler/index.js +161 -0
- package/libs/logger/index.js +49 -0
- package/libs/logger/morgan.js +24 -0
- package/libs/passport/passport.js +109 -0
- package/libs/search/api.js +384 -0
- package/libs/search/features.js +219 -0
- package/libs/search/service.js +64 -0
- package/libs/swagger/config.js +18 -0
- package/libs/swagger/index.js +35 -0
- package/libs/validator/index.js +254 -0
- package/models/blog.js +31 -0
- package/models/brand.js +12 -0
- package/models/cart.js +14 -0
- package/models/category.js +11 -0
- package/models/coupon.js +9 -0
- package/models/customer.js +0 -0
- package/models/enquiry.js +29 -0
- package/models/events.js +13 -0
- package/models/order.js +94 -0
- package/models/product.js +32 -0
- package/models/review.js +14 -0
- package/models/tag.js +10 -0
- package/models/task.js +11 -0
- package/models/user.js +68 -0
- package/package.json +12 -0
- package/routes/agent.js +615 -0
- package/routes/auth.js +13 -0
- package/routes/blog.js +19 -0
- package/routes/brand.js +15 -0
- package/routes/cart.js +105 -0
- package/routes/category.js +16 -0
- package/routes/coupon.js +15 -0
- package/routes/enquiry.js +14 -0
- package/routes/events.js +16 -0
- package/routes/mail.js +170 -0
- package/routes/order.js +19 -0
- package/routes/product.js +22 -0
- package/routes/review.js +11 -0
- package/routes/task.js +12 -0
- package/routes/user.js +17 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
// modules/traffic-monitor.js - Real-time Network Traffic Monitor
|
|
2
|
+
const { spawn } = require('child_process');
|
|
3
|
+
const fs = require('fs').promises;
|
|
4
|
+
const os = require('os');
|
|
5
|
+
|
|
6
|
+
class Monitor {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.monitoring = false;
|
|
9
|
+
this.tcpdumpProcess = null;
|
|
10
|
+
this.stats = {
|
|
11
|
+
startTime: null,
|
|
12
|
+
packets: {
|
|
13
|
+
total: 0,
|
|
14
|
+
tcp: 0,
|
|
15
|
+
udp: 0,
|
|
16
|
+
icmp: 0,
|
|
17
|
+
other: 0
|
|
18
|
+
},
|
|
19
|
+
protocols: {
|
|
20
|
+
http: 0,
|
|
21
|
+
https: 0,
|
|
22
|
+
dns: 0,
|
|
23
|
+
ssh: 0,
|
|
24
|
+
ftp: 0
|
|
25
|
+
},
|
|
26
|
+
traffic: {
|
|
27
|
+
incoming: 0,
|
|
28
|
+
outgoing: 0,
|
|
29
|
+
totalBytes: 0
|
|
30
|
+
},
|
|
31
|
+
suspicious: [],
|
|
32
|
+
connections: new Map()
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async startMonitoring(args) {
|
|
37
|
+
if (this.monitoring) {
|
|
38
|
+
console.log('⚠️ Traffic monitoring is already running. Use "stop-monitor" first.\n');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const iface = args[0] || this.getDefaultInterface();
|
|
43
|
+
|
|
44
|
+
console.log(`\n������ Starting Traffic Monitor`);
|
|
45
|
+
console.log(`═══════════════════════════════════════`);
|
|
46
|
+
console.log(`Interface: ${iface}`);
|
|
47
|
+
console.log(`Time: ${new Date().toLocaleString()}`);
|
|
48
|
+
console.log(`\nMonitoring... (Press Ctrl+C or use "stop-monitor" to stop)\n`);
|
|
49
|
+
|
|
50
|
+
this.monitoring = true;
|
|
51
|
+
this.stats.startTime = Date.now();
|
|
52
|
+
|
|
53
|
+
// Check if we have tcpdump or use fallback
|
|
54
|
+
const hasTcpdump = await this.checkCommand('tcpdump');
|
|
55
|
+
|
|
56
|
+
if (hasTcpdump) {
|
|
57
|
+
this.startTcpdumpMonitor(iface);
|
|
58
|
+
} else {
|
|
59
|
+
console.log('⚠️ tcpdump not found. Using fallback monitoring...\n');
|
|
60
|
+
this.startFallbackMonitor();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async checkCommand(cmd) {
|
|
65
|
+
return new Promise((resolve) => {
|
|
66
|
+
const proc = spawn('which', [cmd]);
|
|
67
|
+
proc.on('close', (code) => resolve(code === 0));
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
startTcpdumpMonitor(iface) {
|
|
72
|
+
// tcpdump -i interface -n -l
|
|
73
|
+
// Note: May require sudo privileges
|
|
74
|
+
this.tcpdumpProcess = spawn('tcpdump', [
|
|
75
|
+
'-i', iface,
|
|
76
|
+
'-n', // Don't resolve hostnames
|
|
77
|
+
'-l', // Line buffered
|
|
78
|
+
'-tttt' // Human readable timestamps
|
|
79
|
+
]);
|
|
80
|
+
|
|
81
|
+
this.tcpdumpProcess.stdout.on('data', (data) => {
|
|
82
|
+
const lines = data.toString().split('\n');
|
|
83
|
+
lines.forEach(line => this.parsePacket(line));
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
this.tcpdumpProcess.stderr.on('data', (data) => {
|
|
87
|
+
const msg = data.toString();
|
|
88
|
+
if (msg.includes('Permission denied')) {
|
|
89
|
+
console.log('❌ Permission denied. Try running with sudo.\n');
|
|
90
|
+
this.stopMonitoring();
|
|
91
|
+
} else if (!msg.includes('listening on')) {
|
|
92
|
+
console.error(`⚠️ ${msg}`);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
this.tcpdumpProcess.on('close', () => {
|
|
97
|
+
this.monitoring = false;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
startFallbackMonitor() {
|
|
102
|
+
// Fallback: Monitor using netstat
|
|
103
|
+
this.monitorInterval = setInterval(() => {
|
|
104
|
+
this.sampleNetworkActivity();
|
|
105
|
+
}, 2000);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async sampleNetworkActivity() {
|
|
109
|
+
const proc = spawn('netstat', ['-an']);
|
|
110
|
+
let output = '';
|
|
111
|
+
|
|
112
|
+
proc.stdout.on('data', (data) => {
|
|
113
|
+
output += data.toString();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
proc.on('close', () => {
|
|
117
|
+
const lines = output.split('\n');
|
|
118
|
+
let established = 0;
|
|
119
|
+
|
|
120
|
+
lines.forEach(line => {
|
|
121
|
+
if (line.includes('ESTABLISHED')) {
|
|
122
|
+
established++;
|
|
123
|
+
this.stats.packets.total++;
|
|
124
|
+
|
|
125
|
+
// Basic protocol detection
|
|
126
|
+
if (line.includes(':80 ') || line.includes(':8080 ')) {
|
|
127
|
+
this.stats.protocols.http++;
|
|
128
|
+
} else if (line.includes(':443 ') || line.includes(':8443 ')) {
|
|
129
|
+
this.stats.protocols.https++;
|
|
130
|
+
} else if (line.includes(':22 ')) {
|
|
131
|
+
this.stats.protocols.ssh++;
|
|
132
|
+
} else if (line.includes(':53 ')) {
|
|
133
|
+
this.stats.protocols.dns++;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (established > 0) {
|
|
139
|
+
console.log(`������ Active connections: ${established}`);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
parsePacket(line) {
|
|
145
|
+
if (!line.trim()) return;
|
|
146
|
+
|
|
147
|
+
this.stats.packets.total++;
|
|
148
|
+
|
|
149
|
+
// Parse protocol
|
|
150
|
+
if (line.includes('TCP') || line.includes('tcp')) {
|
|
151
|
+
this.stats.packets.tcp++;
|
|
152
|
+
} else if (line.includes('UDP') || line.includes('udp')) {
|
|
153
|
+
this.stats.packets.udp++;
|
|
154
|
+
} else if (line.includes('ICMP') || line.includes('icmp')) {
|
|
155
|
+
this.stats.packets.icmp++;
|
|
156
|
+
} else {
|
|
157
|
+
this.stats.packets.other++;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Parse ports for protocol detection
|
|
161
|
+
if (line.match(/\.80\s|\.80:/)) {
|
|
162
|
+
this.stats.protocols.http++;
|
|
163
|
+
} else if (line.match(/\.443\s|\.443:/)) {
|
|
164
|
+
this.stats.protocols.https++;
|
|
165
|
+
} else if (line.match(/\.53\s|\.53:/)) {
|
|
166
|
+
this.stats.protocols.dns++;
|
|
167
|
+
} else if (line.match(/\.22\s|\.22:/)) {
|
|
168
|
+
this.stats.protocols.ssh++;
|
|
169
|
+
} else if (line.match(/\.21\s|\.21:/)) {
|
|
170
|
+
this.stats.protocols.ftp++;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Detect suspicious patterns
|
|
174
|
+
this.detectSuspicious(line);
|
|
175
|
+
|
|
176
|
+
// Display packet (rate limited)
|
|
177
|
+
if (this.stats.packets.total % 50 === 0) {
|
|
178
|
+
this.displayLiveStats();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
detectSuspicious(line) {
|
|
183
|
+
const suspicious = [];
|
|
184
|
+
|
|
185
|
+
// Port scanning detection (many connections from same IP)
|
|
186
|
+
const ipMatch = line.match(/(\d+\.\d+\.\d+\.\d+)/);
|
|
187
|
+
if (ipMatch) {
|
|
188
|
+
const ip = ipMatch[1];
|
|
189
|
+
const count = this.stats.connections.get(ip) || 0;
|
|
190
|
+
this.stats.connections.set(ip, count + 1);
|
|
191
|
+
|
|
192
|
+
if (count > 100) {
|
|
193
|
+
suspicious.push({
|
|
194
|
+
type: 'Port Scan',
|
|
195
|
+
detail: `Multiple connections from ${ip}`,
|
|
196
|
+
timestamp: new Date()
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Unusual ports
|
|
202
|
+
if (line.match(/\.(666|1337|31337|4444|5555)\s/)) {
|
|
203
|
+
suspicious.push({
|
|
204
|
+
type: 'Suspicious Port',
|
|
205
|
+
detail: 'Connection to uncommon port',
|
|
206
|
+
timestamp: new Date()
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// FTP (unencrypted)
|
|
211
|
+
if (line.includes('.21 ') || line.includes(':21 ')) {
|
|
212
|
+
suspicious.push({
|
|
213
|
+
type: 'Unencrypted Protocol',
|
|
214
|
+
detail: 'FTP traffic detected (consider SFTP)',
|
|
215
|
+
timestamp: new Date()
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Telnet (unencrypted)
|
|
220
|
+
if (line.includes('.23 ') || line.includes(':23 ')) {
|
|
221
|
+
suspicious.push({
|
|
222
|
+
type: 'Unencrypted Protocol',
|
|
223
|
+
detail: 'Telnet traffic detected (use SSH)',
|
|
224
|
+
timestamp: new Date()
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (suspicious.length > 0) {
|
|
229
|
+
suspicious.forEach(s => {
|
|
230
|
+
this.stats.suspicious.push(s);
|
|
231
|
+
console.log(`������ ${s.type}: ${s.detail}`);
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
displayLiveStats() {
|
|
237
|
+
console.log(`\n������ Live Stats (${this.stats.packets.total} packets)`);
|
|
238
|
+
console.log(` TCP: ${this.stats.packets.tcp} | UDP: ${this.stats.packets.udp} | ICMP: ${this.stats.packets.icmp}`);
|
|
239
|
+
console.log(` HTTP: ${this.stats.protocols.http} | HTTPS: ${this.stats.protocols.https} | DNS: ${this.stats.protocols.dns}`);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
stopMonitoring() {
|
|
243
|
+
if (!this.monitoring) {
|
|
244
|
+
console.log('ℹ️ Traffic monitoring is not running.\n');
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (this.tcpdumpProcess) {
|
|
249
|
+
this.tcpdumpProcess.kill();
|
|
250
|
+
this.tcpdumpProcess = null;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (this.monitorInterval) {
|
|
254
|
+
clearInterval(this.monitorInterval);
|
|
255
|
+
this.monitorInterval = null;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
this.monitoring = false;
|
|
259
|
+
console.log('\n✅ Traffic monitoring stopped.\n');
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
showStats() {
|
|
263
|
+
if (!this.stats.startTime) {
|
|
264
|
+
console.log('ℹ️ No monitoring data available. Start monitoring first.\n');
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const duration = Math.floor((Date.now() - this.stats.startTime) / 1000);
|
|
269
|
+
const minutes = Math.floor(duration / 60);
|
|
270
|
+
const seconds = duration % 60;
|
|
271
|
+
|
|
272
|
+
console.log(`\n������ Traffic Statistics`);
|
|
273
|
+
console.log(`═══════════════════════════════════════`);
|
|
274
|
+
console.log(`Duration: ${minutes}m ${seconds}s`);
|
|
275
|
+
console.log(`Status: ${this.monitoring ? '������ Active' : '������ Stopped'}\n`);
|
|
276
|
+
|
|
277
|
+
console.log(`Packets:`);
|
|
278
|
+
console.log(` Total: ${this.stats.packets.total}`);
|
|
279
|
+
console.log(` TCP: ${this.stats.packets.tcp} (${this.getPercentage(this.stats.packets.tcp, this.stats.packets.total)}%)`);
|
|
280
|
+
console.log(` UDP: ${this.stats.packets.udp} (${this.getPercentage(this.stats.packets.udp, this.stats.packets.total)}%)`);
|
|
281
|
+
console.log(` ICMP: ${this.stats.packets.icmp} (${this.getPercentage(this.stats.packets.icmp, this.stats.packets.total)}%)`);
|
|
282
|
+
console.log(` Other: ${this.stats.packets.other}\n`);
|
|
283
|
+
|
|
284
|
+
console.log(`Protocols:`);
|
|
285
|
+
console.log(` HTTP: ${this.stats.protocols.http}`);
|
|
286
|
+
console.log(` HTTPS: ${this.stats.protocols.https}`);
|
|
287
|
+
console.log(` DNS: ${this.stats.protocols.dns}`);
|
|
288
|
+
console.log(` SSH: ${this.stats.protocols.ssh}`);
|
|
289
|
+
console.log(` FTP: ${this.stats.protocols.ftp}\n`);
|
|
290
|
+
|
|
291
|
+
if (this.stats.suspicious.length > 0) {
|
|
292
|
+
console.log(`������ Suspicious Activity (${this.stats.suspicious.length} events):`);
|
|
293
|
+
const recent = this.stats.suspicious.slice(-10);
|
|
294
|
+
recent.forEach(s => {
|
|
295
|
+
console.log(` [${s.timestamp.toLocaleTimeString()}] ${s.type}: ${s.detail}`);
|
|
296
|
+
});
|
|
297
|
+
console.log();
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Top talkers
|
|
301
|
+
if (this.stats.connections.size > 0) {
|
|
302
|
+
console.log(`Top Connections:`);
|
|
303
|
+
const sorted = Array.from(this.stats.connections.entries())
|
|
304
|
+
.sort((a, b) => b[1] - a[1])
|
|
305
|
+
.slice(0, 5);
|
|
306
|
+
|
|
307
|
+
sorted.forEach(([ip, count]) => {
|
|
308
|
+
console.log(` ${ip}: ${count} packets`);
|
|
309
|
+
});
|
|
310
|
+
console.log();
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
getPercentage(value, total) {
|
|
315
|
+
if (total === 0) return 0;
|
|
316
|
+
return ((value / total) * 100).toFixed(1);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
async exportData(args) {
|
|
320
|
+
const filename = args[0] || `traffic-export-${Date.now()}.json`;
|
|
321
|
+
|
|
322
|
+
const exportData = {
|
|
323
|
+
exportTime: new Date().toISOString(),
|
|
324
|
+
monitoringDuration: this.stats.startTime ? Date.now() - this.stats.startTime : 0,
|
|
325
|
+
statistics: {
|
|
326
|
+
packets: this.stats.packets,
|
|
327
|
+
protocols: this.stats.protocols,
|
|
328
|
+
traffic: this.stats.traffic
|
|
329
|
+
},
|
|
330
|
+
suspicious: this.stats.suspicious,
|
|
331
|
+
topConnections: Array.from(this.stats.connections.entries())
|
|
332
|
+
.sort((a, b) => b[1] - a[1])
|
|
333
|
+
.slice(0, 20)
|
|
334
|
+
.map(([ip, count]) => ({ ip, packetCount: count }))
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
try {
|
|
338
|
+
await fs.writeFile(filename, JSON.stringify(exportData, null, 2));
|
|
339
|
+
console.log(`\n✅ Traffic data exported to: ${filename}\n`);
|
|
340
|
+
} catch (err) {
|
|
341
|
+
console.log(`❌ Export failed: ${err.message}\n`);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
getDefaultInterface() {
|
|
346
|
+
const platform = os.platform();
|
|
347
|
+
|
|
348
|
+
if (platform === 'darwin') {
|
|
349
|
+
return 'en0';
|
|
350
|
+
} else if (platform === 'linux') {
|
|
351
|
+
return 'eth0';
|
|
352
|
+
} else if (platform === 'win32') {
|
|
353
|
+
return 'Ethernet';
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return 'any';
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
module.exports = Monitor;
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
// modules/scanner.js - Network and Security Scanner
|
|
2
|
+
const net = require('net');
|
|
3
|
+
const fs = require('fs').promises;
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
|
|
7
|
+
const Scanner = function() {
|
|
8
|
+
this.commonPorts = {
|
|
9
|
+
20: 'FTP Data',
|
|
10
|
+
21: 'FTP Control',
|
|
11
|
+
22: 'SSH',
|
|
12
|
+
23: 'Telnet',
|
|
13
|
+
25: 'SMTP',
|
|
14
|
+
53: 'DNS',
|
|
15
|
+
80: 'HTTP',
|
|
16
|
+
110: 'POP3',
|
|
17
|
+
143: 'IMAP',
|
|
18
|
+
443: 'HTTPS',
|
|
19
|
+
445: 'SMB',
|
|
20
|
+
3306: 'MySQL',
|
|
21
|
+
3389: 'RDP',
|
|
22
|
+
5432: 'PostgreSQL',
|
|
23
|
+
6379: 'Redis',
|
|
24
|
+
8080: 'HTTP Alt',
|
|
25
|
+
8443: 'HTTPS Alt',
|
|
26
|
+
27017: 'MongoDB'
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
Scanner.prototype = {
|
|
31
|
+
|
|
32
|
+
async scanPorts(args) {
|
|
33
|
+
const host = args[0] || '127.0.0.1';
|
|
34
|
+
const startPort = parseInt(args[1]) || 1;
|
|
35
|
+
const endPort = parseInt(args[2]) || 1024;
|
|
36
|
+
|
|
37
|
+
console.log(`\n������ Port Scan Report`);
|
|
38
|
+
console.log(`═══════════════════════════════════════`);
|
|
39
|
+
console.log(`Target: ${host}`);
|
|
40
|
+
console.log(`Range: ${startPort}-${endPort}`);
|
|
41
|
+
console.log(`Started: ${new Date().toLocaleString()}\n`);
|
|
42
|
+
|
|
43
|
+
const startTime = Date.now();
|
|
44
|
+
const openPorts = [];
|
|
45
|
+
const promises = [];
|
|
46
|
+
let scanned = 0;
|
|
47
|
+
const total = endPort - startPort + 1;
|
|
48
|
+
|
|
49
|
+
for (let port = startPort; port <= endPort; port++) {
|
|
50
|
+
promises.push(
|
|
51
|
+
this.checkPort(host, port)
|
|
52
|
+
.then(isOpen => {
|
|
53
|
+
scanned++;
|
|
54
|
+
if (isOpen) {
|
|
55
|
+
const service = this.commonPorts[port] || 'Unknown';
|
|
56
|
+
openPorts.push({ port, service });
|
|
57
|
+
console.log(`✅ Port ${port} OPEN - ${service}`);
|
|
58
|
+
}
|
|
59
|
+
// Progress indicator
|
|
60
|
+
if (scanned % 100 === 0) {
|
|
61
|
+
process.stdout.write(`\r⏳ Progress: ${scanned}/${total} ports scanned...`);
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
.catch(() => {})
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// Limit concurrent connections
|
|
68
|
+
if (promises.length >= 100) {
|
|
69
|
+
await Promise.all(promises);
|
|
70
|
+
promises.length = 0;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
await Promise.all(promises);
|
|
75
|
+
|
|
76
|
+
const duration = ((Date.now() - startTime) / 1000).toFixed(2);
|
|
77
|
+
|
|
78
|
+
console.log(`\n\n������ Scan Summary`);
|
|
79
|
+
console.log(`═══════════════════════════════════════`);
|
|
80
|
+
console.log(`Total ports scanned: ${total}`);
|
|
81
|
+
console.log(`Open ports: ${openPorts.length}`);
|
|
82
|
+
console.log(`Duration: ${duration}s`);
|
|
83
|
+
|
|
84
|
+
if (openPorts.length > 0) {
|
|
85
|
+
console.log(`\n⚠️ Security Notes:`);
|
|
86
|
+
openPorts.forEach(({ port, service }) => {
|
|
87
|
+
if ([21, 23, 445, 3389].includes(port)) {
|
|
88
|
+
console.log(` ������ Port ${port} (${service}) - Consider closing if unused`);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
console.log();
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
checkPort(host, port, timeout = 1000) {
|
|
96
|
+
return new Promise((resolve) => {
|
|
97
|
+
const socket = new net.Socket();
|
|
98
|
+
|
|
99
|
+
socket.setTimeout(timeout);
|
|
100
|
+
socket.on('connect', () => {
|
|
101
|
+
socket.destroy();
|
|
102
|
+
resolve(true);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
socket.on('timeout', () => {
|
|
106
|
+
socket.destroy();
|
|
107
|
+
resolve(false);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
socket.on('error', () => {
|
|
111
|
+
resolve(false);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
socket.connect(port, host);
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
async checkDependencies(args) {
|
|
119
|
+
const dir = args[0] || '.';
|
|
120
|
+
const pkgPath = path.join(dir, 'package.json');
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
const data = await fs.readFile(pkgPath, 'utf8');
|
|
124
|
+
const pkg = JSON.parse(data);
|
|
125
|
+
|
|
126
|
+
console.log('\n������ Dependency Analysis');
|
|
127
|
+
console.log(`═══════════════════════════════════════`);
|
|
128
|
+
console.log(`Project: ${pkg.name || 'Unknown'}`);
|
|
129
|
+
console.log(`Version: ${pkg.version || 'Unknown'}`);
|
|
130
|
+
console.log(`License: ${pkg.license || 'Not specified'}\n`);
|
|
131
|
+
|
|
132
|
+
const deps = pkg.dependencies || {};
|
|
133
|
+
const devDeps = pkg.devDependencies || {};
|
|
134
|
+
|
|
135
|
+
if (Object.keys(deps).length > 0) {
|
|
136
|
+
console.log('������ Production Dependencies:');
|
|
137
|
+
Object.entries(deps).forEach(([name, ver]) => {
|
|
138
|
+
console.log(` • ${name}: ${ver}`);
|
|
139
|
+
});
|
|
140
|
+
console.log();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (Object.keys(devDeps).length > 0) {
|
|
144
|
+
console.log('������ Dev Dependencies:');
|
|
145
|
+
Object.entries(devDeps).forEach(([name, ver]) => {
|
|
146
|
+
console.log(` • ${name}: ${ver}`);
|
|
147
|
+
});
|
|
148
|
+
console.log();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
console.log('Recommendations:');
|
|
152
|
+
console.log(' • Run "npm audit" for vulnerability scan');
|
|
153
|
+
console.log(' • Run "npm outdated" to check for updates');
|
|
154
|
+
console.log(' • Consider using "npm audit fix" for auto-fixes\n');
|
|
155
|
+
|
|
156
|
+
} catch (err) {
|
|
157
|
+
console.log(`❌ Could not read package.json: ${err.message}\n`);
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
async getNetworkInfo() {
|
|
162
|
+
const interfaces = os.networkInterfaces();
|
|
163
|
+
|
|
164
|
+
console.log('\n������ Network Interface Information');
|
|
165
|
+
console.log(`═══════════════════════════════════════`);
|
|
166
|
+
console.log(`Hostname: ${os.hostname()}`);
|
|
167
|
+
console.log(`Platform: ${os.platform()} ${os.arch()}\n`);
|
|
168
|
+
|
|
169
|
+
Object.entries(interfaces).forEach(([name, addrs]) => {
|
|
170
|
+
console.log(`������ ${name}:`);
|
|
171
|
+
addrs.forEach(addr => {
|
|
172
|
+
const status = addr.internal ? '(Internal)' : '(External)';
|
|
173
|
+
console.log(` ${addr.family.padEnd(6)} ${addr.address.padEnd(40)} ${status}`);
|
|
174
|
+
if (addr.mac && addr.mac !== '00:00:00:00:00:00') {
|
|
175
|
+
console.log(` MAC: ${addr.mac}`);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
console.log();
|
|
179
|
+
});
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
async securityAudit(args) {
|
|
183
|
+
const dir = args[0] || '.';
|
|
184
|
+
|
|
185
|
+
console.log('\n������ Security Audit Report');
|
|
186
|
+
console.log(`═══════════════════════════════════════`);
|
|
187
|
+
console.log(`Directory: ${path.resolve(dir)}`);
|
|
188
|
+
console.log(`Date: ${new Date().toLocaleString()}\n`);
|
|
189
|
+
|
|
190
|
+
const checks = [];
|
|
191
|
+
|
|
192
|
+
// Check Node.js version
|
|
193
|
+
const nodeVer = process.version;
|
|
194
|
+
const majorVer = parseInt(nodeVer.slice(1).split('.')[0]);
|
|
195
|
+
checks.push({
|
|
196
|
+
category: 'Runtime',
|
|
197
|
+
name: 'Node.js Version',
|
|
198
|
+
status: majorVer >= 18 ? 'PASS' : 'WARN',
|
|
199
|
+
value: nodeVer,
|
|
200
|
+
note: majorVer < 18 ? 'Consider upgrading to LTS version' : null
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// Check for security files
|
|
204
|
+
const securityFiles = [
|
|
205
|
+
{ file: '.gitignore', critical: true },
|
|
206
|
+
{ file: '.env.example', critical: false },
|
|
207
|
+
{ file: 'README.md', critical: false },
|
|
208
|
+
{ file: 'SECURITY.md', critical: false },
|
|
209
|
+
{ file: '.npmrc', critical: false }
|
|
210
|
+
];
|
|
211
|
+
|
|
212
|
+
for (const { file, critical } of securityFiles) {
|
|
213
|
+
try {
|
|
214
|
+
await fs.access(path.join(dir, file));
|
|
215
|
+
checks.push({
|
|
216
|
+
category: 'Files',
|
|
217
|
+
name: file,
|
|
218
|
+
status: 'PASS',
|
|
219
|
+
value: 'Present'
|
|
220
|
+
});
|
|
221
|
+
} catch {
|
|
222
|
+
checks.push({
|
|
223
|
+
category: 'Files',
|
|
224
|
+
name: file,
|
|
225
|
+
status: critical ? 'FAIL' : 'INFO',
|
|
226
|
+
value: 'Missing',
|
|
227
|
+
note: critical ? 'Recommended' : 'Optional'
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Check .gitignore for sensitive patterns
|
|
233
|
+
try {
|
|
234
|
+
const gitignore = await fs.readFile(path.join(dir, '.gitignore'), 'utf8');
|
|
235
|
+
const patterns = ['.env', 'node_modules', '*.log', '.DS_Store'];
|
|
236
|
+
|
|
237
|
+
patterns.forEach(pattern => {
|
|
238
|
+
checks.push({
|
|
239
|
+
category: 'GitIgnore',
|
|
240
|
+
name: pattern,
|
|
241
|
+
status: gitignore.includes(pattern) ? 'PASS' : 'WARN',
|
|
242
|
+
value: gitignore.includes(pattern) ? 'Ignored' : 'Not ignored'
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
} catch {
|
|
246
|
+
// Already reported missing .gitignore
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Check for .env file (should exist, but be gitignored)
|
|
250
|
+
try {
|
|
251
|
+
await fs.access(path.join(dir, '.env'));
|
|
252
|
+
checks.push({
|
|
253
|
+
category: 'Environment',
|
|
254
|
+
name: '.env file',
|
|
255
|
+
status: 'INFO',
|
|
256
|
+
value: 'Present',
|
|
257
|
+
note: 'Ensure it\'s in .gitignore'
|
|
258
|
+
});
|
|
259
|
+
} catch {
|
|
260
|
+
checks.push({
|
|
261
|
+
category: 'Environment',
|
|
262
|
+
name: '.env file',
|
|
263
|
+
status: 'INFO',
|
|
264
|
+
value: 'Not found'
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Display results
|
|
269
|
+
const grouped = {};
|
|
270
|
+
checks.forEach(check => {
|
|
271
|
+
if (!grouped[check.category]) grouped[check.category] = [];
|
|
272
|
+
grouped[check.category].push(check);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
Object.entries(grouped).forEach(([category, items]) => {
|
|
276
|
+
console.log(`\n${category}:`);
|
|
277
|
+
items.forEach(item => {
|
|
278
|
+
const icon = item.status === 'PASS' ? '✅' :
|
|
279
|
+
item.status === 'WARN' ? '⚠️' :
|
|
280
|
+
item.status === 'FAIL' ? '❌' : 'ℹ️';
|
|
281
|
+
console.log(` ${icon} ${item.name}: ${item.value}`);
|
|
282
|
+
if (item.note) {
|
|
283
|
+
console.log(` └─ ${item.note}`);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
console.log('\n\n������ Security Recommendations:');
|
|
289
|
+
console.log(' • Keep Node.js and dependencies updated');
|
|
290
|
+
console.log(' • Use environment variables for secrets');
|
|
291
|
+
console.log(' • Implement HTTPS in production');
|
|
292
|
+
console.log(' • Enable rate limiting on APIs');
|
|
293
|
+
console.log(' • Use security headers (helmet.js)');
|
|
294
|
+
console.log(' • Implement proper input validation');
|
|
295
|
+
console.log(' • Use parameterized queries for databases');
|
|
296
|
+
console.log(' • Enable CORS properly\n');
|
|
297
|
+
},
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
module.exports = Scanner;
|