UNPKG

@ordojs/security

Version:

Security package for OrdoJS with XSS, CSRF, and injection protection

173 lines 6.28 kB
/** * SQL Injection Prevention * Provides comprehensive protection against SQL injection attacks */ export class SqlInjectionPrevention { static SQL_INJECTION_PATTERNS = [ // Union-based injection patterns { pattern: /(\bunion\b.*\bselect\b)|(\bselect\b.*\bunion\b)/gi, severity: 'critical', description: 'UNION-based SQL injection attempt detected' }, // Boolean-based blind injection { pattern: /(\b(and|or)\b\s*\d+\s*[=<>]\s*\d+)|(\b(and|or)\b\s*['"]?\w+['"]?\s*[=<>]\s*['"]?\w+['"]?)/gi, severity: 'high', description: 'Boolean-based blind SQL injection attempt detected' }, // Time-based blind injection { pattern: /\b(sleep|waitfor|delay|benchmark)\s*\(/gi, severity: 'critical', description: 'Time-based blind SQL injection attempt detected' }, // Error-based injection { pattern: /\b(extractvalue|updatexml|exp|floor|rand)\s*\(/gi, severity: 'high', description: 'Error-based SQL injection attempt detected' }, // Stacked queries { pattern: /;\s*(drop|delete|insert|update|create|alter|exec|execute)\b/gi, severity: 'critical', description: 'Stacked query SQL injection attempt detected' }, // Comment-based evasion { pattern: /(\/\*.*?\*\/)|(--.*)|(#.*)/g, severity: 'medium', description: 'SQL comment-based evasion attempt detected' }, // Information schema access { pattern: /\binformation_schema\b/gi, severity: 'high', description: 'Information schema access attempt detected' }, // System function calls { pattern: /\b(xp_cmdshell|sp_oacreate|sp_oamethod|openrowset|opendatasource)\b/gi, severity: 'critical', description: 'System function SQL injection attempt detected' }, // Hex encoding evasion { pattern: /0x[0-9a-f]+/gi, severity: 'medium', description: 'Hex-encoded SQL injection attempt detected' }, // Concatenation-based evasion { pattern: /\bconcat\s*\(|(\|\|)|(\+\s*['"])/gi, severity: 'medium', description: 'Concatenation-based SQL injection attempt detected' } ]; /** * Validates input for SQL injection patterns */ static validateInput(input) { if (typeof input !== 'string') { return { isValid: true, threats: [] }; } const detectedThreats = []; for (const pattern of this.SQL_INJECTION_PATTERNS) { if (pattern.pattern.test(input)) { detectedThreats.push(pattern); } } return { isValid: detectedThreats.length === 0, threats: detectedThreats }; } /** * Sanitizes input by removing or escaping SQL injection patterns */ static sanitizeInput(input, options = {}) { if (typeof input !== 'string') { return String(input); } let sanitized = input; if (options.strict) { // In strict mode, remove any detected patterns entirely for (const pattern of this.SQL_INJECTION_PATTERNS) { sanitized = sanitized.replace(pattern.pattern, ''); } } else { // In normal mode, escape dangerous characters sanitized = sanitized .replace(/'/g, "''") // Escape single quotes .replace(/"/g, '""') // Escape double quotes .replace(/\\/g, '\\\\') // Escape backslashes .replace(/;/g, '\\;') // Escape semicolons .replace(/--/g, '\\-\\-') // Escape SQL comments .replace(/\/\*/g, '\\/\\*') // Escape block comments .replace(/\*\//g, '\\*\\/'); // Escape block comments } return sanitized.trim(); } /** * Creates a parameterized query-safe version of input */ static createSafeParameter(input) { if (typeof input === 'string') { return this.sanitizeInput(input, { strict: true }); } if (typeof input === 'number' || typeof input === 'boolean') { return input; } if (input === null || input === undefined) { return null; } if (Array.isArray(input)) { return input.map(item => this.createSafeParameter(item)); } if (typeof input === 'object') { const safeObject = {}; for (const [key, value] of Object.entries(input)) { safeObject[this.sanitizeInput(key)] = this.createSafeParameter(value); } return safeObject; } return String(input); } /** * Validates and sanitizes multiple inputs */ static validateAndSanitizeInputs(inputs) { const allThreats = []; const sanitizedInputs = {}; for (const [field, value] of Object.entries(inputs)) { try { const sanitized = this.createSafeParameter(value); sanitizedInputs[field] = sanitized; if (typeof value === 'string') { const validation = this.validateInput(value); if (!validation.isValid) { allThreats.push({ field, threats: validation.threats }); } } } catch (error) { allThreats.push({ field, threats: [{ pattern: /.*/, severity: 'critical', description: error instanceof Error ? error.message : 'Unknown SQL injection threat' }] }); } } return { isValid: allThreats.length === 0, threats: allThreats, sanitizedInputs }; } } //# sourceMappingURL=sql-injection-prevention.js.map