xypriss 3.2.1 → 3.2.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.
- package/README.md +98 -447
- package/dist/cjs/src/FiUp.js +85 -0
- package/dist/cjs/src/FiUp.js.map +1 -0
- package/dist/cjs/src/file-upload.js +14 -87
- package/dist/cjs/src/file-upload.js.map +1 -1
- package/dist/cjs/src/index.js +8 -5
- package/dist/cjs/src/index.js.map +1 -1
- package/dist/cjs/src/middleware/built-in/BuiltInMiddleware.js +51 -8
- package/dist/cjs/src/middleware/built-in/BuiltInMiddleware.js.map +1 -1
- package/dist/cjs/src/server/FastServer.js +9 -5
- package/dist/cjs/src/server/FastServer.js.map +1 -1
- package/dist/cjs/src/server/components/fastapi/FileUploadManager.js +31 -19
- package/dist/cjs/src/server/components/fastapi/FileUploadManager.js.map +1 -1
- package/dist/cjs/src/server/const/default.js +10 -6
- package/dist/cjs/src/server/const/default.js.map +1 -1
- package/dist/cjs/src/server/core/HttpServer.js +16 -7
- package/dist/cjs/src/server/core/HttpServer.js.map +1 -1
- package/dist/cjs/src/server/core/XyprissApp.js +2 -1
- package/dist/cjs/src/server/core/XyprissApp.js.map +1 -1
- package/dist/esm/src/FiUp.js +79 -0
- package/dist/esm/src/FiUp.js.map +1 -0
- package/dist/esm/src/file-upload.js +9 -83
- package/dist/esm/src/file-upload.js.map +1 -1
- package/dist/esm/src/index.js +3 -1
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/middleware/built-in/BuiltInMiddleware.js +51 -8
- package/dist/esm/src/middleware/built-in/BuiltInMiddleware.js.map +1 -1
- package/dist/esm/src/server/FastServer.js +9 -5
- package/dist/esm/src/server/FastServer.js.map +1 -1
- package/dist/esm/src/server/components/fastapi/FileUploadManager.js +31 -19
- package/dist/esm/src/server/components/fastapi/FileUploadManager.js.map +1 -1
- package/dist/esm/src/server/const/default.js +10 -6
- package/dist/esm/src/server/const/default.js.map +1 -1
- package/dist/esm/src/server/core/HttpServer.js +16 -7
- package/dist/esm/src/server/core/HttpServer.js.map +1 -1
- package/dist/esm/src/server/core/XyprissApp.js +2 -1
- package/dist/esm/src/server/core/XyprissApp.js.map +1 -1
- package/dist/index.d.ts +154 -99
- package/package.json +4 -4
- package/dist/cjs/mods/security/src/core/crypt.js +0 -56
- package/dist/cjs/mods/security/src/core/crypt.js.map +0 -1
- package/dist/cjs/src/middleware/built-in/index.js +0 -325
- package/dist/cjs/src/middleware/built-in/index.js.map +0 -1
- package/dist/cjs/src/middleware/built-in/sqlInjection.js +0 -335
- package/dist/cjs/src/middleware/built-in/sqlInjection.js.map +0 -1
- package/dist/cjs/src/server/conf/rateLimitConfig.js +0 -35
- package/dist/cjs/src/server/conf/rateLimitConfig.js.map +0 -1
- package/dist/cjs/src/server/utils/wildcardMatcher.js +0 -92
- package/dist/cjs/src/server/utils/wildcardMatcher.js.map +0 -1
- package/dist/esm/mods/security/src/core/crypt.js +0 -54
- package/dist/esm/mods/security/src/core/crypt.js.map +0 -1
- package/dist/esm/src/middleware/built-in/index.js +0 -323
- package/dist/esm/src/middleware/built-in/index.js.map +0 -1
- package/dist/esm/src/middleware/built-in/sqlInjection.js +0 -333
- package/dist/esm/src/middleware/built-in/sqlInjection.js.map +0 -1
- package/dist/esm/src/server/conf/rateLimitConfig.js +0 -33
- package/dist/esm/src/server/conf/rateLimitConfig.js.map +0 -1
- package/dist/esm/src/server/utils/wildcardMatcher.js +0 -88
- package/dist/esm/src/server/utils/wildcardMatcher.js.map +0 -1
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var helmet = require('helmet');
|
|
4
|
-
var cors = require('cors');
|
|
5
|
-
var rateLimit = require('express-rate-limit');
|
|
6
|
-
var compression = require('compression');
|
|
7
|
-
var hpp = require('hpp');
|
|
8
|
-
var mongoSanitize = require('express-mongo-sanitize');
|
|
9
|
-
var xss = require('xss');
|
|
10
|
-
var morgan = require('morgan');
|
|
11
|
-
var slowDown = require('express-slow-down');
|
|
12
|
-
var ExpressBrute = require('express-brute');
|
|
13
|
-
var multer = require('multer');
|
|
14
|
-
var csrfCsrf = require('csrf-csrf');
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* XyPriss Built-in Middleware
|
|
18
|
-
* Wrappers around popular middleware libraries
|
|
19
|
-
*/
|
|
20
|
-
class BuiltInMiddleware {
|
|
21
|
-
/**
|
|
22
|
-
* Get Helmet middleware for security headers
|
|
23
|
-
*/
|
|
24
|
-
static helmet(options = {}) {
|
|
25
|
-
const defaultOptions = {
|
|
26
|
-
contentSecurityPolicy: {
|
|
27
|
-
directives: {
|
|
28
|
-
defaultSrc: ["'self'"],
|
|
29
|
-
scriptSrc: ["'self'"],
|
|
30
|
-
styleSrc: ["'self'", "'unsafe-inline'"],
|
|
31
|
-
imgSrc: ["'self'", "data:"],
|
|
32
|
-
fontSrc: ["'self'"],
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
crossOriginEmbedderPolicy: true,
|
|
36
|
-
crossOriginOpenerPolicy: true,
|
|
37
|
-
crossOriginResourcePolicy: { policy: "same-origin" },
|
|
38
|
-
dnsPrefetchControl: { allow: false },
|
|
39
|
-
frameguard: { action: "deny" },
|
|
40
|
-
hidePoweredBy: true,
|
|
41
|
-
hsts: {
|
|
42
|
-
maxAge: 31536000,
|
|
43
|
-
includeSubDomains: true,
|
|
44
|
-
preload: false,
|
|
45
|
-
},
|
|
46
|
-
ieNoOpen: true,
|
|
47
|
-
noSniff: true,
|
|
48
|
-
originAgentCluster: true,
|
|
49
|
-
permittedCrossDomainPolicies: false,
|
|
50
|
-
referrerPolicy: { policy: "strict-origin-when-cross-origin" },
|
|
51
|
-
xssFilter: true,
|
|
52
|
-
};
|
|
53
|
-
const config = { ...defaultOptions, ...options };
|
|
54
|
-
return helmet(config);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Get CORS middleware
|
|
58
|
-
*/
|
|
59
|
-
static cors(options = {}) {
|
|
60
|
-
const defaultOptions = {
|
|
61
|
-
origin: true,
|
|
62
|
-
methods: ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"],
|
|
63
|
-
allowedHeaders: [
|
|
64
|
-
"Content-Type",
|
|
65
|
-
"Authorization",
|
|
66
|
-
"X-Requested-With",
|
|
67
|
-
],
|
|
68
|
-
credentials: false,
|
|
69
|
-
maxAge: 86400, // 24 hours
|
|
70
|
-
};
|
|
71
|
-
const config = { ...defaultOptions, ...options };
|
|
72
|
-
return cors(config);
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Get Rate Limiting middleware
|
|
76
|
-
*/
|
|
77
|
-
static rateLimit(options = {}) {
|
|
78
|
-
const defaultOptions = {
|
|
79
|
-
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
80
|
-
max: 100, // limit each IP to 100 requests per windowMs
|
|
81
|
-
message: {
|
|
82
|
-
error: "Too many requests from this IP, please try again later.",
|
|
83
|
-
retryAfter: "Please try again later.",
|
|
84
|
-
},
|
|
85
|
-
standardHeaders: true,
|
|
86
|
-
legacyHeaders: false,
|
|
87
|
-
handler: (_req, res) => {
|
|
88
|
-
res.status(429).json({
|
|
89
|
-
error: "Too many requests",
|
|
90
|
-
message: "Rate limit exceeded. Please try again later.",
|
|
91
|
-
retryAfter: Math.ceil(options.windowMs / 1000) || 900,
|
|
92
|
-
});
|
|
93
|
-
},
|
|
94
|
-
};
|
|
95
|
-
const config = { ...defaultOptions, ...options };
|
|
96
|
-
return rateLimit(config);
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Get Compression middleware
|
|
100
|
-
*/
|
|
101
|
-
static compression(options = {}) {
|
|
102
|
-
const defaultOptions = {
|
|
103
|
-
level: 6,
|
|
104
|
-
threshold: 1024, // Only compress responses >= 1KB
|
|
105
|
-
filter: (req, res) => {
|
|
106
|
-
// Don't compress responses with this request header
|
|
107
|
-
if (req.headers["x-no-compression"]) {
|
|
108
|
-
return false;
|
|
109
|
-
}
|
|
110
|
-
// Fallback to standard filter function
|
|
111
|
-
return compression.filter(req, res);
|
|
112
|
-
},
|
|
113
|
-
};
|
|
114
|
-
const config = { ...defaultOptions, ...options };
|
|
115
|
-
return compression(config);
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* CSRF protection middleware using csrf-csrf library
|
|
119
|
-
*/
|
|
120
|
-
static csrf(options = {}) {
|
|
121
|
-
const defaultOptions = {
|
|
122
|
-
getSecret: () => "your-secret-key", // In production, use a proper secret
|
|
123
|
-
cookieName: "__Host-psifi.x-csrf-token",
|
|
124
|
-
cookieOptions: {
|
|
125
|
-
httpOnly: true,
|
|
126
|
-
sameSite: "strict",
|
|
127
|
-
secure: process.env.NODE_ENV === "production",
|
|
128
|
-
maxAge: 3600000, // 1 hour
|
|
129
|
-
},
|
|
130
|
-
size: 64,
|
|
131
|
-
ignoredMethods: ["GET", "HEAD", "OPTIONS"],
|
|
132
|
-
getTokenFromRequest: (req) => {
|
|
133
|
-
return (req.headers["x-csrf-token"] ||
|
|
134
|
-
req.body?._csrf ||
|
|
135
|
-
req.query?._csrf);
|
|
136
|
-
},
|
|
137
|
-
};
|
|
138
|
-
const config = { ...defaultOptions, ...options };
|
|
139
|
-
const { doubleCsrfProtection } = csrfCsrf.doubleCsrf(config);
|
|
140
|
-
// Return the protection middleware
|
|
141
|
-
return doubleCsrfProtection;
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Get Express Validator middleware for input validation
|
|
145
|
-
* Simplified implementation - users should install express-validator separately
|
|
146
|
-
*/
|
|
147
|
-
static validator(options = {}) {
|
|
148
|
-
const defaultOptions = {
|
|
149
|
-
sanitizeBody: true,
|
|
150
|
-
checkBody: true,
|
|
151
|
-
checkQuery: true,
|
|
152
|
-
checkParams: true,
|
|
153
|
-
};
|
|
154
|
-
({ ...defaultOptions, ...options });
|
|
155
|
-
return (req, res, next) => {
|
|
156
|
-
// Basic validation middleware - simplified
|
|
157
|
-
// In production, use express-validator library directly
|
|
158
|
-
console.log("[Validator] Basic validation middleware active");
|
|
159
|
-
// Add basic validation helpers to request
|
|
160
|
-
req.validation = {
|
|
161
|
-
body: (field) => req.body?.[field],
|
|
162
|
-
query: (field) => req.query?.[field],
|
|
163
|
-
params: (field) => req.params?.[field],
|
|
164
|
-
};
|
|
165
|
-
next();
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Get HPP (HTTP Parameter Pollution) protection middleware
|
|
170
|
-
*/
|
|
171
|
-
static hpp(options = {}) {
|
|
172
|
-
const defaultOptions = {
|
|
173
|
-
whitelist: ["tags", "categories"], // Allow arrays for these parameters
|
|
174
|
-
};
|
|
175
|
-
const config = { ...defaultOptions, ...options };
|
|
176
|
-
return hpp(config);
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Get MongoDB injection protection middleware
|
|
180
|
-
*/
|
|
181
|
-
static mongoSanitize(options = {}) {
|
|
182
|
-
const defaultOptions = {
|
|
183
|
-
replaceWith: "_",
|
|
184
|
-
onSanitize: (key, value) => {
|
|
185
|
-
console.warn(`[MongoSanitize] Sanitized key: ${key}, value: ${value}`);
|
|
186
|
-
},
|
|
187
|
-
};
|
|
188
|
-
const config = { ...defaultOptions, ...options };
|
|
189
|
-
return mongoSanitize(config);
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Get XSS protection middleware
|
|
193
|
-
*/
|
|
194
|
-
static xss(options = {}) {
|
|
195
|
-
const defaultOptions = {
|
|
196
|
-
whiteList: {
|
|
197
|
-
a: ["href", "title"],
|
|
198
|
-
b: [],
|
|
199
|
-
i: [],
|
|
200
|
-
strong: [],
|
|
201
|
-
em: [],
|
|
202
|
-
},
|
|
203
|
-
};
|
|
204
|
-
const config = { ...defaultOptions, ...options };
|
|
205
|
-
return (req, _res, next) => {
|
|
206
|
-
// Sanitize request body
|
|
207
|
-
if (req.body) {
|
|
208
|
-
req.body = this.sanitizeObject(req.body, config);
|
|
209
|
-
}
|
|
210
|
-
// Sanitize query parameters
|
|
211
|
-
if (req.query) {
|
|
212
|
-
req.query = this.sanitizeObject(req.query, config);
|
|
213
|
-
}
|
|
214
|
-
next();
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* Get Morgan logging middleware
|
|
219
|
-
*/
|
|
220
|
-
static morgan(options = {}) {
|
|
221
|
-
const defaultFormat = options.format || "combined";
|
|
222
|
-
const defaultOptions = {
|
|
223
|
-
skip: (_req, res) => res.statusCode < 400, // Only log errors by default
|
|
224
|
-
stream: process.stdout,
|
|
225
|
-
};
|
|
226
|
-
const config = { ...defaultOptions, ...options };
|
|
227
|
-
return morgan(defaultFormat, config);
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* Get Slow Down middleware for progressive delays
|
|
231
|
-
*/
|
|
232
|
-
static slowDown(options = {}) {
|
|
233
|
-
const defaultOptions = {
|
|
234
|
-
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
235
|
-
delayAfter: 2, // Allow 2 requests per windowMs without delay
|
|
236
|
-
delayMs: 500, // Add 500ms delay per request after delayAfter
|
|
237
|
-
maxDelayMs: 20000, // Maximum delay of 20 seconds
|
|
238
|
-
skipFailedRequests: false,
|
|
239
|
-
skipSuccessfulRequests: false,
|
|
240
|
-
};
|
|
241
|
-
const config = { ...defaultOptions, ...options };
|
|
242
|
-
return slowDown(config);
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* Get Express Brute middleware for brute force protection
|
|
246
|
-
*/
|
|
247
|
-
static brute(options = {}) {
|
|
248
|
-
const store = new ExpressBrute.MemoryStore();
|
|
249
|
-
const defaultOptions = {
|
|
250
|
-
freeRetries: 2,
|
|
251
|
-
minWait: 5 * 60 * 1000, // 5 minutes
|
|
252
|
-
maxWait: 60 * 60 * 1000, // 1 hour
|
|
253
|
-
lifetime: 24 * 60 * 60, // 1 day (in seconds)
|
|
254
|
-
failCallback: (_req, res, _next, nextValidRequestDate) => {
|
|
255
|
-
res.status(429).json({
|
|
256
|
-
error: "Too many failed attempts",
|
|
257
|
-
message: "Account temporarily locked due to too many failed attempts",
|
|
258
|
-
nextValidRequestDate: nextValidRequestDate,
|
|
259
|
-
});
|
|
260
|
-
},
|
|
261
|
-
};
|
|
262
|
-
const config = { ...defaultOptions, ...options };
|
|
263
|
-
const bruteforce = new ExpressBrute(store, config);
|
|
264
|
-
return bruteforce.prevent;
|
|
265
|
-
}
|
|
266
|
-
/**
|
|
267
|
-
* Get Multer middleware for file uploads
|
|
268
|
-
*/
|
|
269
|
-
static multer(options = {}) {
|
|
270
|
-
const defaultOptions = {
|
|
271
|
-
limits: {
|
|
272
|
-
fileSize: 5 * 1024 * 1024, // 5MB limit
|
|
273
|
-
files: 5, // Maximum 5 files
|
|
274
|
-
},
|
|
275
|
-
fileFilter: (_req, file, cb) => {
|
|
276
|
-
// Allow only specific file types
|
|
277
|
-
const allowedTypes = /jpeg|jpg|png|gif|pdf|doc|docx/;
|
|
278
|
-
const extname = allowedTypes.test(file.originalname.toLowerCase());
|
|
279
|
-
const mimetype = allowedTypes.test(file.mimetype);
|
|
280
|
-
if (mimetype && extname) {
|
|
281
|
-
return cb(null, true);
|
|
282
|
-
}
|
|
283
|
-
else {
|
|
284
|
-
cb(new Error("Invalid file type. Only images and documents are allowed."));
|
|
285
|
-
}
|
|
286
|
-
},
|
|
287
|
-
};
|
|
288
|
-
const config = { ...defaultOptions, ...options };
|
|
289
|
-
return multer(config);
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
* Get all default security middleware
|
|
293
|
-
*/
|
|
294
|
-
static security(options = {}) {
|
|
295
|
-
return {
|
|
296
|
-
helmet: this.helmet(options.helmet),
|
|
297
|
-
cors: this.cors(options.cors),
|
|
298
|
-
rateLimit: this.rateLimit(options.rateLimit),
|
|
299
|
-
compression: this.compression(options.compression),
|
|
300
|
-
csrf: this.csrf(options.csrf),
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
// Helper method for XSS sanitization
|
|
304
|
-
static sanitizeObject(obj, config) {
|
|
305
|
-
if (typeof obj === "string") {
|
|
306
|
-
return xss(obj, config);
|
|
307
|
-
}
|
|
308
|
-
else if (Array.isArray(obj)) {
|
|
309
|
-
return obj.map((item) => this.sanitizeObject(item, config));
|
|
310
|
-
}
|
|
311
|
-
else if (obj && typeof obj === "object") {
|
|
312
|
-
const sanitized = {};
|
|
313
|
-
for (const key in obj) {
|
|
314
|
-
if (obj.hasOwnProperty(key)) {
|
|
315
|
-
sanitized[key] = this.sanitizeObject(obj[key], config);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
return sanitized;
|
|
319
|
-
}
|
|
320
|
-
return obj;
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
exports.BuiltInMiddleware = BuiltInMiddleware;
|
|
325
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../../src/middleware/built-in/index.ts"],"sourcesContent":[null],"names":["doubleCsrf"],"mappings":"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"}
|
|
@@ -1,335 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
class SQLInjectionDetector {
|
|
4
|
-
constructor(config = {}) {
|
|
5
|
-
// High-confidence SQL injection patterns (more specific to reduce false positives)
|
|
6
|
-
this.highRiskPatterns = [
|
|
7
|
-
// Union attacks with SELECT
|
|
8
|
-
/(\s|^)(union|UNION)(\s)+(all\s+)?(select|SELECT)/gi,
|
|
9
|
-
// SQL comments at end of input or before SQL keywords
|
|
10
|
-
/(--|#|\/\*).*?(select|union|drop|delete|insert|update|create|alter)/gi,
|
|
11
|
-
/;(\s)*--.*/gi,
|
|
12
|
-
// Enhanced boolean injections (more comprehensive)
|
|
13
|
-
/(\s|^)(or|OR)(\s)+('?\d+'?\s*=\s*'?\d+'?|'[^']*'\s*=\s*'[^']*'|true|false)/gi,
|
|
14
|
-
/(\s|^)(and|AND)(\s)+('?\d+'?\s*=\s*'?\d+'?|'[^']*'\s*=\s*'[^']*'|true|false)/gi,
|
|
15
|
-
// Quote-based boolean injections
|
|
16
|
-
/'(\s)+(or|OR|and|AND)(\s)+'/gi,
|
|
17
|
-
// Comment-obfuscated patterns
|
|
18
|
-
/\/\*.*?\*\/(or|OR|and|AND)\/\*.*?\*\//gi,
|
|
19
|
-
// Time-based with specific syntax (enhanced)
|
|
20
|
-
/(sleep|SLEEP|waitfor|WAITFOR|delay|DELAY)\s*\(.*?\)/gi,
|
|
21
|
-
/(waitfor|WAITFOR)\s+(delay|DELAY)\s+'/gi,
|
|
22
|
-
// System stored procedures
|
|
23
|
-
/(exec|EXEC|execute|EXECUTE)\s+(sp_|xp_)\w+/gi,
|
|
24
|
-
// Information schema with specific queries
|
|
25
|
-
/(information_schema|INFORMATION_SCHEMA)\.(tables|columns|schemata)/gi,
|
|
26
|
-
// Dangerous DDL operations with semicolons
|
|
27
|
-
/;(\s)*(drop|DROP|delete|DELETE|truncate|TRUNCATE)\s+(table|database)/gi,
|
|
28
|
-
// Hex encoding of common injection strings
|
|
29
|
-
/0x(27|22|5C|2D|2D)/gi, // ', ", \, --
|
|
30
|
-
// Multiple quotes for quote breaking
|
|
31
|
-
/('{3,}|"{3,})/g,
|
|
32
|
-
// Stacked queries with dangerous operations
|
|
33
|
-
/;(\s)*(drop|delete|insert|update|create|alter)(\s)+/gi,
|
|
34
|
-
];
|
|
35
|
-
// Medium risk patterns (require context analysis)
|
|
36
|
-
this.mediumRiskPatterns = [
|
|
37
|
-
// Single SQL keywords (common in legitimate text)
|
|
38
|
-
/\b(select|union|drop|delete|insert|update|create|alter)\b/gi,
|
|
39
|
-
// Simple OR/AND conditions
|
|
40
|
-
/\b(or|and)\s+\w+\s*=\s*\w+/gi,
|
|
41
|
-
// Single quotes or double quotes
|
|
42
|
-
/'/g,
|
|
43
|
-
/"/g,
|
|
44
|
-
// Basic SQL comments
|
|
45
|
-
/(--|#)/g,
|
|
46
|
-
// Wildcards
|
|
47
|
-
/[%_]/g,
|
|
48
|
-
];
|
|
49
|
-
// Characters that are suspicious in certain contexts
|
|
50
|
-
this.contextSensitiveChars = /[';\"\\%_]/g;
|
|
51
|
-
this.config = {
|
|
52
|
-
strictMode: config.strictMode ?? false,
|
|
53
|
-
allowedChars: config.allowedChars ?? /^[a-zA-Z0-9\s\-@.!?,()]+$/,
|
|
54
|
-
maxLength: config.maxLength ?? 1000,
|
|
55
|
-
logAttempts: config.logAttempts ?? true,
|
|
56
|
-
contextualAnalysis: config.contextualAnalysis ?? true,
|
|
57
|
-
falsePositiveThreshold: config.falsePositiveThreshold ?? 0.6,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Main detection method with improved false positive handling
|
|
62
|
-
*/
|
|
63
|
-
detect(input, context) {
|
|
64
|
-
if (!input || typeof input !== "string") {
|
|
65
|
-
return {
|
|
66
|
-
isMalicious: false,
|
|
67
|
-
confidence: 0,
|
|
68
|
-
detectedPatterns: [],
|
|
69
|
-
riskLevel: "LOW",
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
const result = {
|
|
73
|
-
isMalicious: false,
|
|
74
|
-
confidence: 0,
|
|
75
|
-
detectedPatterns: [],
|
|
76
|
-
sanitizedInput: input,
|
|
77
|
-
riskLevel: "LOW",
|
|
78
|
-
};
|
|
79
|
-
// Check input length (very long inputs are suspicious)
|
|
80
|
-
if (input.length > this.config.maxLength) {
|
|
81
|
-
result.confidence += 0.2; // Reduced penalty for length
|
|
82
|
-
result.detectedPatterns.push("Excessive length");
|
|
83
|
-
}
|
|
84
|
-
// High-risk pattern analysis (strong indicators)
|
|
85
|
-
let highRiskScore = 0;
|
|
86
|
-
this.highRiskPatterns.forEach((pattern, index) => {
|
|
87
|
-
const matches = input.match(pattern);
|
|
88
|
-
if (matches) {
|
|
89
|
-
const patternName = this.getHighRiskPatternName(index);
|
|
90
|
-
result.detectedPatterns.push(`${patternName}: ${matches.join(", ")}`);
|
|
91
|
-
highRiskScore += this.getHighRiskPatternWeight(index);
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
// Medium-risk pattern analysis (context-dependent)
|
|
95
|
-
let mediumRiskScore = 0;
|
|
96
|
-
if (this.config.contextualAnalysis) {
|
|
97
|
-
mediumRiskScore = this.analyzeContext(input, context || "");
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
// Basic medium risk analysis without context
|
|
101
|
-
this.mediumRiskPatterns.forEach((pattern, index) => {
|
|
102
|
-
const matches = input.match(pattern);
|
|
103
|
-
if (matches) {
|
|
104
|
-
mediumRiskScore += 0.1 * matches.length; // Lower weight for medium risk
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
// Contextual analysis for legitimate use cases
|
|
109
|
-
const legitimacyScore = this.calculateLegitimacyScore(input);
|
|
110
|
-
// Calculate confidence with false positive mitigation
|
|
111
|
-
const rawScore = highRiskScore + mediumRiskScore * 0.3;
|
|
112
|
-
result.confidence = Math.max(0, rawScore - legitimacyScore);
|
|
113
|
-
result.confidence = Math.min(result.confidence, 1.0);
|
|
114
|
-
// Determine risk level and malicious status
|
|
115
|
-
if (result.confidence >= 0.8) {
|
|
116
|
-
result.riskLevel = "CRITICAL";
|
|
117
|
-
result.isMalicious = true;
|
|
118
|
-
}
|
|
119
|
-
else if (result.confidence >= this.config.falsePositiveThreshold) {
|
|
120
|
-
result.riskLevel = "HIGH";
|
|
121
|
-
result.isMalicious = true;
|
|
122
|
-
}
|
|
123
|
-
else if (result.confidence >= 0.3) {
|
|
124
|
-
result.riskLevel = "MEDIUM";
|
|
125
|
-
result.isMalicious = false; // Don't block medium risk by default
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
result.riskLevel = "LOW";
|
|
129
|
-
result.isMalicious = false;
|
|
130
|
-
}
|
|
131
|
-
// Log only high confidence attempts
|
|
132
|
-
if (this.config.logAttempts && result.confidence >= 0.7) {
|
|
133
|
-
this.logAttempt(input, result);
|
|
134
|
-
}
|
|
135
|
-
// Provide sanitized version only for high-risk inputs
|
|
136
|
-
if (result.confidence >= 0.4) {
|
|
137
|
-
result.sanitizedInput = this.smartSanitize(input);
|
|
138
|
-
}
|
|
139
|
-
return result;
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Analyze context to reduce false positives
|
|
143
|
-
*/
|
|
144
|
-
analyzeContext(input, context) {
|
|
145
|
-
let score = 0;
|
|
146
|
-
// Check for legitimate business contexts
|
|
147
|
-
const businessContexts = [
|
|
148
|
-
"search",
|
|
149
|
-
"filter",
|
|
150
|
-
"name",
|
|
151
|
-
"description",
|
|
152
|
-
"comment",
|
|
153
|
-
"review",
|
|
154
|
-
"address",
|
|
155
|
-
"title",
|
|
156
|
-
"content",
|
|
157
|
-
"message",
|
|
158
|
-
"email",
|
|
159
|
-
];
|
|
160
|
-
const isBusinessContext = businessContexts.some((ctx) => context.toLowerCase().includes(ctx));
|
|
161
|
-
this.mediumRiskPatterns.forEach((pattern, index) => {
|
|
162
|
-
const matches = input.match(pattern);
|
|
163
|
-
if (matches) {
|
|
164
|
-
let patternScore = 0.1 * matches.length;
|
|
165
|
-
// Reduce score for legitimate contexts
|
|
166
|
-
if (isBusinessContext) {
|
|
167
|
-
patternScore *= 0.3; // Reduce by 70%
|
|
168
|
-
}
|
|
169
|
-
// Special handling for common false positives
|
|
170
|
-
if (index === 0 && isBusinessContext) {
|
|
171
|
-
// SQL keywords in business text
|
|
172
|
-
patternScore *= 0.1; // Very low weight for SQL keywords in business context
|
|
173
|
-
}
|
|
174
|
-
if (index === 2 || index === 3) {
|
|
175
|
-
// Single quotes in names, descriptions
|
|
176
|
-
if (context.includes("name") ||
|
|
177
|
-
context.includes("description")) {
|
|
178
|
-
patternScore *= 0.2;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
score += patternScore;
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
return score;
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Calculate legitimacy score to offset false positives
|
|
188
|
-
*/
|
|
189
|
-
calculateLegitimacyScore(input) {
|
|
190
|
-
let legitimacyScore = 0;
|
|
191
|
-
// Natural language indicators
|
|
192
|
-
const naturalWords = input.match(/\b[a-zA-Z]{3,}\b/g);
|
|
193
|
-
if (naturalWords && naturalWords.length > 2) {
|
|
194
|
-
legitimacyScore += 0.2; // Looks like natural text
|
|
195
|
-
}
|
|
196
|
-
// Check for common legitimate patterns
|
|
197
|
-
const legitimatePatterns = [
|
|
198
|
-
/^[A-Z][a-z]+\s[A-Z][a-z]+$/, // First Last name
|
|
199
|
-
/^[\w\.-]+@[\w\.-]+\.\w+$/, // Email
|
|
200
|
-
/^\d{1,5}\s\w+(\s\w+)*$/, // Address format
|
|
201
|
-
/^[A-Za-z0-9\s\-.,!?()]+$/, // Normal text with punctuation
|
|
202
|
-
];
|
|
203
|
-
legitimatePatterns.forEach((pattern) => {
|
|
204
|
-
if (pattern.test(input)) {
|
|
205
|
-
legitimacyScore += 0.15;
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
// Length-based legitimacy (very short or very specific lengths are more suspicious)
|
|
209
|
-
if (input.length > 10 && input.length < 200) {
|
|
210
|
-
legitimacyScore += 0.1;
|
|
211
|
-
}
|
|
212
|
-
// Check for balanced quotes (legitimate text often has balanced quotes)
|
|
213
|
-
const singleQuotes = (input.match(/'/g) || []).length;
|
|
214
|
-
const doubleQuotes = (input.match(/"/g) || []).length;
|
|
215
|
-
if (singleQuotes % 2 === 0 && doubleQuotes % 2 === 0) {
|
|
216
|
-
legitimacyScore += 0.1;
|
|
217
|
-
}
|
|
218
|
-
return Math.min(legitimacyScore, 0.5); // Cap legitimacy score
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Smart sanitization that preserves legitimate content
|
|
222
|
-
*/
|
|
223
|
-
smartSanitize(input) {
|
|
224
|
-
if (!input)
|
|
225
|
-
return input;
|
|
226
|
-
let sanitized = input;
|
|
227
|
-
// Only remove obvious SQL injection patterns, not all SQL keywords
|
|
228
|
-
sanitized = sanitized.replace(/(--|#).*$/gm, ""); // Remove comment tails
|
|
229
|
-
sanitized = sanitized.replace(/\/\*.*?\*\//g, ""); // Remove /* */ comments
|
|
230
|
-
// Only escape quotes if they appear to be part of injection attempts
|
|
231
|
-
const suspiciousQuotes = /'(\s*(or|and|union|select)\s|;|\s*--)/gi;
|
|
232
|
-
sanitized = sanitized.replace(suspiciousQuotes, "''$1");
|
|
233
|
-
// Remove only dangerous control characters
|
|
234
|
-
sanitized = sanitized.replace(/[\x00\x1a]/g, "");
|
|
235
|
-
// Only remove semicolons if followed by SQL keywords
|
|
236
|
-
sanitized = sanitized.replace(/;(\s)*(drop|delete|insert|update|create|alter|union|select)/gi, " $2");
|
|
237
|
-
return sanitized.trim();
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* Validate and sanitize input, throwing error if malicious
|
|
241
|
-
*/
|
|
242
|
-
validateAndSanitize(input, throwOnDetection = false) {
|
|
243
|
-
const result = this.detect(input);
|
|
244
|
-
if (result.isMalicious && throwOnDetection) {
|
|
245
|
-
throw new Error(`SQL injection attempt detected. Confidence: ${(result.confidence * 100).toFixed(1)}%. ` +
|
|
246
|
-
`Patterns: ${result.detectedPatterns.join(", ")}`);
|
|
247
|
-
}
|
|
248
|
-
return result.sanitizedInput || "";
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Create parameterized query helper
|
|
252
|
-
*/
|
|
253
|
-
createParameterizedQuery(query, params) {
|
|
254
|
-
// Simple parameterization helper
|
|
255
|
-
let parameterizedQuery = query;
|
|
256
|
-
const safeParams = [];
|
|
257
|
-
params.forEach((param, index) => {
|
|
258
|
-
if (typeof param === "string") {
|
|
259
|
-
const result = this.detect(param);
|
|
260
|
-
if (result.isMalicious) {
|
|
261
|
-
throw new Error(`Parameter ${index} contains potential SQL injection`);
|
|
262
|
-
}
|
|
263
|
-
safeParams.push(result.sanitizedInput);
|
|
264
|
-
}
|
|
265
|
-
else {
|
|
266
|
-
safeParams.push(param);
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
return { query: parameterizedQuery, params: safeParams };
|
|
270
|
-
}
|
|
271
|
-
getHighRiskPatternName(index) {
|
|
272
|
-
const names = [
|
|
273
|
-
"Union-Select attack",
|
|
274
|
-
"Commented injection",
|
|
275
|
-
"Comment with semicolon",
|
|
276
|
-
"Enhanced boolean OR",
|
|
277
|
-
"Enhanced boolean AND",
|
|
278
|
-
"Quote-based boolean",
|
|
279
|
-
"Comment-obfuscated injection",
|
|
280
|
-
"Time-based delay",
|
|
281
|
-
"WAITFOR delay attack",
|
|
282
|
-
"System procedure call",
|
|
283
|
-
"Information schema query",
|
|
284
|
-
"DDL with semicolon",
|
|
285
|
-
"Hex-encoded injection",
|
|
286
|
-
"Quote sequence attack",
|
|
287
|
-
"Stacked query attack",
|
|
288
|
-
];
|
|
289
|
-
return names[index] || `High-risk pattern ${index}`;
|
|
290
|
-
}
|
|
291
|
-
getHighRiskPatternWeight(index) {
|
|
292
|
-
// Higher weights for more definitive attack patterns
|
|
293
|
-
const weights = [
|
|
294
|
-
0.9, // Union-Select attack
|
|
295
|
-
0.8, // Commented injection
|
|
296
|
-
0.7, // Comment with semicolon
|
|
297
|
-
0.8, // Enhanced boolean OR
|
|
298
|
-
0.8, // Enhanced boolean AND
|
|
299
|
-
0.7, // Quote-based boolean
|
|
300
|
-
0.8, // Comment-obfuscated injection
|
|
301
|
-
0.9, // Time-based delay
|
|
302
|
-
0.8, // WAITFOR delay attack
|
|
303
|
-
0.8, // System procedure call
|
|
304
|
-
0.7, // Information schema query
|
|
305
|
-
0.9, // DDL with semicolon
|
|
306
|
-
0.6, // Hex-encoded injection
|
|
307
|
-
0.5, // Quote sequence attack
|
|
308
|
-
0.8, // Stacked query attack
|
|
309
|
-
];
|
|
310
|
-
return weights[index] || 0.7;
|
|
311
|
-
}
|
|
312
|
-
logAttempt(input, result) {
|
|
313
|
-
console.warn(`SQL Injection Attempt Detected:`, {
|
|
314
|
-
timestamp: new Date().toISOString(),
|
|
315
|
-
input: input.substring(0, 100) + (input.length > 100 ? "..." : ""),
|
|
316
|
-
confidence: result.confidence,
|
|
317
|
-
patterns: result.detectedPatterns,
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
/**
|
|
321
|
-
* Update configuration
|
|
322
|
-
*/
|
|
323
|
-
updateConfig(newConfig) {
|
|
324
|
-
this.config = { ...this.config, ...newConfig };
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Get current configuration
|
|
328
|
-
*/
|
|
329
|
-
getConfig() {
|
|
330
|
-
return { ...this.config };
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
module.exports = SQLInjectionDetector;
|
|
335
|
-
//# sourceMappingURL=sqlInjection.js.map
|