honeyweb-core 2.0.2 → 2.0.4
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/ai/gemini.js +54 -29
- package/ai/index.js +4 -27
- package/ai/prompt-templates.js +22 -42
- package/config/defaults.js +14 -37
- package/config/index.js +7 -35
- package/config/schema.js +1 -17
- package/detection/behavioral.js +26 -118
- package/detection/bot-detector.js +11 -62
- package/detection/index.js +19 -35
- package/detection/patterns.js +14 -51
- package/detection/rate-limiter.js +15 -86
- package/detection/traversal.js +42 -0
- package/index.js +1 -13
- package/middleware/blocklist-checker.js +1 -15
- package/middleware/dashboard.js +218 -214
- package/middleware/index.js +17 -39
- package/middleware/request-analyzer.js +29 -70
- package/middleware/trap-injector.js +3 -28
- package/package.json +1 -1
- package/storage/bot-tracker.js +9 -56
- package/storage/index.js +3 -12
- package/storage/json-store.js +15 -89
- package/storage/memory-store.js +9 -61
- package/utils/cache.js +5 -48
- package/utils/dns-verify.js +8 -45
- package/utils/event-emitter.js +7 -39
- package/utils/logger.js +9 -35
|
@@ -1,109 +1,38 @@
|
|
|
1
|
-
// honeyweb-core/detection/rate-limiter.js
|
|
2
|
-
// Rate limiting with auto-cleanup (fixes memory leak)
|
|
3
|
-
|
|
4
1
|
class RateLimiter {
|
|
5
2
|
constructor(config) {
|
|
6
|
-
this.window = config.window || 10000;
|
|
3
|
+
this.window = config.window || 10000;
|
|
7
4
|
this.maxRequests = config.maxRequests || 50;
|
|
8
|
-
this.requests = new Map();
|
|
9
|
-
|
|
10
|
-
// Auto-cleanup to prevent memory leak
|
|
11
|
-
const cleanupInterval = config.cleanupInterval || 60000; // 60 seconds
|
|
12
|
-
this.cleanupTimer = setInterval(() => {
|
|
13
|
-
this._cleanup();
|
|
14
|
-
}, cleanupInterval);
|
|
5
|
+
this.requests = new Map();
|
|
6
|
+
this.cleanupTimer = setInterval(() => this._cleanup(), config.cleanupInterval || 60000);
|
|
15
7
|
}
|
|
16
8
|
|
|
17
|
-
/**
|
|
18
|
-
* Check if IP has exceeded rate limit
|
|
19
|
-
* @param {string} ip
|
|
20
|
-
* @returns {Object} - { limited: boolean, count: number, remaining: number }
|
|
21
|
-
*/
|
|
22
9
|
check(ip) {
|
|
23
10
|
const now = Date.now();
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
// Get existing requests for this IP
|
|
27
|
-
let timestamps = this.requests.get(ip) || [];
|
|
28
|
-
|
|
29
|
-
// Filter out old requests outside the window
|
|
30
|
-
timestamps = timestamps.filter(ts => ts > windowStart);
|
|
31
|
-
|
|
32
|
-
// Add current request
|
|
11
|
+
let timestamps = (this.requests.get(ip) || []).filter(ts => ts > now - this.window);
|
|
33
12
|
timestamps.push(now);
|
|
34
|
-
|
|
35
|
-
// Update map
|
|
36
13
|
this.requests.set(ip, timestamps);
|
|
37
14
|
|
|
38
|
-
const count = timestamps.length;
|
|
39
|
-
const remaining = Math.max(0, this.maxRequests - count);
|
|
40
|
-
const limited = count > this.maxRequests;
|
|
41
|
-
|
|
42
15
|
return {
|
|
43
|
-
limited,
|
|
44
|
-
count,
|
|
45
|
-
remaining,
|
|
16
|
+
limited: timestamps.length > this.maxRequests,
|
|
17
|
+
count: timestamps.length,
|
|
18
|
+
remaining: Math.max(0, this.maxRequests - timestamps.length),
|
|
46
19
|
resetAt: now + this.window
|
|
47
20
|
};
|
|
48
21
|
}
|
|
49
22
|
|
|
50
|
-
/**
|
|
51
|
-
* Clean up old entries to prevent memory leak
|
|
52
|
-
* @private
|
|
53
|
-
*/
|
|
54
23
|
_cleanup() {
|
|
55
|
-
const
|
|
56
|
-
const windowStart = now - this.window;
|
|
57
|
-
|
|
24
|
+
const cutoff = Date.now() - this.window;
|
|
58
25
|
for (const [ip, timestamps] of this.requests.entries()) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (active.length === 0) {
|
|
63
|
-
// No active requests, remove entry
|
|
64
|
-
this.requests.delete(ip);
|
|
65
|
-
} else {
|
|
66
|
-
// Update with filtered timestamps
|
|
67
|
-
this.requests.set(ip, active);
|
|
68
|
-
}
|
|
26
|
+
const active = timestamps.filter(ts => ts > cutoff);
|
|
27
|
+
if (active.length === 0) this.requests.delete(ip);
|
|
28
|
+
else this.requests.set(ip, active);
|
|
69
29
|
}
|
|
70
30
|
}
|
|
71
31
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
getStats() {
|
|
77
|
-
return {
|
|
78
|
-
trackedIPs: this.requests.size,
|
|
79
|
-
window: this.window,
|
|
80
|
-
maxRequests: this.maxRequests
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Reset rate limit for an IP
|
|
86
|
-
* @param {string} ip
|
|
87
|
-
*/
|
|
88
|
-
reset(ip) {
|
|
89
|
-
this.requests.delete(ip);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Clear all rate limit data
|
|
94
|
-
*/
|
|
95
|
-
clear() {
|
|
96
|
-
this.requests.clear();
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Cleanup and stop timers
|
|
101
|
-
*/
|
|
102
|
-
destroy() {
|
|
103
|
-
if (this.cleanupTimer) {
|
|
104
|
-
clearInterval(this.cleanupTimer);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
32
|
+
getStats() { return { trackedIPs: this.requests.size, window: this.window, maxRequests: this.maxRequests }; }
|
|
33
|
+
reset(ip) { this.requests.delete(ip); }
|
|
34
|
+
clear() { this.requests.clear(); }
|
|
35
|
+
destroy() { if (this.cleanupTimer) clearInterval(this.cleanupTimer); }
|
|
107
36
|
}
|
|
108
37
|
|
|
109
38
|
module.exports = RateLimiter;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const TRAVERSAL_PATTERNS = [
|
|
2
|
+
/\.\.\//,
|
|
3
|
+
/\.\.\\/,
|
|
4
|
+
/%2e%2e[%2f%5c]/i,
|
|
5
|
+
/%252e%252e/i,
|
|
6
|
+
/\.\.%2f/i,
|
|
7
|
+
/\.\.%5c/i,
|
|
8
|
+
/\/etc\/passwd/i,
|
|
9
|
+
/\/etc\/shadow/i,
|
|
10
|
+
/\/etc\/hosts/i,
|
|
11
|
+
/\/proc\/self/i,
|
|
12
|
+
/win\.ini/i,
|
|
13
|
+
/boot\.ini/i,
|
|
14
|
+
/system32/i,
|
|
15
|
+
/%00/,
|
|
16
|
+
/\0/,
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
function detectTraversal(req) {
|
|
20
|
+
const threats = [];
|
|
21
|
+
const targets = [
|
|
22
|
+
req.url || '',
|
|
23
|
+
JSON.stringify(req.query || {}),
|
|
24
|
+
req.headers['referer'] || '',
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
if (req.body) targets.push(JSON.stringify(req.body));
|
|
28
|
+
|
|
29
|
+
for (const target of targets) {
|
|
30
|
+
for (const pattern of TRAVERSAL_PATTERNS) {
|
|
31
|
+
if (pattern.test(target)) {
|
|
32
|
+
threats.push(`Path traversal pattern: ${pattern.source.substring(0, 40)}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Deduplicate
|
|
38
|
+
const unique = [...new Set(threats)];
|
|
39
|
+
return { detected: unique.length > 0, threats: unique };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = { TRAVERSAL_PATTERNS, detectTraversal };
|
package/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// honeyweb-core/index.js
|
|
2
2
|
// HoneyWeb - Intelligent Honeypot Middleware
|
|
3
|
-
// Main entry point - orchestrates all modules
|
|
4
3
|
|
|
5
4
|
const { loadConfig } = require('./config');
|
|
6
5
|
const { createStorage } = require('./storage');
|
|
@@ -11,27 +10,18 @@ const Logger = require('./utils/logger');
|
|
|
11
10
|
const HoneyWebEvents = require('./utils/event-emitter');
|
|
12
11
|
const createMiddleware = require('./middleware');
|
|
13
12
|
|
|
14
|
-
/**
|
|
15
|
-
* HoneyWeb Middleware Factory
|
|
16
|
-
* @param {Object} userConfig - Optional configuration overrides
|
|
17
|
-
* @returns {Function} - Express middleware function with event emitter
|
|
18
|
-
*/
|
|
19
13
|
function honeyWeb(userConfig = {}) {
|
|
20
|
-
// 1. Load and merge configuration
|
|
21
14
|
const config = loadConfig(userConfig);
|
|
22
15
|
|
|
23
|
-
// 2. Initialize core components
|
|
24
16
|
const logger = new Logger(config.logging);
|
|
25
17
|
const events = new HoneyWebEvents();
|
|
26
18
|
const storage = createStorage(config.storage);
|
|
27
|
-
const botTracker = new BotTracker();
|
|
19
|
+
const botTracker = new BotTracker();
|
|
28
20
|
const detector = new DetectionEngine(config);
|
|
29
21
|
const aiAnalyzer = new AIAnalyzer(config.ai);
|
|
30
22
|
|
|
31
|
-
// 3. Create middleware
|
|
32
23
|
const middleware = createMiddleware(config, storage, botTracker, detector, aiAnalyzer, logger, events);
|
|
33
24
|
|
|
34
|
-
// 4. Attach event emitter and utilities to middleware function
|
|
35
25
|
middleware.on = events.on.bind(events);
|
|
36
26
|
middleware.once = events.once.bind(events);
|
|
37
27
|
middleware.off = events.off.bind(events);
|
|
@@ -42,7 +32,6 @@ function honeyWeb(userConfig = {}) {
|
|
|
42
32
|
middleware.logger = logger;
|
|
43
33
|
middleware.config = config;
|
|
44
34
|
|
|
45
|
-
// 5. Cleanup on process exit
|
|
46
35
|
const cleanup = () => {
|
|
47
36
|
detector.destroy();
|
|
48
37
|
storage.destroy();
|
|
@@ -60,5 +49,4 @@ function honeyWeb(userConfig = {}) {
|
|
|
60
49
|
return middleware;
|
|
61
50
|
}
|
|
62
51
|
|
|
63
|
-
// Export for backward compatibility
|
|
64
52
|
module.exports = honeyWeb;
|
|
@@ -1,27 +1,13 @@
|
|
|
1
|
-
// honeyweb-core/middleware/blocklist-checker.js
|
|
2
|
-
// Blocklist checking middleware
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Create blocklist checker middleware
|
|
6
|
-
* @param {Object} storage - Storage instance
|
|
7
|
-
* @param {Object} logger - Logger instance
|
|
8
|
-
* @param {Object} events - Event emitter
|
|
9
|
-
* @returns {Function} - Middleware function
|
|
10
|
-
*/
|
|
11
1
|
function createBlocklistChecker(storage, logger, events) {
|
|
12
2
|
return async function checkBlocklist(req, res, next) {
|
|
13
3
|
const clientIP = req.ip || req.connection.remoteAddress;
|
|
14
4
|
|
|
15
5
|
try {
|
|
16
6
|
const isBanned = await storage.isBanned(clientIP);
|
|
17
|
-
|
|
18
7
|
if (isBanned) {
|
|
19
8
|
logger.blocked(clientIP, 'IP is banned');
|
|
20
9
|
events.emitRequestBlocked(clientIP, 'IP is banned');
|
|
21
|
-
|
|
22
|
-
return res.status(403).send(
|
|
23
|
-
'<h1>403 Forbidden</h1><p>Your IP has been flagged for suspicious activity.</p>'
|
|
24
|
-
);
|
|
10
|
+
return res.status(403).send('<h1>403 Forbidden</h1><p>Your IP has been flagged for suspicious activity.</p>');
|
|
25
11
|
}
|
|
26
12
|
} catch (err) {
|
|
27
13
|
logger.error('Error checking blocklist', { error: err.message });
|