@yognky/premium-security 1.0.0
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/CHANGELOG.md +39 -0
- package/LICENSE +21 -0
- package/README.md +8 -0
- package/dist/defenses/advanced.d.ts +2 -0
- package/dist/defenses/advanced.js +7 -0
- package/dist/defenses/advenced.d.ts +2 -0
- package/dist/defenses/advenced.js +48 -0
- package/dist/defenses/bruteforce.d.ts +2 -0
- package/dist/defenses/bruteforce.js +43 -0
- package/dist/defenses/curlBot.d.ts +2 -0
- package/dist/defenses/curlBot.js +31 -0
- package/dist/defenses/ddos.d.ts +2 -0
- package/dist/defenses/ddos.js +42 -0
- package/dist/defenses/headers.d.ts +2 -0
- package/dist/defenses/headers.js +25 -0
- package/dist/defenses/malware.d.ts +2 -0
- package/dist/defenses/malware.js +34 -0
- package/dist/defenses/rateLimit.d.ts +2 -0
- package/dist/defenses/rateLimit.js +31 -0
- package/dist/defenses/spoofing.d.ts +2 -0
- package/dist/defenses/spoofing.js +7 -0
- package/dist/defenses/sqlInjection.d.ts +2 -0
- package/dist/defenses/sqlInjection.js +40 -0
- package/dist/defenses/timingAttack.d.ts +2 -0
- package/dist/defenses/timingAttack.js +7 -0
- package/dist/defenses/whitelist.d.ts +2 -0
- package/dist/defenses/whitelist.js +22 -0
- package/dist/defenses/xss.d.ts +2 -0
- package/dist/defenses/xss.js +45 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +98 -0
- package/dist/type/index.d.ts +41 -0
- package/dist/type/index.js +2 -0
- package/dist/types/index.d.ts +27 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/banner.d.ts +3 -0
- package/dist/utils/banner.js +71 -0
- package/dist/utils/helpers.d.ts +11 -0
- package/dist/utils/helpers.js +74 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +18 -0
- package/dist/utils/logger.d.ts +44 -0
- package/dist/utils/logger.js +148 -0
- package/docs/API.md +35 -0
- package/docs/EXAMPLE.md +45 -0
- package/docs/INSTALLATTION.md +6 -0
- package/examples/advenced-server.js +59 -0
- package/examples/basic-server.js +33 -0
- package/examples/simple-express.js +21 -0
- package/examples/with-express.ts +33 -0
- package/gitignore +48 -0
- package/nodemon.json +11 -0
- package/npmignore +36 -0
- package/package.json +27 -0
- package/src/defenses/advanced.ts +6 -0
- package/src/defenses/advenced.ts +54 -0
- package/src/defenses/bruteforce.ts +47 -0
- package/src/defenses/curlBot.ts +33 -0
- package/src/defenses/ddos.ts +46 -0
- package/src/defenses/headers.ts +27 -0
- package/src/defenses/malware.ts +35 -0
- package/src/defenses/rateLimit.ts +34 -0
- package/src/defenses/spoofing.ts +5 -0
- package/src/defenses/sqlInjection.ts +41 -0
- package/src/defenses/timingAttack.ts +5 -0
- package/src/defenses/whitelist.ts +23 -0
- package/src/defenses/xss.ts +46 -0
- package/src/index.ts +125 -0
- package/src/type/index.ts +48 -0
- package/src/types/index.ts +32 -0
- package/src/utils/banner.ts +73 -0
- package/src/utils/helpers +237 -0
- package/src/utils/helpers.ts +77 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/logger.ts +174 -0
- package/test/bruteforce.test.ts +34 -0
- package/test/ddos.test.ts +30 -0
- package/test/integration.test.ts +44 -0
- package/test/sql.test.ts +39 -0
- package/test/xss.test.ts +39 -0
- package/test-module.js +23 -0
- package/tsconfig.build.json +17 -0
- package/tsconfig.json +26 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
export type DefenseConfig = {
|
|
3
|
+
anti_ddos?: boolean | DDOSConfig;
|
|
4
|
+
anti_sql?: boolean;
|
|
5
|
+
anti_curl?: boolean;
|
|
6
|
+
anti_header?: boolean;
|
|
7
|
+
anti_pengunjung?: string | false;
|
|
8
|
+
anti_xss?: boolean;
|
|
9
|
+
anti_bruteforce?: boolean;
|
|
10
|
+
anti_rateLimit?: boolean | RateLimitConfig;
|
|
11
|
+
anti_malware?: boolean;
|
|
12
|
+
anti_advanced?: boolean;
|
|
13
|
+
anti_spoofing?: boolean;
|
|
14
|
+
anti_timing?: boolean;
|
|
15
|
+
enableLogging?: boolean;
|
|
16
|
+
debug?: boolean;
|
|
17
|
+
};
|
|
18
|
+
export type DDOSConfig = {
|
|
19
|
+
maxPerMinute?: number;
|
|
20
|
+
blockDuration?: number;
|
|
21
|
+
};
|
|
22
|
+
export type RateLimitConfig = {
|
|
23
|
+
windowMs?: number;
|
|
24
|
+
maxRequests?: number;
|
|
25
|
+
};
|
|
26
|
+
export interface RequestInfo {
|
|
27
|
+
ip: string;
|
|
28
|
+
timestamp: number;
|
|
29
|
+
url: string;
|
|
30
|
+
method: string;
|
|
31
|
+
fingerprint?: string;
|
|
32
|
+
}
|
|
33
|
+
export type Middleware = (req: Request, res: Response, next: NextFunction) => void;
|
|
34
|
+
export interface AttackLog {
|
|
35
|
+
id: string;
|
|
36
|
+
type: string;
|
|
37
|
+
ip: string;
|
|
38
|
+
timestamp: Date;
|
|
39
|
+
details?: any;
|
|
40
|
+
blocked: boolean;
|
|
41
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
export type DefenseConfig = {
|
|
3
|
+
anti_ddos?: boolean | DDOSConfig;
|
|
4
|
+
anti_sql?: boolean;
|
|
5
|
+
anti_curl?: boolean;
|
|
6
|
+
anti_header?: boolean;
|
|
7
|
+
anti_pengunjung?: string | boolean;
|
|
8
|
+
anti_xss?: boolean;
|
|
9
|
+
anti_bruteforce?: boolean;
|
|
10
|
+
anti_rateLimit?: boolean | RateLimitConfig;
|
|
11
|
+
anti_malware?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export type DDOSConfig = {
|
|
14
|
+
maxPerMinute?: number;
|
|
15
|
+
blockDuration?: number;
|
|
16
|
+
};
|
|
17
|
+
export type RateLimitConfig = {
|
|
18
|
+
windowMs?: number;
|
|
19
|
+
maxRequests?: number;
|
|
20
|
+
};
|
|
21
|
+
export interface RequestInfo {
|
|
22
|
+
ip: string;
|
|
23
|
+
timestamp: number;
|
|
24
|
+
url: string;
|
|
25
|
+
method: string;
|
|
26
|
+
}
|
|
27
|
+
export type Middleware = (req: Request, res: Response, next: NextFunction) => void;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.showYognkyBanner = showYognkyBanner;
|
|
7
|
+
exports.showDefenseTable = showDefenseTable;
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const figlet_1 = __importDefault(require("figlet"));
|
|
10
|
+
const gradient_string_1 = __importDefault(require("gradient-string"));
|
|
11
|
+
function showYognkyBanner() {
|
|
12
|
+
console.log('\n');
|
|
13
|
+
console.log(chalk_1.default.red('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
14
|
+
console.log(chalk_1.default.red('ā ā'));
|
|
15
|
+
const yongkyText = figlet_1.default.textSync('YOGNKY', { font: 'Slant' });
|
|
16
|
+
console.log(gradient_string_1.default.passion(yongkyText));
|
|
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(' āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
21
|
+
console.log(chalk_1.default.white(`\n š Creator : ${chalk_1.default.green('YOGNKY')}`));
|
|
22
|
+
console.log(chalk_1.default.white(` š”ļø Version : ${chalk_1.default.green('3.0.0')}`));
|
|
23
|
+
console.log(chalk_1.default.white(` šŖ Status : ${chalk_1.default.green('ACTIVATED')}`));
|
|
24
|
+
console.log(chalk_1.default.white(` š Power : ${chalk_1.default.green('ULTIMATE')}`));
|
|
25
|
+
console.log(chalk_1.default.white(` š Defense : ${chalk_1.default.green('12 LAYERS')}`));
|
|
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!"'));
|
|
32
|
+
console.log(chalk_1.default.red('\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n'));
|
|
33
|
+
}
|
|
34
|
+
function showDefenseTable(config) {
|
|
35
|
+
console.log(chalk_1.default.cyan('\nš ACTIVE DEFENSES:'));
|
|
36
|
+
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
|
+
const defenses = [
|
|
48
|
+
{ name: 'Anti DDoS', active: !!config.anti_ddos, emoji: 'š”ļø', desc: 'Block flood attacks' },
|
|
49
|
+
{ name: 'Anti SQL Injection', active: !!config.anti_sql, emoji: 'š', desc: 'Prevent SQLi' },
|
|
50
|
+
{ name: 'Anti XSS', active: !!config.anti_xss, emoji: 'ā ļø', desc: 'Stop XSS attacks' },
|
|
51
|
+
{ name: 'Anti Bot/Curl', active: !!config.anti_curl, emoji: 'š¤', desc: 'Block bots' },
|
|
52
|
+
{ name: 'Anti Malicious Headers', active: !!config.anti_header, emoji: 'š', desc: 'Filter bad headers' },
|
|
53
|
+
{ name: 'Anti Brute Force', active: !!config.anti_bruteforce, emoji: 'š', desc: 'Prevent brute force' },
|
|
54
|
+
{ name: 'Rate Limiter', active: !!config.anti_rateLimit, emoji: 'š', desc: 'Limit requests' },
|
|
55
|
+
{ name: 'Anti Malware', active: !!config.anti_malware, emoji: 'š¦ ', desc: 'Detect malware' },
|
|
56
|
+
{ name: 'Whitelist Mode', active: isWhitelistOn(), emoji: 'š', desc: 'IP whitelist' }
|
|
57
|
+
];
|
|
58
|
+
defenses.forEach(defense => {
|
|
59
|
+
if (defense.active) {
|
|
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
|
+
}
|
|
62
|
+
});
|
|
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
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Request } from 'express';
|
|
2
|
+
export declare function generateFingerprint(req: Request): string;
|
|
3
|
+
export declare function getRealIP(req: Request): string;
|
|
4
|
+
export declare class RateLimiter {
|
|
5
|
+
private requests;
|
|
6
|
+
isAllowed(key: string, maxRequests?: number, windowMs?: number): boolean;
|
|
7
|
+
getRemainingRequests(key: string, maxRequests?: number, windowMs?: number): number;
|
|
8
|
+
clear(key: string): void;
|
|
9
|
+
clearAll(): void;
|
|
10
|
+
}
|
|
11
|
+
export declare function sanitizeInput(input: string): string;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RateLimiter = void 0;
|
|
7
|
+
exports.generateFingerprint = generateFingerprint;
|
|
8
|
+
exports.getRealIP = getRealIP;
|
|
9
|
+
exports.sanitizeInput = sanitizeInput;
|
|
10
|
+
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
|
+
function getRealIP(req) {
|
|
22
|
+
const forwarded = req.headers['x-forwarded-for'];
|
|
23
|
+
if (forwarded && typeof forwarded === 'string') {
|
|
24
|
+
const ips = forwarded.split(',');
|
|
25
|
+
return ips[0].trim();
|
|
26
|
+
}
|
|
27
|
+
const realIP = req.headers['x-real-ip'];
|
|
28
|
+
if (realIP && typeof realIP === 'string') {
|
|
29
|
+
return realIP;
|
|
30
|
+
}
|
|
31
|
+
return req.ip || req.socket.remoteAddress || 'unknown';
|
|
32
|
+
}
|
|
33
|
+
class RateLimiter {
|
|
34
|
+
constructor() {
|
|
35
|
+
this.requests = new Map();
|
|
36
|
+
}
|
|
37
|
+
isAllowed(key, maxRequests = 60, windowMs = 60000) {
|
|
38
|
+
const now = Date.now();
|
|
39
|
+
const requests = this.requests.get(key) || [];
|
|
40
|
+
const recent = requests.filter(t => t > now - windowMs);
|
|
41
|
+
if (recent.length >= maxRequests) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
recent.push(now);
|
|
45
|
+
this.requests.set(key, recent);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
getRemainingRequests(key, maxRequests = 60, windowMs = 60000) {
|
|
49
|
+
const now = Date.now();
|
|
50
|
+
const requests = this.requests.get(key) || [];
|
|
51
|
+
const recent = requests.filter(t => t > now - windowMs);
|
|
52
|
+
return Math.max(0, maxRequests - recent.length);
|
|
53
|
+
}
|
|
54
|
+
clear(key) {
|
|
55
|
+
this.requests.delete(key);
|
|
56
|
+
}
|
|
57
|
+
clearAll() {
|
|
58
|
+
this.requests.clear();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.RateLimiter = RateLimiter;
|
|
62
|
+
function sanitizeInput(input) {
|
|
63
|
+
if (!input)
|
|
64
|
+
return '';
|
|
65
|
+
return input
|
|
66
|
+
.replace(/[&<>]/g, (match) => {
|
|
67
|
+
const escape = {
|
|
68
|
+
'&': '&',
|
|
69
|
+
'<': '<',
|
|
70
|
+
'>': '>'
|
|
71
|
+
};
|
|
72
|
+
return escape[match];
|
|
73
|
+
});
|
|
74
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./banner"), exports);
|
|
18
|
+
__exportStar(require("./helpers"), exports);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export declare enum LogLevel {
|
|
2
|
+
INFO = "INFO",
|
|
3
|
+
WARNING = "WARNING",
|
|
4
|
+
ERROR = "ERROR",
|
|
5
|
+
ATTACK = "ATTACK",
|
|
6
|
+
DEBUG = "DEBUG"
|
|
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 {};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.logger = exports.LogLevel = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
var LogLevel;
|
|
10
|
+
(function (LogLevel) {
|
|
11
|
+
LogLevel["INFO"] = "INFO";
|
|
12
|
+
LogLevel["WARNING"] = "WARNING";
|
|
13
|
+
LogLevel["ERROR"] = "ERROR";
|
|
14
|
+
LogLevel["ATTACK"] = "ATTACK";
|
|
15
|
+
LogLevel["DEBUG"] = "DEBUG";
|
|
16
|
+
})(LogLevel || (exports.LogLevel = LogLevel = {}));
|
|
17
|
+
class Logger {
|
|
18
|
+
constructor() {
|
|
19
|
+
this.logBuffer = [];
|
|
20
|
+
this.bufferSize = 100;
|
|
21
|
+
this.logFile = path_1.default.join(process.cwd(), 'yongky-security.log');
|
|
22
|
+
this.enableFileLogging = true;
|
|
23
|
+
this.enableConsoleLogging = true;
|
|
24
|
+
this.initLogFile();
|
|
25
|
+
}
|
|
26
|
+
initLogFile() {
|
|
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();
|
package/docs/API.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# API Documentation
|
|
2
|
+
|
|
3
|
+
## YONGKY SECURITY V3 API
|
|
4
|
+
|
|
5
|
+
### ModulesEz(config)
|
|
6
|
+
|
|
7
|
+
Main function to initialize YONGKY security.
|
|
8
|
+
|
|
9
|
+
**Parameters:**
|
|
10
|
+
- `config` (Object) - Configuration object
|
|
11
|
+
|
|
12
|
+
**Returns:**
|
|
13
|
+
- Function that accepts Express app
|
|
14
|
+
|
|
15
|
+
### Configuration Object
|
|
16
|
+
|
|
17
|
+
| Option | Type | Default | Description |
|
|
18
|
+
|--------|------|---------|-------------|
|
|
19
|
+
| anti_ddos | boolean/object | false | DDoS protection |
|
|
20
|
+
| anti_sql | boolean | false | SQL injection protection |
|
|
21
|
+
| anti_xss | boolean | false | XSS protection |
|
|
22
|
+
| anti_curl | boolean | false | Bot/curl protection |
|
|
23
|
+
| anti_header | boolean | false | Malicious headers protection |
|
|
24
|
+
| anti_bruteforce | boolean | false | Brute force protection |
|
|
25
|
+
| anti_rateLimit | boolean/object | false | Rate limiter |
|
|
26
|
+
| anti_malware | boolean | false | Malware detection |
|
|
27
|
+
| anti_pengunjung | string/false | false | IP whitelist |
|
|
28
|
+
|
|
29
|
+
### DDoS Configuration
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
{
|
|
33
|
+
maxPerMinute: 60, // Number (default: 60)
|
|
34
|
+
blockDuration: 60 // Number in seconds (default: 60)
|
|
35
|
+
}
|
package/docs/EXAMPLE.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# EXAMPLE USAGE - YONGKY SECURITY V3
|
|
2
|
+
|
|
3
|
+
## Daftar Isi
|
|
4
|
+
1. [Basic Server](#1-basic-server)
|
|
5
|
+
2. [Full Protection](#2-full-protection)
|
|
6
|
+
3. [Custom DDoS](#3-custom-ddos)
|
|
7
|
+
4. [Custom Rate Limit](#4-custom-rate-limit)
|
|
8
|
+
5. [IP Whitelist](#5-ip-whitelist)
|
|
9
|
+
6. [No Whitelist](#6-no-whitelist)
|
|
10
|
+
7. [TypeScript](#7-typescript)
|
|
11
|
+
8. [Production Server](#8-production-server)
|
|
12
|
+
9. [REST API](#9-rest-api)
|
|
13
|
+
10. [Login System](#10-login-system)
|
|
14
|
+
11. [File Upload](#11-file-upload)
|
|
15
|
+
12. [Webhook Receiver](#12-webhook-receiver)
|
|
16
|
+
13. [Microservice](#13-microservice)
|
|
17
|
+
14. [GraphQL API](#14-graphql-api)
|
|
18
|
+
15. [Socket.IO](#15-socketio)
|
|
19
|
+
16. [Admin Panel](#16-admin-panel)
|
|
20
|
+
17. [Public Website](#17-public-website)
|
|
21
|
+
18. [E-commerce API](#18-e-commerce-api)
|
|
22
|
+
19. [Banking API](#19-banking-api)
|
|
23
|
+
20. [Healthcare API](#20-healthcare-api)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 1. Basic Server
|
|
28
|
+
|
|
29
|
+
```javascript
|
|
30
|
+
const express = require('express');
|
|
31
|
+
const ModulesEz = require('modules-ez-v3');
|
|
32
|
+
|
|
33
|
+
const app = express();
|
|
34
|
+
|
|
35
|
+
ModulesEz({
|
|
36
|
+
anti_ddos: true,
|
|
37
|
+
anti_sql: true,
|
|
38
|
+
anti_curl: true
|
|
39
|
+
})(app);
|
|
40
|
+
|
|
41
|
+
app.get('/', (req, res) => {
|
|
42
|
+
res.json({ message: 'YONGKY SECURITY ACTIVE! šæ' });
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
app.listen(3000);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const ModulesEz = require('../dist/index');
|
|
3
|
+
|
|
4
|
+
const app = express();
|
|
5
|
+
|
|
6
|
+
// CONFIG ADVANCED - CUSTOM SEMUA
|
|
7
|
+
ModulesEz({
|
|
8
|
+
// Custom DDoS protection
|
|
9
|
+
anti_ddos: {
|
|
10
|
+
maxPerMinute: 30, // Maks 30 request per menit
|
|
11
|
+
blockDuration: 120 // Block 2 menit kalo kena
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
// Aktifin semua defense
|
|
15
|
+
anti_sql: true,
|
|
16
|
+
anti_xss: true,
|
|
17
|
+
anti_curl: true,
|
|
18
|
+
anti_header: true,
|
|
19
|
+
anti_bruteforce: true,
|
|
20
|
+
|
|
21
|
+
// Rate limit custom
|
|
22
|
+
anti_rateLimit: {
|
|
23
|
+
windowMs: 60000, // 1 menit
|
|
24
|
+
maxRequests: 50 // Maks 50 request
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
anti_malware: true,
|
|
28
|
+
|
|
29
|
+
// Whitelist khusus buat IP owner
|
|
30
|
+
anti_pengunjung: "127.0.0.1,192.168.1.100"
|
|
31
|
+
})(app);
|
|
32
|
+
|
|
33
|
+
// Routes
|
|
34
|
+
app.get('/', (req, res) => {
|
|
35
|
+
res.json({
|
|
36
|
+
message: 'YONGKY ULTIMATE SECURITY šæ',
|
|
37
|
+
timestamp: new Date().toISOString()
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
app.get('/api/data', (req, res) => {
|
|
42
|
+
res.json({ data: 'Protected data', secured: true });
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
app.post('/api/login', (req, res) => {
|
|
46
|
+
res.json({ message: 'Login attempt logged' });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Error handler
|
|
50
|
+
app.use((err, req, res, next) => {
|
|
51
|
+
console.error('Error:', err);
|
|
52
|
+
res.status(500).json({ error: 'Internal error' });
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const PORT = process.env.PORT || 3000;
|
|
56
|
+
app.listen(PORT, () => {
|
|
57
|
+
console.log(`\nš Advanced server running on port ${PORT}`);
|
|
58
|
+
console.log(`š”ļø YONGKY SECURITY V3 ACTIVE\n`);
|
|
59
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const ModulesEz = require('../dist/index');
|
|
3
|
+
|
|
4
|
+
const app = express();
|
|
5
|
+
|
|
6
|
+
// CONFIG SIMPLE - AKTIFIN SEMUA
|
|
7
|
+
ModulesEz({
|
|
8
|
+
anti_ddos: true,
|
|
9
|
+
anti_sql: true,
|
|
10
|
+
anti_curl: true,
|
|
11
|
+
anti_header: true,
|
|
12
|
+
anti_pengunjung: false, // GA pake whitelist
|
|
13
|
+
anti_xss: true,
|
|
14
|
+
anti_bruteforce: true,
|
|
15
|
+
anti_rateLimit: true,
|
|
16
|
+
anti_malware: true
|
|
17
|
+
})(app);
|
|
18
|
+
|
|
19
|
+
app.get('/', (req, res) => {
|
|
20
|
+
res.json({
|
|
21
|
+
message: 'YONGKY SECURITY ACTIVE! šæ',
|
|
22
|
+
status: 'Protected'
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
app.post('/login', (req, res) => {
|
|
27
|
+
res.json({ message: 'Login endpoint' });
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const PORT = 3000;
|
|
31
|
+
app.listen(PORT, () => {
|
|
32
|
+
console.log(`\nš Server: http://localhost:${PORT}`);
|
|
33
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// PALING SIMPLE - COPY PASTE LANGSUNG JALAN
|
|
2
|
+
const express = require('express');
|
|
3
|
+
const ModulesEz = require('modules-ez-v3');
|
|
4
|
+
|
|
5
|
+
const app = express();
|
|
6
|
+
|
|
7
|
+
// CUMA 1 BARIS ACTIVATE!
|
|
8
|
+
ModulesEz({
|
|
9
|
+
anti_ddos: true,
|
|
10
|
+
anti_sql: true,
|
|
11
|
+
anti_curl: true,
|
|
12
|
+
anti_header: true,
|
|
13
|
+
anti_xss: true,
|
|
14
|
+
anti_bruteforce: true
|
|
15
|
+
})(app);
|
|
16
|
+
|
|
17
|
+
app.get('/', (req, res) => {
|
|
18
|
+
res.send('Server aman bersama YONGKY! šæ');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
app.listen(3000);
|