@yognky/premium-security 1.0.4 → 1.0.6
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/dist/index.d.ts +1 -3
- package/dist/index.js +20 -28
- package/dist/utils/banner.d.ts +2 -3
- package/dist/utils/banner.js +27 -55
- package/dist/utils/helpers.d.ts +4 -4
- package/dist/utils/helpers.js +27 -26
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/logger.d.ts +7 -44
- package/dist/utils/logger.js +29 -140
- package/package.json +1 -1
- package/src/index.ts +43 -40
- package/src/utils/banner.ts +26 -56
- package/src/utils/helpers.ts +29 -34
- package/src/utils/index.ts +1 -0
- package/src/utils/logger.ts +34 -171
package/dist/index.d.ts
CHANGED
|
@@ -2,12 +2,10 @@ import { Express } from 'express';
|
|
|
2
2
|
declare function Premium(app: Express): void;
|
|
3
3
|
declare function start(port?: number): Promise<import("express-serve-static-core").Express>;
|
|
4
4
|
declare function use(app: Express): Promise<Express>;
|
|
5
|
-
|
|
6
|
-
export { start, use, premium, Premium };
|
|
5
|
+
export { start, use, Premium };
|
|
7
6
|
declare const _default: {
|
|
8
7
|
start: typeof start;
|
|
9
8
|
use: typeof use;
|
|
10
|
-
premium: typeof premium;
|
|
11
9
|
Premium: typeof Premium;
|
|
12
10
|
};
|
|
13
11
|
export default _default;
|
package/dist/index.js
CHANGED
|
@@ -5,11 +5,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.start = start;
|
|
7
7
|
exports.use = use;
|
|
8
|
-
exports.premium = premium;
|
|
9
8
|
exports.Premium = Premium;
|
|
10
9
|
const chalk_1 = __importDefault(require("chalk"));
|
|
11
10
|
const readline_1 = __importDefault(require("readline"));
|
|
12
11
|
const express_1 = __importDefault(require("express"));
|
|
12
|
+
const banner_1 = require("./utils/banner");
|
|
13
|
+
const logger_1 = require("./utils/logger");
|
|
14
|
+
const helpers_1 = require("./utils/helpers");
|
|
13
15
|
const ddos_1 = require("./defenses/ddos");
|
|
14
16
|
const sqlInjection_1 = require("./defenses/sqlInjection");
|
|
15
17
|
const xss_1 = require("./defenses/xss");
|
|
@@ -22,19 +24,11 @@ const advanced_1 = require("./defenses/advanced");
|
|
|
22
24
|
const spoofing_1 = require("./defenses/spoofing");
|
|
23
25
|
const timingAttack_1 = require("./defenses/timingAttack");
|
|
24
26
|
const PREMIUM_PASSWORD = 'Yongkykiyotaka';
|
|
25
|
-
const VERSION = '1.0.
|
|
27
|
+
const VERSION = '1.0.4';
|
|
26
28
|
let isVerified = false;
|
|
27
|
-
function showBanner() {
|
|
28
|
-
console.log('\n');
|
|
29
|
-
console.log(chalk_1.default.yellow('╔══════════════════════════════════════════════════════════╗'));
|
|
30
|
-
console.log(chalk_1.default.yellow('║ 💎 PREMIUM SECURITY 💎 ║'));
|
|
31
|
-
console.log(chalk_1.default.green(`║ 12 DEFENSES ACTIVE | v${VERSION} ║`));
|
|
32
|
-
console.log(chalk_1.default.yellow('╚══════════════════════════════════════════════════════════╝\n'));
|
|
33
|
-
}
|
|
34
29
|
async function verifyPassword() {
|
|
35
|
-
if (isVerified)
|
|
30
|
+
if (isVerified)
|
|
36
31
|
return true;
|
|
37
|
-
}
|
|
38
32
|
const rl = readline_1.default.createInterface({
|
|
39
33
|
input: process.stdin,
|
|
40
34
|
output: process.stdout
|
|
@@ -44,23 +38,30 @@ async function verifyPassword() {
|
|
|
44
38
|
rl.question(chalk_1.default.yellow('📝 Enter Premium Password: '), (answer) => {
|
|
45
39
|
rl.close();
|
|
46
40
|
if (answer === PREMIUM_PASSWORD) {
|
|
47
|
-
|
|
41
|
+
logger_1.logger.success('Password Valid! Premium Security Activated!');
|
|
48
42
|
isVerified = true;
|
|
49
43
|
resolve(true);
|
|
50
44
|
}
|
|
51
45
|
else {
|
|
52
|
-
|
|
46
|
+
logger_1.logger.error('Invalid Password! Access Denied.');
|
|
53
47
|
resolve(false);
|
|
54
48
|
}
|
|
55
49
|
});
|
|
56
50
|
});
|
|
57
51
|
}
|
|
58
52
|
function Premium(app) {
|
|
53
|
+
(0, banner_1.showPremiumBanner)();
|
|
54
|
+
(0, banner_1.showDefenseTable)();
|
|
59
55
|
console.log(chalk_1.default.cyan('⚙️ Memasang 12 Defense Premium...\n'));
|
|
60
56
|
app.use(express_1.default.json());
|
|
61
57
|
app.use(express_1.default.urlencoded({ extended: true }));
|
|
58
|
+
app.use((req, res, next) => {
|
|
59
|
+
const ip = (0, helpers_1.getRealIP)(req);
|
|
60
|
+
logger_1.logger.info(`${req.method} ${req.url} from ${ip}`);
|
|
61
|
+
next();
|
|
62
|
+
});
|
|
62
63
|
app.use((0, ddos_1.ddosProtection)({ maxPerMinute: 100, blockDuration: 60 }));
|
|
63
|
-
console.log(chalk_1.default.green(' ✓ ') + 'Anti DDoS');
|
|
64
|
+
console.log(chalk_1.default.green(' ✓ ') + 'Anti DDoS Protection');
|
|
64
65
|
app.use(sqlInjection_1.sqlInjectionProtection);
|
|
65
66
|
console.log(chalk_1.default.green(' ✓ ') + 'Anti SQL Injection');
|
|
66
67
|
app.use(xss_1.xssProtection);
|
|
@@ -75,9 +76,9 @@ function Premium(app) {
|
|
|
75
76
|
console.log(chalk_1.default.green(' ✓ ') + 'Rate Limiter');
|
|
76
77
|
app.use(malware_1.malwareProtection);
|
|
77
78
|
console.log(chalk_1.default.green(' ✓ ') + 'Anti Malware');
|
|
78
|
-
console.log(chalk_1.default.green(' ✓ ') + 'Whitelist Ready');
|
|
79
|
+
console.log(chalk_1.default.green(' ✓ ') + 'IP Whitelist Ready');
|
|
79
80
|
app.use(advanced_1.advancedProtection);
|
|
80
|
-
console.log(chalk_1.default.green(' ✓ ') + 'Advanced
|
|
81
|
+
console.log(chalk_1.default.green(' ✓ ') + 'Advanced Fingerprinting');
|
|
81
82
|
app.use(spoofing_1.antiSpoofing);
|
|
82
83
|
console.log(chalk_1.default.green(' ✓ ') + 'Anti IP Spoofing');
|
|
83
84
|
app.use(timingAttack_1.antiTimingAttack);
|
|
@@ -86,13 +87,13 @@ function Premium(app) {
|
|
|
86
87
|
res.json({
|
|
87
88
|
status: 'Premium Security Active',
|
|
88
89
|
defenses: '12 Layers',
|
|
89
|
-
version: VERSION
|
|
90
|
+
version: VERSION,
|
|
91
|
+
premium: true
|
|
90
92
|
});
|
|
91
93
|
});
|
|
92
94
|
console.log(chalk_1.default.green('\n✨ PREMIUM 12 DEFENSES READY! ✨\n'));
|
|
93
95
|
}
|
|
94
96
|
async function start(port = 3000) {
|
|
95
|
-
showBanner();
|
|
96
97
|
const isValid = await verifyPassword();
|
|
97
98
|
if (!isValid)
|
|
98
99
|
process.exit(1);
|
|
@@ -106,19 +107,10 @@ async function start(port = 3000) {
|
|
|
106
107
|
return app;
|
|
107
108
|
}
|
|
108
109
|
async function use(app) {
|
|
109
|
-
showBanner();
|
|
110
|
-
const isValid = await verifyPassword();
|
|
111
|
-
if (!isValid)
|
|
112
|
-
process.exit(1);
|
|
113
|
-
Premium(app);
|
|
114
|
-
return app;
|
|
115
|
-
}
|
|
116
|
-
async function premium(app) {
|
|
117
|
-
showBanner();
|
|
118
110
|
const isValid = await verifyPassword();
|
|
119
111
|
if (!isValid)
|
|
120
112
|
process.exit(1);
|
|
121
113
|
Premium(app);
|
|
122
114
|
return app;
|
|
123
115
|
}
|
|
124
|
-
exports.default = { start, use,
|
|
116
|
+
exports.default = { start, use, Premium };
|
package/dist/utils/banner.d.ts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export declare function
|
|
3
|
-
export declare function showDefenseTable(config: DefenseConfig): void;
|
|
1
|
+
export declare function showPremiumBanner(): void;
|
|
2
|
+
export declare function showDefenseTable(): void;
|
package/dist/utils/banner.js
CHANGED
|
@@ -3,69 +3,41 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.showPremiumBanner = showPremiumBanner;
|
|
7
7
|
exports.showDefenseTable = showDefenseTable;
|
|
8
8
|
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
-
|
|
10
|
-
const gradient_string_1 = __importDefault(require("gradient-string"));
|
|
11
|
-
function showYognkyBanner() {
|
|
9
|
+
function showPremiumBanner() {
|
|
12
10
|
console.log('\n');
|
|
13
|
-
console.log(chalk_1.default.
|
|
14
|
-
console.log(chalk_1.default.
|
|
15
|
-
|
|
16
|
-
console.log(
|
|
17
|
-
const securityText = figlet_1.default.textSync('SECURITY', { font: 'Small' });
|
|
18
|
-
console.log(gradient_string_1.default.rainbow(securityText));
|
|
19
|
-
console.log(chalk_1.default.yellow('\n 🔥 MODULES EZ V3 - ULTIMATE DEFENSE 🔥'));
|
|
20
|
-
console.log(chalk_1.default.cyan(' ════════════════════════════════════════════════════════════'));
|
|
11
|
+
console.log(chalk_1.default.yellow('╔════════════════════════════════════════════════════════════════╗'));
|
|
12
|
+
console.log(chalk_1.default.yellow('║ ║'));
|
|
13
|
+
console.log(chalk_1.default.green.bold(' 💎 P R E M I U M S E C U R I T Y 💎 '));
|
|
14
|
+
console.log(chalk_1.default.cyan(' ═══════════════════════════════════════════════════════════════'));
|
|
21
15
|
console.log(chalk_1.default.white(`\n 👑 Creator : ${chalk_1.default.green('YOGNKY')}`));
|
|
22
|
-
console.log(chalk_1.default.white(`
|
|
23
|
-
console.log(chalk_1.default.white(`
|
|
24
|
-
console.log(chalk_1.default.white(`
|
|
25
|
-
console.log(chalk_1.default.
|
|
26
|
-
console.log(chalk_1.default.white(` 🎯 Accuracy : ${chalk_1.default.green('99.99%')}`));
|
|
27
|
-
console.log(chalk_1.default.white(` ⚡ Response : ${chalk_1.default.green('< 5ms')}`));
|
|
28
|
-
console.log(chalk_1.default.white(` 💾 Memory : ${chalk_1.default.green('~15MB')}`));
|
|
29
|
-
console.log('\n' + chalk_1.default.gray(' "Jangan coba-coba nakal, nanti kena YOGNKY!"'));
|
|
30
|
-
console.log(chalk_1.default.gray(' "Hacker kiddie? Mah jajan dulu baru berani!"'));
|
|
31
|
-
console.log(chalk_1.default.gray(' "Bukan buat hacker, emang buat mereka semua!"'));
|
|
16
|
+
console.log(chalk_1.default.white(` 💎 Version : ${chalk_1.default.green('1.0.4 PREMIUM')}`));
|
|
17
|
+
console.log(chalk_1.default.white(` 🛡️ Defenses : ${chalk_1.default.green('12 LAYERS ACTIVE')}`));
|
|
18
|
+
console.log(chalk_1.default.white(` 🔐 Security : ${chalk_1.default.green('PASSWORD PROTECTED')}`));
|
|
19
|
+
console.log(chalk_1.default.yellow('\n 💰 PREMIUM SECURITY - UNLIMITED PROTECTION 💰'));
|
|
32
20
|
console.log(chalk_1.default.red('\n╚════════════════════════════════════════════════════════════════╝\n'));
|
|
33
21
|
}
|
|
34
|
-
function showDefenseTable(
|
|
35
|
-
console.log(chalk_1.default.cyan('\n📋
|
|
22
|
+
function showDefenseTable() {
|
|
23
|
+
console.log(chalk_1.default.cyan('\n📋 PREMIUM DEFENSES:'));
|
|
36
24
|
console.log(chalk_1.default.gray('┌─────────────────────────────────────────────────────────────────┐'));
|
|
37
|
-
const isWhitelistOn = () => {
|
|
38
|
-
const wp = config.anti_pengunjung;
|
|
39
|
-
if (wp === undefined)
|
|
40
|
-
return false;
|
|
41
|
-
if (wp === false)
|
|
42
|
-
return false;
|
|
43
|
-
if (wp === true)
|
|
44
|
-
return false;
|
|
45
|
-
return typeof wp === 'string' && wp.length > 0;
|
|
46
|
-
};
|
|
47
25
|
const defenses = [
|
|
48
|
-
{ name: 'Anti DDoS',
|
|
49
|
-
{ name: 'Anti SQL Injection',
|
|
50
|
-
{ name: 'Anti XSS',
|
|
51
|
-
{ name: 'Anti Bot/Curl',
|
|
52
|
-
{ name: 'Anti Malicious Headers',
|
|
53
|
-
{ name: 'Anti Brute Force',
|
|
54
|
-
{ name: 'Rate Limiter',
|
|
55
|
-
{ name: 'Anti Malware',
|
|
56
|
-
{ name: 'Whitelist
|
|
26
|
+
{ name: 'Anti DDoS', emoji: '🛡️', status: 'ACTIVE' },
|
|
27
|
+
{ name: 'Anti SQL Injection', emoji: '💉', status: 'ACTIVE' },
|
|
28
|
+
{ name: 'Anti XSS', emoji: '⚠️', status: 'ACTIVE' },
|
|
29
|
+
{ name: 'Anti Bot/Curl', emoji: '🤖', status: 'ACTIVE' },
|
|
30
|
+
{ name: 'Anti Malicious Headers', emoji: '🎭', status: 'ACTIVE' },
|
|
31
|
+
{ name: 'Anti Brute Force', emoji: '🔒', status: 'ACTIVE' },
|
|
32
|
+
{ name: 'Rate Limiter', emoji: '🐌', status: 'ACTIVE' },
|
|
33
|
+
{ name: 'Anti Malware', emoji: '🦠', status: 'ACTIVE' },
|
|
34
|
+
{ name: 'IP Whitelist', emoji: '📝', status: 'READY' },
|
|
35
|
+
{ name: 'Advanced Fingerprinting', emoji: '🔐', status: 'ACTIVE' },
|
|
36
|
+
{ name: 'Anti IP Spoofing', emoji: '🎯', status: 'ACTIVE' },
|
|
37
|
+
{ name: 'Anti Timing Attack', emoji: '⏱️', status: 'ACTIVE' }
|
|
57
38
|
];
|
|
58
|
-
defenses.forEach(
|
|
59
|
-
|
|
60
|
-
console.log(chalk_1.default.green(` ${defense.emoji} ${defense.name.padEnd(22)} : ${chalk_1.default.green('✓ ACTIVE')} ${chalk_1.default.gray(defense.desc)}`));
|
|
61
|
-
}
|
|
39
|
+
defenses.forEach(def => {
|
|
40
|
+
console.log(chalk_1.default.green(` ${def.emoji} ${def.name.padEnd(25)} : ${chalk_1.default.green(def.status)}`));
|
|
62
41
|
});
|
|
63
|
-
console.log(chalk_1.default.gray('
|
|
64
|
-
if (typeof config.anti_pengunjung === 'string' && config.anti_pengunjung.length > 0) {
|
|
65
|
-
console.log(chalk_1.default.yellow(`\n 👑 WHITELISTED IPS : ${chalk_1.default.white(config.anti_pengunjung)}`));
|
|
66
|
-
console.log(chalk_1.default.gray(' ─────────────────────────────────────────────────────────────────\n'));
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
console.log(chalk_1.default.gray('\n 📝 Whitelist Mode : DISABLED (all IPs allowed)\n'));
|
|
70
|
-
}
|
|
42
|
+
console.log(chalk_1.default.gray('└─────────────────────────────────────────────────────────────────┘\n'));
|
|
71
43
|
}
|
package/dist/utils/helpers.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Request } from 'express';
|
|
2
|
-
export declare function generateFingerprint(req: Request): string;
|
|
3
2
|
export declare function getRealIP(req: Request): string;
|
|
3
|
+
export declare function generateFingerprint(req: Request): string;
|
|
4
4
|
export declare class RateLimiter {
|
|
5
5
|
private requests;
|
|
6
6
|
isAllowed(key: string, maxRequests?: number, windowMs?: number): boolean;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
clearAll(): void;
|
|
7
|
+
getRemaining(key: string, maxRequests?: number, windowMs?: number): number;
|
|
8
|
+
reset(key: string): void;
|
|
10
9
|
}
|
|
11
10
|
export declare function sanitizeInput(input: string): string;
|
|
11
|
+
export declare function isValidIP(ip: string): boolean;
|
package/dist/utils/helpers.js
CHANGED
|
@@ -4,25 +4,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.RateLimiter = void 0;
|
|
7
|
-
exports.generateFingerprint = generateFingerprint;
|
|
8
7
|
exports.getRealIP = getRealIP;
|
|
8
|
+
exports.generateFingerprint = generateFingerprint;
|
|
9
9
|
exports.sanitizeInput = sanitizeInput;
|
|
10
|
+
exports.isValidIP = isValidIP;
|
|
10
11
|
const crypto_1 = __importDefault(require("crypto"));
|
|
11
|
-
function generateFingerprint(req) {
|
|
12
|
-
const ip = req.ip || req.socket.remoteAddress || '';
|
|
13
|
-
const ua = req.get('user-agent') || '';
|
|
14
|
-
const acceptLang = req.get('accept-language') || '';
|
|
15
|
-
const fingerprintString = `${ip}|${ua}|${acceptLang}`;
|
|
16
|
-
return crypto_1.default
|
|
17
|
-
.createHash('sha256')
|
|
18
|
-
.update(fingerprintString)
|
|
19
|
-
.digest('hex');
|
|
20
|
-
}
|
|
21
12
|
function getRealIP(req) {
|
|
22
13
|
const forwarded = req.headers['x-forwarded-for'];
|
|
23
14
|
if (forwarded && typeof forwarded === 'string') {
|
|
24
|
-
|
|
25
|
-
return ips[0].trim();
|
|
15
|
+
return forwarded.split(',')[0].trim();
|
|
26
16
|
}
|
|
27
17
|
const realIP = req.headers['x-real-ip'];
|
|
28
18
|
if (realIP && typeof realIP === 'string') {
|
|
@@ -30,33 +20,38 @@ function getRealIP(req) {
|
|
|
30
20
|
}
|
|
31
21
|
return req.ip || req.socket.remoteAddress || 'unknown';
|
|
32
22
|
}
|
|
23
|
+
function generateFingerprint(req) {
|
|
24
|
+
const ip = getRealIP(req);
|
|
25
|
+
const ua = req.get('user-agent') || '';
|
|
26
|
+
const acceptLang = req.get('accept-language') || '';
|
|
27
|
+
return crypto_1.default
|
|
28
|
+
.createHash('sha256')
|
|
29
|
+
.update(`${ip}|${ua}|${acceptLang}`)
|
|
30
|
+
.digest('hex');
|
|
31
|
+
}
|
|
33
32
|
class RateLimiter {
|
|
34
33
|
constructor() {
|
|
35
34
|
this.requests = new Map();
|
|
36
35
|
}
|
|
37
|
-
isAllowed(key, maxRequests =
|
|
36
|
+
isAllowed(key, maxRequests = 100, windowMs = 60000) {
|
|
38
37
|
const now = Date.now();
|
|
39
|
-
const
|
|
40
|
-
const recent =
|
|
41
|
-
if (recent.length >= maxRequests)
|
|
38
|
+
const timestamps = this.requests.get(key) || [];
|
|
39
|
+
const recent = timestamps.filter(t => t > now - windowMs);
|
|
40
|
+
if (recent.length >= maxRequests)
|
|
42
41
|
return false;
|
|
43
|
-
}
|
|
44
42
|
recent.push(now);
|
|
45
43
|
this.requests.set(key, recent);
|
|
46
44
|
return true;
|
|
47
45
|
}
|
|
48
|
-
|
|
46
|
+
getRemaining(key, maxRequests = 100, windowMs = 60000) {
|
|
49
47
|
const now = Date.now();
|
|
50
|
-
const
|
|
51
|
-
const recent =
|
|
48
|
+
const timestamps = this.requests.get(key) || [];
|
|
49
|
+
const recent = timestamps.filter(t => t > now - windowMs);
|
|
52
50
|
return Math.max(0, maxRequests - recent.length);
|
|
53
51
|
}
|
|
54
|
-
|
|
52
|
+
reset(key) {
|
|
55
53
|
this.requests.delete(key);
|
|
56
54
|
}
|
|
57
|
-
clearAll() {
|
|
58
|
-
this.requests.clear();
|
|
59
|
-
}
|
|
60
55
|
}
|
|
61
56
|
exports.RateLimiter = RateLimiter;
|
|
62
57
|
function sanitizeInput(input) {
|
|
@@ -70,5 +65,11 @@ function sanitizeInput(input) {
|
|
|
70
65
|
'>': '>'
|
|
71
66
|
};
|
|
72
67
|
return escape[match];
|
|
73
|
-
})
|
|
68
|
+
})
|
|
69
|
+
.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&');
|
|
70
|
+
}
|
|
71
|
+
function isValidIP(ip) {
|
|
72
|
+
const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
|
73
|
+
const ipv6Regex = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
|
|
74
|
+
return ipv4Regex.test(ip) || ipv6Regex.test(ip);
|
|
74
75
|
}
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
|
@@ -15,4 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./banner"), exports);
|
|
18
|
+
__exportStar(require("./logger"), exports);
|
|
18
19
|
__exportStar(require("./helpers"), exports);
|
package/dist/utils/logger.d.ts
CHANGED
|
@@ -1,44 +1,7 @@
|
|
|
1
|
-
export declare
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
export interface LogEntry {
|
|
9
|
-
timestamp: string;
|
|
10
|
-
level: LogLevel;
|
|
11
|
-
message: string;
|
|
12
|
-
ip?: string;
|
|
13
|
-
attackType?: string;
|
|
14
|
-
details?: any;
|
|
15
|
-
}
|
|
16
|
-
declare class Logger {
|
|
17
|
-
private logFile;
|
|
18
|
-
private enableFileLogging;
|
|
19
|
-
private enableConsoleLogging;
|
|
20
|
-
private logBuffer;
|
|
21
|
-
private bufferSize;
|
|
22
|
-
constructor();
|
|
23
|
-
private initLogFile;
|
|
24
|
-
private formatLogEntry;
|
|
25
|
-
private writeToFile;
|
|
26
|
-
private flushLogs;
|
|
27
|
-
log(level: LogLevel, message: string, metadata?: any): void;
|
|
28
|
-
info(message: string, metadata?: any): void;
|
|
29
|
-
warning(message: string, metadata?: any): void;
|
|
30
|
-
error(message: string, metadata?: any): void;
|
|
31
|
-
attack(attackType: string, ip: string, details?: any): void;
|
|
32
|
-
debug(message: string, metadata?: any): void;
|
|
33
|
-
getLogs(level?: LogLevel, limit?: number): Promise<LogEntry[]>;
|
|
34
|
-
clearLogs(): Promise<void>;
|
|
35
|
-
getStatistics(): Promise<{
|
|
36
|
-
totalAttacks: number;
|
|
37
|
-
totalErrors: number;
|
|
38
|
-
topAttackTypes: Record<string, number>;
|
|
39
|
-
topIPs: Record<string, number>;
|
|
40
|
-
timeline: Record<string, number>;
|
|
41
|
-
}>;
|
|
42
|
-
}
|
|
43
|
-
export declare const logger: Logger;
|
|
44
|
-
export {};
|
|
1
|
+
export declare const logger: {
|
|
2
|
+
info: (msg: string) => void;
|
|
3
|
+
error: (msg: string) => void;
|
|
4
|
+
warn: (msg: string) => void;
|
|
5
|
+
attack: (type: string, ip: string) => void;
|
|
6
|
+
success: (msg: string) => void;
|
|
7
|
+
};
|
package/dist/utils/logger.js
CHANGED
|
@@ -3,146 +3,35 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.logger =
|
|
6
|
+
exports.logger = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
7
8
|
const fs_1 = __importDefault(require("fs"));
|
|
8
9
|
const path_1 = __importDefault(require("path"));
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
10
|
+
const LOG_FILE = path_1.default.join(process.cwd(), 'premium-security.log');
|
|
11
|
+
exports.logger = {
|
|
12
|
+
info: (msg) => {
|
|
13
|
+
const log = `[${new Date().toISOString()}] ℹ️ ${msg}`;
|
|
14
|
+
console.log(chalk_1.default.blue(log));
|
|
15
|
+
fs_1.default.appendFileSync(LOG_FILE, log + '\n');
|
|
16
|
+
},
|
|
17
|
+
error: (msg) => {
|
|
18
|
+
const log = `[${new Date().toISOString()}] ❌ ${msg}`;
|
|
19
|
+
console.log(chalk_1.default.red(log));
|
|
20
|
+
fs_1.default.appendFileSync(LOG_FILE, log + '\n');
|
|
21
|
+
},
|
|
22
|
+
warn: (msg) => {
|
|
23
|
+
const log = `[${new Date().toISOString()}] ⚠️ ${msg}`;
|
|
24
|
+
console.log(chalk_1.default.yellow(log));
|
|
25
|
+
fs_1.default.appendFileSync(LOG_FILE, log + '\n');
|
|
26
|
+
},
|
|
27
|
+
attack: (type, ip) => {
|
|
28
|
+
const log = `[${new Date().toISOString()}] 🚨 ${type} blocked from ${ip}`;
|
|
29
|
+
console.log(chalk_1.default.magenta(log));
|
|
30
|
+
fs_1.default.appendFileSync(LOG_FILE, log + '\n');
|
|
31
|
+
},
|
|
32
|
+
success: (msg) => {
|
|
33
|
+
const log = `[${new Date().toISOString()}] ✅ ${msg}`;
|
|
34
|
+
console.log(chalk_1.default.green(log));
|
|
35
|
+
fs_1.default.appendFileSync(LOG_FILE, log + '\n');
|
|
25
36
|
}
|
|
26
|
-
|
|
27
|
-
if (!fs_1.default.existsSync(this.logFile)) {
|
|
28
|
-
fs_1.default.writeFileSync(this.logFile, `# YOGNKY SECURITY LOG\n# Started at: ${new Date().toISOString()}\n\n`);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
formatLogEntry(entry) {
|
|
32
|
-
return `[${entry.timestamp}] [${entry.level}] ${entry.message}${entry.ip ? ` | IP: ${entry.ip}` : ''}${entry.attackType ? ` | Attack: ${entry.attackType}` : ''}`;
|
|
33
|
-
}
|
|
34
|
-
async writeToFile(entry) {
|
|
35
|
-
if (!this.enableFileLogging)
|
|
36
|
-
return;
|
|
37
|
-
this.logBuffer.push(entry);
|
|
38
|
-
if (this.logBuffer.length >= this.bufferSize) {
|
|
39
|
-
await this.flushLogs();
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
async flushLogs() {
|
|
43
|
-
const logsToWrite = this.logBuffer.splice(0, this.bufferSize);
|
|
44
|
-
const logText = logsToWrite.map(entry => this.formatLogEntry(entry)).join('\n') + '\n';
|
|
45
|
-
try {
|
|
46
|
-
fs_1.default.appendFileSync(this.logFile, logText);
|
|
47
|
-
}
|
|
48
|
-
catch (error) {
|
|
49
|
-
console.error('Failed to write log:', error);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
log(level, message, metadata) {
|
|
53
|
-
const entry = {
|
|
54
|
-
timestamp: new Date().toISOString(),
|
|
55
|
-
level,
|
|
56
|
-
message,
|
|
57
|
-
...metadata
|
|
58
|
-
};
|
|
59
|
-
if (this.enableConsoleLogging) {
|
|
60
|
-
const colors = {
|
|
61
|
-
[LogLevel.INFO]: '\x1b[36m',
|
|
62
|
-
[LogLevel.WARNING]: '\x1b[33m',
|
|
63
|
-
[LogLevel.ERROR]: '\x1b[31m',
|
|
64
|
-
[LogLevel.ATTACK]: '\x1b[35m',
|
|
65
|
-
[LogLevel.DEBUG]: '\x1b[32m'
|
|
66
|
-
};
|
|
67
|
-
const reset = '\x1b[0m';
|
|
68
|
-
console.log(`${colors[level]}${this.formatLogEntry(entry)}${reset}`);
|
|
69
|
-
}
|
|
70
|
-
this.writeToFile(entry);
|
|
71
|
-
}
|
|
72
|
-
info(message, metadata) {
|
|
73
|
-
this.log(LogLevel.INFO, message, metadata);
|
|
74
|
-
}
|
|
75
|
-
warning(message, metadata) {
|
|
76
|
-
this.log(LogLevel.WARNING, message, metadata);
|
|
77
|
-
}
|
|
78
|
-
error(message, metadata) {
|
|
79
|
-
this.log(LogLevel.ERROR, message, metadata);
|
|
80
|
-
}
|
|
81
|
-
attack(attackType, ip, details) {
|
|
82
|
-
this.log(LogLevel.ATTACK, `${attackType} detected`, {
|
|
83
|
-
ip,
|
|
84
|
-
attackType,
|
|
85
|
-
details
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
debug(message, metadata) {
|
|
89
|
-
if (process.env.NODE_ENV === 'development') {
|
|
90
|
-
this.log(LogLevel.DEBUG, message, metadata);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
async getLogs(level, limit = 100) {
|
|
94
|
-
try {
|
|
95
|
-
const content = fs_1.default.readFileSync(this.logFile, 'utf-8');
|
|
96
|
-
const lines = content.split('\n').filter(line => line.trim());
|
|
97
|
-
const logs = [];
|
|
98
|
-
for (const line of lines) {
|
|
99
|
-
if (line.startsWith('#'))
|
|
100
|
-
continue;
|
|
101
|
-
const match = line.match(/\[(.*?)\] \[(.*?)\] (.*?)(?: \| IP: (.*?))?(?: \| Attack: (.*?))?/);
|
|
102
|
-
if (match) {
|
|
103
|
-
const [, timestamp, level, message, ip, attackType] = match;
|
|
104
|
-
if (!level || (level && (!level || level === level))) {
|
|
105
|
-
logs.push({ timestamp, level: level, message, ip, attackType });
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return logs.slice(-limit);
|
|
110
|
-
}
|
|
111
|
-
catch (error) {
|
|
112
|
-
this.error('Failed to read logs', error);
|
|
113
|
-
return [];
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
async clearLogs() {
|
|
117
|
-
try {
|
|
118
|
-
fs_1.default.writeFileSync(this.logFile, `# YOGNKY SECURITY LOG\n# Cleared at: ${new Date().toISOString()}\n\n`);
|
|
119
|
-
this.logBuffer = [];
|
|
120
|
-
this.info('Logs cleared successfully');
|
|
121
|
-
}
|
|
122
|
-
catch (error) {
|
|
123
|
-
this.error('Failed to clear logs', error);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
async getStatistics() {
|
|
127
|
-
const logs = await this.getLogs();
|
|
128
|
-
const stats = {
|
|
129
|
-
totalAttacks: logs.filter(log => log.level === LogLevel.ATTACK).length,
|
|
130
|
-
totalErrors: logs.filter(log => log.level === LogLevel.ERROR).length,
|
|
131
|
-
topAttackTypes: {},
|
|
132
|
-
topIPs: {},
|
|
133
|
-
timeline: {}
|
|
134
|
-
};
|
|
135
|
-
for (const log of logs) {
|
|
136
|
-
if (log.attackType) {
|
|
137
|
-
stats.topAttackTypes[log.attackType] = (stats.topAttackTypes[log.attackType] || 0) + 1;
|
|
138
|
-
}
|
|
139
|
-
if (log.ip) {
|
|
140
|
-
stats.topIPs[log.ip] = (stats.topIPs[log.ip] || 0) + 1;
|
|
141
|
-
}
|
|
142
|
-
const date = log.timestamp.split('T')[0];
|
|
143
|
-
stats.timeline[date] = (stats.timeline[date] || 0) + 1;
|
|
144
|
-
}
|
|
145
|
-
return stats;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
exports.logger = new Logger();
|
|
37
|
+
};
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -3,6 +3,11 @@ import chalk from 'chalk';
|
|
|
3
3
|
import readline from 'readline';
|
|
4
4
|
import express from 'express';
|
|
5
5
|
|
|
6
|
+
// ========== IMPORT UTILS ==========
|
|
7
|
+
import { showPremiumBanner, showDefenseTable } from './utils/banner';
|
|
8
|
+
import { logger } from './utils/logger';
|
|
9
|
+
import { getRealIP, generateFingerprint, RateLimiter } from './utils/helpers';
|
|
10
|
+
|
|
6
11
|
// ========== 12 DEFENSES PREMIUM ==========
|
|
7
12
|
import { ddosProtection } from './defenses/ddos';
|
|
8
13
|
import { sqlInjectionProtection } from './defenses/sqlInjection';
|
|
@@ -18,23 +23,11 @@ import { antiSpoofing } from './defenses/spoofing';
|
|
|
18
23
|
import { antiTimingAttack } from './defenses/timingAttack';
|
|
19
24
|
|
|
20
25
|
const PREMIUM_PASSWORD = 'Yongkykiyotaka';
|
|
21
|
-
const VERSION = '1.0.
|
|
22
|
-
|
|
23
|
-
let isVerified = false; // GLOBAL VERIFICATION FLAG
|
|
24
|
-
|
|
25
|
-
function showBanner() {
|
|
26
|
-
console.log('\n');
|
|
27
|
-
console.log(chalk.yellow('╔══════════════════════════════════════════════════════════╗'));
|
|
28
|
-
console.log(chalk.yellow('║ 💎 PREMIUM SECURITY 💎 ║'));
|
|
29
|
-
console.log(chalk.green(`║ 12 DEFENSES ACTIVE | v${VERSION} ║`));
|
|
30
|
-
console.log(chalk.yellow('╚══════════════════════════════════════════════════════════╝\n'));
|
|
31
|
-
}
|
|
26
|
+
const VERSION = '1.0.4';
|
|
27
|
+
let isVerified = false;
|
|
32
28
|
|
|
33
29
|
async function verifyPassword(): Promise<boolean> {
|
|
34
|
-
|
|
35
|
-
if (isVerified) {
|
|
36
|
-
return true;
|
|
37
|
-
}
|
|
30
|
+
if (isVerified) return true;
|
|
38
31
|
|
|
39
32
|
const rl = readline.createInterface({
|
|
40
33
|
input: process.stdin,
|
|
@@ -47,11 +40,11 @@ async function verifyPassword(): Promise<boolean> {
|
|
|
47
40
|
rl.question(chalk.yellow('📝 Enter Premium Password: '), (answer) => {
|
|
48
41
|
rl.close();
|
|
49
42
|
if (answer === PREMIUM_PASSWORD) {
|
|
50
|
-
|
|
43
|
+
logger.success('Password Valid! Premium Security Activated!');
|
|
51
44
|
isVerified = true;
|
|
52
45
|
resolve(true);
|
|
53
46
|
} else {
|
|
54
|
-
|
|
47
|
+
logger.error('Invalid Password! Access Denied.');
|
|
55
48
|
resolve(false);
|
|
56
49
|
}
|
|
57
50
|
});
|
|
@@ -59,61 +52,84 @@ async function verifyPassword(): Promise<boolean> {
|
|
|
59
52
|
}
|
|
60
53
|
|
|
61
54
|
function Premium(app: Express) {
|
|
55
|
+
showPremiumBanner();
|
|
56
|
+
showDefenseTable();
|
|
57
|
+
|
|
62
58
|
console.log(chalk.cyan('⚙️ Memasang 12 Defense Premium...\n'));
|
|
63
59
|
|
|
60
|
+
// Auto middleware
|
|
64
61
|
app.use(express.json());
|
|
65
62
|
app.use(express.urlencoded({ extended: true }));
|
|
66
63
|
|
|
64
|
+
// Logger middleware
|
|
65
|
+
app.use((req: Request, res: Response, next: NextFunction) => {
|
|
66
|
+
const ip = getRealIP(req);
|
|
67
|
+
logger.info(`${req.method} ${req.url} from ${ip}`);
|
|
68
|
+
next();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// 1. Anti DDoS
|
|
67
72
|
app.use(ddosProtection({ maxPerMinute: 100, blockDuration: 60 }));
|
|
68
|
-
console.log(chalk.green(' ✓ ') + 'Anti DDoS');
|
|
73
|
+
console.log(chalk.green(' ✓ ') + 'Anti DDoS Protection');
|
|
69
74
|
|
|
75
|
+
// 2. Anti SQL Injection
|
|
70
76
|
app.use(sqlInjectionProtection);
|
|
71
77
|
console.log(chalk.green(' ✓ ') + 'Anti SQL Injection');
|
|
72
78
|
|
|
79
|
+
// 3. Anti XSS
|
|
73
80
|
app.use(xssProtection);
|
|
74
81
|
console.log(chalk.green(' ✓ ') + 'Anti XSS');
|
|
75
82
|
|
|
83
|
+
// 4. Anti Bot/Curl
|
|
76
84
|
app.use(curlBotProtection);
|
|
77
85
|
console.log(chalk.green(' ✓ ') + 'Anti Bot/Curl');
|
|
78
86
|
|
|
87
|
+
// 5. Anti Malicious Headers
|
|
79
88
|
app.use(headerProtection);
|
|
80
89
|
console.log(chalk.green(' ✓ ') + 'Anti Malicious Headers');
|
|
81
90
|
|
|
91
|
+
// 6. Anti Brute Force
|
|
82
92
|
app.use(bruteforceProtection);
|
|
83
93
|
console.log(chalk.green(' ✓ ') + 'Anti Brute Force');
|
|
84
94
|
|
|
95
|
+
// 7. Rate Limiter
|
|
85
96
|
app.use(rateLimitProtection({ windowMs: 60000, maxRequests: 100 }));
|
|
86
97
|
console.log(chalk.green(' ✓ ') + 'Rate Limiter');
|
|
87
98
|
|
|
99
|
+
// 8. Anti Malware
|
|
88
100
|
app.use(malwareProtection);
|
|
89
101
|
console.log(chalk.green(' ✓ ') + 'Anti Malware');
|
|
90
102
|
|
|
91
|
-
|
|
103
|
+
// 9. Whitelist Ready
|
|
104
|
+
console.log(chalk.green(' ✓ ') + 'IP Whitelist Ready');
|
|
92
105
|
|
|
106
|
+
// 10. Advanced Protection
|
|
93
107
|
app.use(advancedProtection);
|
|
94
|
-
console.log(chalk.green(' ✓ ') + 'Advanced
|
|
108
|
+
console.log(chalk.green(' ✓ ') + 'Advanced Fingerprinting');
|
|
95
109
|
|
|
110
|
+
// 11. Anti Spoofing
|
|
96
111
|
app.use(antiSpoofing);
|
|
97
112
|
console.log(chalk.green(' ✓ ') + 'Anti IP Spoofing');
|
|
98
113
|
|
|
114
|
+
// 12. Anti Timing Attack
|
|
99
115
|
app.use(antiTimingAttack);
|
|
100
116
|
console.log(chalk.green(' ✓ ') + 'Anti Timing Attack');
|
|
101
117
|
|
|
118
|
+
// Default route
|
|
102
119
|
app.get('/', (req, res) => {
|
|
103
120
|
res.json({
|
|
104
121
|
status: 'Premium Security Active',
|
|
105
122
|
defenses: '12 Layers',
|
|
106
|
-
version: VERSION
|
|
123
|
+
version: VERSION,
|
|
124
|
+
premium: true
|
|
107
125
|
});
|
|
108
126
|
});
|
|
109
127
|
|
|
110
128
|
console.log(chalk.green('\n✨ PREMIUM 12 DEFENSES READY! ✨\n'));
|
|
111
129
|
}
|
|
112
130
|
|
|
113
|
-
// ========== START FUNCTION
|
|
131
|
+
// ========== START FUNCTION ==========
|
|
114
132
|
async function start(port: number = 3000) {
|
|
115
|
-
showBanner();
|
|
116
|
-
|
|
117
133
|
const isValid = await verifyPassword();
|
|
118
134
|
if (!isValid) process.exit(1);
|
|
119
135
|
|
|
@@ -129,21 +145,8 @@ async function start(port: number = 3000) {
|
|
|
129
145
|
return app;
|
|
130
146
|
}
|
|
131
147
|
|
|
132
|
-
// ========== USE FUNCTION
|
|
148
|
+
// ========== USE FUNCTION ==========
|
|
133
149
|
async function use(app: Express) {
|
|
134
|
-
showBanner();
|
|
135
|
-
|
|
136
|
-
const isValid = await verifyPassword();
|
|
137
|
-
if (!isValid) process.exit(1);
|
|
138
|
-
|
|
139
|
-
Premium(app);
|
|
140
|
-
return app;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// ========== PREMIUM FUNCTION (LANGSUNG) - JUGA WAJIB PW! ==========
|
|
144
|
-
async function premium(app: Express) {
|
|
145
|
-
showBanner();
|
|
146
|
-
|
|
147
150
|
const isValid = await verifyPassword();
|
|
148
151
|
if (!isValid) process.exit(1);
|
|
149
152
|
|
|
@@ -152,5 +155,5 @@ async function premium(app: Express) {
|
|
|
152
155
|
}
|
|
153
156
|
|
|
154
157
|
// ========== EXPORT ==========
|
|
155
|
-
export { start, use,
|
|
156
|
-
export default { start, use,
|
|
158
|
+
export { start, use, Premium };
|
|
159
|
+
export default { start, use, Premium };
|
package/src/utils/banner.ts
CHANGED
|
@@ -1,73 +1,43 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import figlet from 'figlet';
|
|
3
3
|
import gradient from 'gradient-string';
|
|
4
|
-
import { DefenseConfig } from '../types';
|
|
5
4
|
|
|
6
|
-
export function
|
|
5
|
+
export function showPremiumBanner() {
|
|
7
6
|
console.log('\n');
|
|
8
|
-
console.log(chalk.
|
|
9
|
-
console.log(chalk.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
console.log(gradient.passion(yongkyText));
|
|
13
|
-
|
|
14
|
-
const securityText = figlet.textSync('SECURITY', { font: 'Small' });
|
|
15
|
-
console.log(gradient.rainbow(securityText));
|
|
16
|
-
|
|
17
|
-
console.log(chalk.yellow('\n 🔥 MODULES EZ V3 - ULTIMATE DEFENSE 🔥'));
|
|
18
|
-
console.log(chalk.cyan(' ════════════════════════════════════════════════════════════'));
|
|
7
|
+
console.log(chalk.yellow('╔════════════════════════════════════════════════════════════════╗'));
|
|
8
|
+
console.log(chalk.yellow('║ ║'));
|
|
9
|
+
console.log(chalk.green.bold(' 💎 P R E M I U M S E C U R I T Y 💎 '));
|
|
10
|
+
console.log(chalk.cyan(' ═══════════════════════════════════════════════════════════════'));
|
|
19
11
|
console.log(chalk.white(`\n 👑 Creator : ${chalk.green('YOGNKY')}`));
|
|
20
|
-
console.log(chalk.white(`
|
|
21
|
-
console.log(chalk.white(`
|
|
22
|
-
console.log(chalk.white(`
|
|
23
|
-
console.log(chalk.
|
|
24
|
-
console.log(chalk.white(` 🎯 Accuracy : ${chalk.green('99.99%')}`));
|
|
25
|
-
console.log(chalk.white(` ⚡ Response : ${chalk.green('< 5ms')}`));
|
|
26
|
-
console.log(chalk.white(` 💾 Memory : ${chalk.green('~15MB')}`));
|
|
27
|
-
|
|
28
|
-
console.log('\n' + chalk.gray(' "Jangan coba-coba nakal, nanti kena YOGNKY!"'));
|
|
29
|
-
console.log(chalk.gray(' "Hacker kiddie? Mah jajan dulu baru berani!"'));
|
|
30
|
-
console.log(chalk.gray(' "Bukan buat hacker, emang buat mereka semua!"'));
|
|
12
|
+
console.log(chalk.white(` 💎 Version : ${chalk.green('1.0.4 PREMIUM')}`));
|
|
13
|
+
console.log(chalk.white(` 🛡️ Defenses : ${chalk.green('12 LAYERS ACTIVE')}`));
|
|
14
|
+
console.log(chalk.white(` 🔐 Security : ${chalk.green('PASSWORD PROTECTED')}`));
|
|
15
|
+
console.log(chalk.yellow('\n 💰 PREMIUM SECURITY - UNLIMITED PROTECTION 💰'));
|
|
31
16
|
console.log(chalk.red('\n╚════════════════════════════════════════════════════════════════╝\n'));
|
|
32
17
|
}
|
|
33
18
|
|
|
34
|
-
export function showDefenseTable(
|
|
35
|
-
console.log(chalk.cyan('\n📋
|
|
19
|
+
export function showDefenseTable() {
|
|
20
|
+
console.log(chalk.cyan('\n📋 PREMIUM DEFENSES:'));
|
|
36
21
|
console.log(chalk.gray('┌─────────────────────────────────────────────────────────────────┐'));
|
|
37
22
|
|
|
38
|
-
// FIX: pake helper function
|
|
39
|
-
const isWhitelistOn = () => {
|
|
40
|
-
const wp = config.anti_pengunjung;
|
|
41
|
-
if (wp === undefined) return false;
|
|
42
|
-
if (wp === false) return false;
|
|
43
|
-
if (wp === true) return false;
|
|
44
|
-
return typeof wp === 'string' && wp.length > 0;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
23
|
const defenses = [
|
|
48
|
-
{ name: 'Anti DDoS',
|
|
49
|
-
{ name: 'Anti SQL Injection',
|
|
50
|
-
{ name: 'Anti XSS',
|
|
51
|
-
{ name: 'Anti Bot/Curl',
|
|
52
|
-
{ name: 'Anti Malicious Headers',
|
|
53
|
-
{ name: 'Anti Brute Force',
|
|
54
|
-
{ name: 'Rate Limiter',
|
|
55
|
-
{ name: 'Anti Malware',
|
|
56
|
-
{ name: 'Whitelist
|
|
24
|
+
{ name: 'Anti DDoS', emoji: '🛡️', status: 'ACTIVE' },
|
|
25
|
+
{ name: 'Anti SQL Injection', emoji: '💉', status: 'ACTIVE' },
|
|
26
|
+
{ name: 'Anti XSS', emoji: '⚠️', status: 'ACTIVE' },
|
|
27
|
+
{ name: 'Anti Bot/Curl', emoji: '🤖', status: 'ACTIVE' },
|
|
28
|
+
{ name: 'Anti Malicious Headers', emoji: '🎭', status: 'ACTIVE' },
|
|
29
|
+
{ name: 'Anti Brute Force', emoji: '🔒', status: 'ACTIVE' },
|
|
30
|
+
{ name: 'Rate Limiter', emoji: '🐌', status: 'ACTIVE' },
|
|
31
|
+
{ name: 'Anti Malware', emoji: '🦠', status: 'ACTIVE' },
|
|
32
|
+
{ name: 'IP Whitelist', emoji: '📝', status: 'READY' },
|
|
33
|
+
{ name: 'Advanced Fingerprinting', emoji: '🔐', status: 'ACTIVE' },
|
|
34
|
+
{ name: 'Anti IP Spoofing', emoji: '🎯', status: 'ACTIVE' },
|
|
35
|
+
{ name: 'Anti Timing Attack', emoji: '⏱️', status: 'ACTIVE' }
|
|
57
36
|
];
|
|
58
37
|
|
|
59
|
-
defenses.forEach(
|
|
60
|
-
|
|
61
|
-
console.log(chalk.green(` ${defense.emoji} ${defense.name.padEnd(22)} : ${chalk.green('✓ ACTIVE')} ${chalk.gray(defense.desc)}`));
|
|
62
|
-
}
|
|
38
|
+
defenses.forEach(def => {
|
|
39
|
+
console.log(chalk.green(` ${def.emoji} ${def.name.padEnd(25)} : ${chalk.green(def.status)}`));
|
|
63
40
|
});
|
|
64
41
|
|
|
65
|
-
console.log(chalk.gray('
|
|
66
|
-
|
|
67
|
-
if (typeof config.anti_pengunjung === 'string' && config.anti_pengunjung.length > 0) {
|
|
68
|
-
console.log(chalk.yellow(`\n 👑 WHITELISTED IPS : ${chalk.white(config.anti_pengunjung)}`));
|
|
69
|
-
console.log(chalk.gray(' ─────────────────────────────────────────────────────────────────\n'));
|
|
70
|
-
} else {
|
|
71
|
-
console.log(chalk.gray('\n 📝 Whitelist Mode : DISABLED (all IPs allowed)\n'));
|
|
72
|
-
}
|
|
42
|
+
console.log(chalk.gray('└─────────────────────────────────────────────────────────────────┘\n'));
|
|
73
43
|
}
|
package/src/utils/helpers.ts
CHANGED
|
@@ -1,70 +1,58 @@
|
|
|
1
|
-
import crypto from 'crypto';
|
|
2
1
|
import { Request } from 'express';
|
|
3
|
-
|
|
4
|
-
export function generateFingerprint(req: Request): string {
|
|
5
|
-
const ip = req.ip || req.socket.remoteAddress || '';
|
|
6
|
-
const ua = req.get('user-agent') || '';
|
|
7
|
-
const acceptLang = req.get('accept-language') || '';
|
|
8
|
-
|
|
9
|
-
const fingerprintString = `${ip}|${ua}|${acceptLang}`;
|
|
10
|
-
|
|
11
|
-
return crypto
|
|
12
|
-
.createHash('sha256')
|
|
13
|
-
.update(fingerprintString)
|
|
14
|
-
.digest('hex');
|
|
15
|
-
}
|
|
2
|
+
import crypto from 'crypto';
|
|
16
3
|
|
|
17
4
|
export function getRealIP(req: Request): string {
|
|
18
5
|
const forwarded = req.headers['x-forwarded-for'];
|
|
19
6
|
if (forwarded && typeof forwarded === 'string') {
|
|
20
|
-
|
|
21
|
-
return ips[0].trim();
|
|
7
|
+
return forwarded.split(',')[0].trim();
|
|
22
8
|
}
|
|
23
|
-
|
|
24
9
|
const realIP = req.headers['x-real-ip'];
|
|
25
10
|
if (realIP && typeof realIP === 'string') {
|
|
26
11
|
return realIP;
|
|
27
12
|
}
|
|
28
|
-
|
|
29
13
|
return req.ip || req.socket.remoteAddress || 'unknown';
|
|
30
14
|
}
|
|
31
15
|
|
|
16
|
+
export function generateFingerprint(req: Request): string {
|
|
17
|
+
const ip = getRealIP(req);
|
|
18
|
+
const ua = req.get('user-agent') || '';
|
|
19
|
+
const acceptLang = req.get('accept-language') || '';
|
|
20
|
+
|
|
21
|
+
return crypto
|
|
22
|
+
.createHash('sha256')
|
|
23
|
+
.update(`${ip}|${ua}|${acceptLang}`)
|
|
24
|
+
.digest('hex');
|
|
25
|
+
}
|
|
26
|
+
|
|
32
27
|
export class RateLimiter {
|
|
33
28
|
private requests: Map<string, number[]> = new Map();
|
|
34
29
|
|
|
35
|
-
|
|
30
|
+
isAllowed(key: string, maxRequests: number = 100, windowMs: number = 60000): boolean {
|
|
36
31
|
const now = Date.now();
|
|
37
|
-
const
|
|
38
|
-
const recent =
|
|
32
|
+
const timestamps = this.requests.get(key) || [];
|
|
33
|
+
const recent = timestamps.filter(t => t > now - windowMs);
|
|
39
34
|
|
|
40
|
-
if (recent.length >= maxRequests)
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
35
|
+
if (recent.length >= maxRequests) return false;
|
|
43
36
|
|
|
44
37
|
recent.push(now);
|
|
45
38
|
this.requests.set(key, recent);
|
|
46
39
|
return true;
|
|
47
40
|
}
|
|
48
41
|
|
|
49
|
-
|
|
42
|
+
getRemaining(key: string, maxRequests: number = 100, windowMs: number = 60000): number {
|
|
50
43
|
const now = Date.now();
|
|
51
|
-
const
|
|
52
|
-
const recent =
|
|
44
|
+
const timestamps = this.requests.get(key) || [];
|
|
45
|
+
const recent = timestamps.filter(t => t > now - windowMs);
|
|
53
46
|
return Math.max(0, maxRequests - recent.length);
|
|
54
47
|
}
|
|
55
48
|
|
|
56
|
-
|
|
49
|
+
reset(key: string): void {
|
|
57
50
|
this.requests.delete(key);
|
|
58
51
|
}
|
|
59
|
-
|
|
60
|
-
public clearAll(): void {
|
|
61
|
-
this.requests.clear();
|
|
62
|
-
}
|
|
63
52
|
}
|
|
64
53
|
|
|
65
54
|
export function sanitizeInput(input: string): string {
|
|
66
55
|
if (!input) return '';
|
|
67
|
-
|
|
68
56
|
return input
|
|
69
57
|
.replace(/[&<>]/g, (match) => {
|
|
70
58
|
const escape: Record<string, string> = {
|
|
@@ -73,5 +61,12 @@ export function sanitizeInput(input: string): string {
|
|
|
73
61
|
'>': '>'
|
|
74
62
|
};
|
|
75
63
|
return escape[match];
|
|
76
|
-
})
|
|
64
|
+
})
|
|
65
|
+
.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function isValidIP(ip: string): boolean {
|
|
69
|
+
const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
|
70
|
+
const ipv6Regex = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
|
|
71
|
+
return ipv4Regex.test(ip) || ipv6Regex.test(ip);
|
|
77
72
|
}
|
package/src/utils/index.ts
CHANGED
package/src/utils/logger.ts
CHANGED
|
@@ -1,174 +1,37 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
1
2
|
import fs from 'fs';
|
|
2
3
|
import path from 'path';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
fs.writeFileSync(this.logFile, `# YOGNKY SECURITY LOG\n# Started at: ${new Date().toISOString()}\n\n`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
private formatLogEntry(entry: LogEntry): string {
|
|
42
|
-
return `[${entry.timestamp}] [${entry.level}] ${entry.message}${entry.ip ? ` | IP: ${entry.ip}` : ''}${entry.attackType ? ` | Attack: ${entry.attackType}` : ''}`;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
private async writeToFile(entry: LogEntry) {
|
|
46
|
-
if (!this.enableFileLogging) return;
|
|
47
|
-
|
|
48
|
-
this.logBuffer.push(entry);
|
|
49
|
-
if (this.logBuffer.length >= this.bufferSize) {
|
|
50
|
-
await this.flushLogs();
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
private async flushLogs() {
|
|
55
|
-
const logsToWrite = this.logBuffer.splice(0, this.bufferSize);
|
|
56
|
-
const logText = logsToWrite.map(entry => this.formatLogEntry(entry)).join('\n') + '\n';
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
fs.appendFileSync(this.logFile, logText);
|
|
60
|
-
} catch (error) {
|
|
61
|
-
console.error('Failed to write log:', error);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
public log(level: LogLevel, message: string, metadata?: any) {
|
|
66
|
-
const entry: LogEntry = {
|
|
67
|
-
timestamp: new Date().toISOString(),
|
|
68
|
-
level,
|
|
69
|
-
message,
|
|
70
|
-
...metadata
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
if (this.enableConsoleLogging) {
|
|
74
|
-
const colors = {
|
|
75
|
-
[LogLevel.INFO]: '\x1b[36m', // Cyan
|
|
76
|
-
[LogLevel.WARNING]: '\x1b[33m', // Yellow
|
|
77
|
-
[LogLevel.ERROR]: '\x1b[31m', // Red
|
|
78
|
-
[LogLevel.ATTACK]: '\x1b[35m', // Magenta
|
|
79
|
-
[LogLevel.DEBUG]: '\x1b[32m' // Green
|
|
80
|
-
};
|
|
81
|
-
const reset = '\x1b[0m';
|
|
82
|
-
console.log(`${colors[level]}${this.formatLogEntry(entry)}${reset}`);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
this.writeToFile(entry);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
public info(message: string, metadata?: any) {
|
|
89
|
-
this.log(LogLevel.INFO, message, metadata);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
public warning(message: string, metadata?: any) {
|
|
93
|
-
this.log(LogLevel.WARNING, message, metadata);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
public error(message: string, metadata?: any) {
|
|
97
|
-
this.log(LogLevel.ERROR, message, metadata);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
public attack(attackType: string, ip: string, details?: any) {
|
|
101
|
-
this.log(LogLevel.ATTACK, `${attackType} detected`, {
|
|
102
|
-
ip,
|
|
103
|
-
attackType,
|
|
104
|
-
details
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
public debug(message: string, metadata?: any) {
|
|
109
|
-
if (process.env.NODE_ENV === 'development') {
|
|
110
|
-
this.log(LogLevel.DEBUG, message, metadata);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
public async getLogs(level?: LogLevel, limit: number = 100): Promise<LogEntry[]> {
|
|
115
|
-
try {
|
|
116
|
-
const content = fs.readFileSync(this.logFile, 'utf-8');
|
|
117
|
-
const lines = content.split('\n').filter(line => line.trim());
|
|
118
|
-
const logs: LogEntry[] = [];
|
|
119
|
-
|
|
120
|
-
for (const line of lines) {
|
|
121
|
-
if (line.startsWith('#')) continue;
|
|
122
|
-
|
|
123
|
-
const match = line.match(/\[(.*?)\] \[(.*?)\] (.*?)(?: \| IP: (.*?))?(?: \| Attack: (.*?))?/);
|
|
124
|
-
if (match) {
|
|
125
|
-
const [, timestamp, level, message, ip, attackType] = match;
|
|
126
|
-
if (!level || (level && (!level || level === level))) {
|
|
127
|
-
logs.push({ timestamp, level: level as LogLevel, message, ip, attackType });
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return logs.slice(-limit);
|
|
133
|
-
} catch (error) {
|
|
134
|
-
this.error('Failed to read logs', error);
|
|
135
|
-
return [];
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
public async clearLogs() {
|
|
140
|
-
try {
|
|
141
|
-
fs.writeFileSync(this.logFile, `# YOGNKY SECURITY LOG\n# Cleared at: ${new Date().toISOString()}\n\n`);
|
|
142
|
-
this.logBuffer = [];
|
|
143
|
-
this.info('Logs cleared successfully');
|
|
144
|
-
} catch (error) {
|
|
145
|
-
this.error('Failed to clear logs', error);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
public async getStatistics() {
|
|
150
|
-
const logs = await this.getLogs();
|
|
151
|
-
const stats = {
|
|
152
|
-
totalAttacks: logs.filter(log => log.level === LogLevel.ATTACK).length,
|
|
153
|
-
totalErrors: logs.filter(log => log.level === LogLevel.ERROR).length,
|
|
154
|
-
topAttackTypes: {} as Record<string, number>,
|
|
155
|
-
topIPs: {} as Record<string, number>,
|
|
156
|
-
timeline: {} as Record<string, number>
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
for (const log of logs) {
|
|
160
|
-
if (log.attackType) {
|
|
161
|
-
stats.topAttackTypes[log.attackType] = (stats.topAttackTypes[log.attackType] || 0) + 1;
|
|
162
|
-
}
|
|
163
|
-
if (log.ip) {
|
|
164
|
-
stats.topIPs[log.ip] = (stats.topIPs[log.ip] || 0) + 1;
|
|
165
|
-
}
|
|
166
|
-
const date = log.timestamp.split('T')[0];
|
|
167
|
-
stats.timeline[date] = (stats.timeline[date] || 0) + 1;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return stats;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export const logger = new Logger();
|
|
5
|
+
const LOG_FILE = path.join(process.cwd(), 'premium-security.log');
|
|
6
|
+
|
|
7
|
+
export const logger = {
|
|
8
|
+
info: (msg: string) => {
|
|
9
|
+
const log = `[${new Date().toISOString()}] ℹ️ ${msg}`;
|
|
10
|
+
console.log(chalk.blue(log));
|
|
11
|
+
fs.appendFileSync(LOG_FILE, log + '\n');
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
error: (msg: string) => {
|
|
15
|
+
const log = `[${new Date().toISOString()}] ❌ ${msg}`;
|
|
16
|
+
console.log(chalk.red(log));
|
|
17
|
+
fs.appendFileSync(LOG_FILE, log + '\n');
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
warn: (msg: string) => {
|
|
21
|
+
const log = `[${new Date().toISOString()}] ⚠️ ${msg}`;
|
|
22
|
+
console.log(chalk.yellow(log));
|
|
23
|
+
fs.appendFileSync(LOG_FILE, log + '\n');
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
attack: (type: string, ip: string) => {
|
|
27
|
+
const log = `[${new Date().toISOString()}] 🚨 ${type} blocked from ${ip}`;
|
|
28
|
+
console.log(chalk.magenta(log));
|
|
29
|
+
fs.appendFileSync(LOG_FILE, log + '\n');
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
success: (msg: string) => {
|
|
33
|
+
const log = `[${new Date().toISOString()}] ✅ ${msg}`;
|
|
34
|
+
console.log(chalk.green(log));
|
|
35
|
+
fs.appendFileSync(LOG_FILE, log + '\n');
|
|
36
|
+
}
|
|
37
|
+
};
|