mdefender-pro 1.2.6 → 1.2.7
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/client.mjs +78 -3
- package/package.json +1 -1
package/client.mjs
CHANGED
|
@@ -481,6 +481,20 @@ export function initWaf(options = {}) {
|
|
|
481
481
|
const backendUrl = (options.backendUrl || 'http://localhost:8000').replace(/\/+$/, '');
|
|
482
482
|
const domain = options.domain || window.location.hostname || 'localhost';
|
|
483
483
|
|
|
484
|
+
// 0. Auto-inspect current page URL on load (e.g. ?q=<script> or ?id=1 UNION SELECT)
|
|
485
|
+
try {
|
|
486
|
+
const currentUrlParams = (window.location.search || '') + ' ' + (window.location.hash || '');
|
|
487
|
+
if (currentUrlParams.trim()) {
|
|
488
|
+
const normUrl = normalizeInput(currentUrlParams);
|
|
489
|
+
for (const pattern of ATTACK_PATTERNS) {
|
|
490
|
+
if (pattern.regex.test(normUrl)) {
|
|
491
|
+
renderOfficialBlockPage(pattern.type, null, domain);
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
} catch (e) {}
|
|
497
|
+
|
|
484
498
|
// 1. Wrap window.fetch for outgoing requests
|
|
485
499
|
const originalFetch = window.fetch;
|
|
486
500
|
window.fetch = async (input, init, ...args) => {
|
|
@@ -491,6 +505,7 @@ export function initWaf(options = {}) {
|
|
|
491
505
|
else if (url.includes('#')) targetParamStr = url.substring(url.indexOf('#'));
|
|
492
506
|
} catch (e) {}
|
|
493
507
|
|
|
508
|
+
// Inspect URL
|
|
494
509
|
if (targetParamStr) {
|
|
495
510
|
const normParams = normalizeInput(targetParamStr);
|
|
496
511
|
for (const pattern of ATTACK_PATTERNS) {
|
|
@@ -501,14 +516,36 @@ export function initWaf(options = {}) {
|
|
|
501
516
|
}
|
|
502
517
|
}
|
|
503
518
|
|
|
519
|
+
// Inspect Body if POST/PUT
|
|
520
|
+
if (init && init.body) {
|
|
521
|
+
try {
|
|
522
|
+
const bodyStr = typeof init.body === 'string' ? init.body : JSON.stringify(init.body);
|
|
523
|
+
const normBody = normalizeInput(bodyStr);
|
|
524
|
+
for (const pattern of ATTACK_PATTERNS) {
|
|
525
|
+
if (pattern.regex.test(normBody)) {
|
|
526
|
+
renderOfficialBlockPage(pattern.type, null, domain);
|
|
527
|
+
throw new Error(`[MDefender WAF] Outgoing payload attack blocked: ${pattern.type}`);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
} catch (e) {}
|
|
531
|
+
}
|
|
532
|
+
|
|
504
533
|
try {
|
|
505
534
|
const response = await originalFetch(input, init, ...args);
|
|
506
535
|
if (response.status === 403) {
|
|
507
536
|
const clone = response.clone();
|
|
508
537
|
try {
|
|
509
538
|
const text = await clone.text();
|
|
510
|
-
|
|
511
|
-
|
|
539
|
+
const statusHeader = response.headers.get('x-mdefender-status');
|
|
540
|
+
const attackHeader = response.headers.get('x-mdefender-attack-type');
|
|
541
|
+
const refHeader = response.headers.get('x-mdefender-ref');
|
|
542
|
+
if (statusHeader === 'blocked' || text.includes('403') || text.includes('MDefender') || text.includes('Access Denied')) {
|
|
543
|
+
if (text.includes('<!DOCTYPE html>') || text.includes('<html')) {
|
|
544
|
+
try { window.stop(); } catch (e) {}
|
|
545
|
+
document.documentElement.innerHTML = text;
|
|
546
|
+
} else {
|
|
547
|
+
renderOfficialBlockPage(attackHeader || 'Cross-Site Scripting (XSS)', refHeader, domain);
|
|
548
|
+
}
|
|
512
549
|
}
|
|
513
550
|
} catch (e) {}
|
|
514
551
|
}
|
|
@@ -518,7 +555,7 @@ export function initWaf(options = {}) {
|
|
|
518
555
|
}
|
|
519
556
|
};
|
|
520
557
|
|
|
521
|
-
// 2. Wrap XMLHttpRequest
|
|
558
|
+
// 2. Wrap XMLHttpRequest (Used by Axios, Redux Toolkit Query, etc.)
|
|
522
559
|
const originalOpen = XMLHttpRequest.prototype.open;
|
|
523
560
|
XMLHttpRequest.prototype.open = function (method, url, ...rest) {
|
|
524
561
|
let targetParamStr = '';
|
|
@@ -538,6 +575,44 @@ export function initWaf(options = {}) {
|
|
|
538
575
|
}
|
|
539
576
|
return originalOpen.apply(this, [method, url, ...rest]);
|
|
540
577
|
};
|
|
578
|
+
|
|
579
|
+
const originalSend = XMLHttpRequest.prototype.send;
|
|
580
|
+
XMLHttpRequest.prototype.send = function (body) {
|
|
581
|
+
if (body) {
|
|
582
|
+
try {
|
|
583
|
+
const bodyStr = typeof body === 'string' ? body : JSON.stringify(body);
|
|
584
|
+
const normBody = normalizeInput(bodyStr);
|
|
585
|
+
for (const pattern of ATTACK_PATTERNS) {
|
|
586
|
+
if (pattern.regex.test(normBody)) {
|
|
587
|
+
renderOfficialBlockPage(pattern.type, null, domain);
|
|
588
|
+
throw new Error(`[MDefender WAF] XHR payload attack blocked: ${pattern.type}`);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
} catch (e) {}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// Intercept 403 Forbidden responses from backend WAF
|
|
595
|
+
this.addEventListener('load', function () {
|
|
596
|
+
if (this.status === 403) {
|
|
597
|
+
try {
|
|
598
|
+
const resp = this.responseText || '';
|
|
599
|
+
const statusHeader = this.getResponseHeader('X-MDefender-Status');
|
|
600
|
+
const attackHeader = this.getResponseHeader('X-MDefender-Attack-Type');
|
|
601
|
+
const refHeader = this.getResponseHeader('X-MDefender-Ref');
|
|
602
|
+
if (statusHeader === 'blocked' || resp.includes('403') || resp.includes('MDefender') || resp.includes('Access Denied')) {
|
|
603
|
+
if (resp.includes('<!DOCTYPE html>') || resp.includes('<html')) {
|
|
604
|
+
try { window.stop(); } catch (e) {}
|
|
605
|
+
document.documentElement.innerHTML = resp;
|
|
606
|
+
} else {
|
|
607
|
+
renderOfficialBlockPage(attackHeader || 'Security Rule Violation', refHeader, domain);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
} catch (e) {}
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
return originalSend.apply(this, arguments);
|
|
615
|
+
};
|
|
541
616
|
}
|
|
542
617
|
|
|
543
618
|
export default { initWaf, renderOfficialBlockPage };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mdefender-pro",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.7",
|
|
4
4
|
"description": "MDefender Pro - Web Application Firewall middleware for Node.js/Express. Protects against XSS, SQLi, CSRF, and other OWASP Top 10 attacks.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|