| |
| |
| |
| |
| |
| |
|
|
| class AdvancedVulnerabilityDetector { |
| constructor() { |
| this.nlpEngine = new NLPVulnerabilityEngine(); |
| this.patternRecognizer = new AdvancedPatternRecognizer(); |
| this.mlClassifier = new MLVulnerabilityClassifier(); |
| this.semanticAnalyzer = new SemanticCodeAnalyzer(); |
| this.contextAnalyzer = new ContextualAnalyzer(); |
| this.initialized = false; |
| this.detectionCache = new Map(); |
| this.learningData = []; |
| } |
|
|
| async initialize() { |
| try { |
| console.log('🔍 Initializing Advanced Vulnerability Detector...'); |
| |
| |
| await this.nlpEngine.initialize(); |
| |
| |
| await this.patternRecognizer.initialize(); |
| |
| |
| await this.mlClassifier.initialize(); |
| |
| |
| await this.semanticAnalyzer.initialize(); |
| |
| |
| await this.contextAnalyzer.initialize(); |
| |
| |
| await this.loadVulnerabilityKnowledgeBase(); |
| |
| |
| this.setupRealTimeDetection(); |
| |
| this.initialized = true; |
| console.log('✅ Advanced Vulnerability Detector initialized successfully'); |
| |
| } catch (error) { |
| console.error('❌ Failed to initialize Advanced Vulnerability Detector:', error); |
| throw error; |
| } |
| } |
|
|
| async loadVulnerabilityKnowledgeBase() { |
| this.vulnerabilityPatterns = { |
| sql_injection: { |
| patterns: [ |
| /union\s+select/gi, |
| /['"]\s*or\s*['"]1['"]\s*=\s*['"]1['"]/gi, |
| /\b(drop|delete|update|insert)\s+table/gi, |
| /\b(exec|execute)\s*\(/gi, |
| /--\s*$/gm, |
| /\bshutdown\b/gi, |
| /\b xp_cmdshell \b/gi |
| ], |
| semantic: { |
| keywords: ['sql', 'database', 'query', 'select', 'insert', 'update', 'delete'], |
| context: ['user_input', 'parameter', 'request', 'form'], |
| severity: 9 |
| }, |
| variants: [ |
| 'union-based injection', |
| 'boolean-based injection', |
| 'time-based injection', |
| 'error-based injection', |
| 'stacked queries injection' |
| ] |
| }, |
| |
| xss: { |
| patterns: [ |
| /<script\b[^>]*>.*?<\/script>/gi, |
| /<iframe\b[^>]*>/gi, |
| /\bon\w+\s*=\s*["'][^"']*["']/gi, |
| /javascript:/gi, |
| /\beval\s*\(/gi, |
| /\bdocument\.(cookie|location)\b/gi, |
| /\bwindow\.(location|open)\b/gi |
| ], |
| semantic: { |
| keywords: ['html', 'script', 'javascript', 'event', 'onclick', 'onload'], |
| context: ['output', 'display', 'render', 'innerHTML', 'document.write'], |
| severity: 8 |
| }, |
| variants: [ |
| 'reflected XSS', |
| 'stored XSS', |
| 'DOM-based XSS', |
| 'mXSS (mutated XSS)', |
| 'Universal XSS (UXSS)' |
| ] |
| }, |
| |
| command_injection: { |
| patterns: [ |
| /[;&|`$]\s*(?:ls|cat|rm|mkdir|chmod|chown|wget|curl|nc|netcat|telnet|ssh)/gi, |
| /\bexec\s*\(\s*\$_(?:GET|POST|REQUEST)\[/gi, |
| /\bshell_exec\s*\(/gi, |
| /\bsystem\s*\(/gi, |
| /\bpopen\s*\(/gi, |
| /`[^`]*`/gi |
| ], |
| semantic: { |
| keywords: ['exec', 'system', 'shell', 'command', 'bash', 'cmd'], |
| context: ['system', 'shell', 'os', 'command', 'execute'], |
| severity: 10 |
| }, |
| variants: [ |
| 'OS Command Injection', |
| 'Shell Injection', |
| 'Code Injection', |
| 'LDAP Injection', |
| 'XPath Injection' |
| ] |
| }, |
| |
| path_traversal: { |
| patterns: [ |
| /\.\.[\/\\]/gi, |
| /%2e%2e%2f/gi, |
| /%252e%252e%252f/gi, |
| /\.\.%2f/gi, |
| /etc\/passwd/gi, |
| /boot\.ini/gi, |
| /windows\/system32/gi |
| ], |
| semantic: { |
| keywords: ['path', 'file', 'directory', 'folder', 'read', 'open'], |
| context: ['file_path', 'directory', 'include', 'require', 'import'], |
| severity: 8 |
| }, |
| variants: [ |
| 'Directory Traversal', |
| 'Path Traversal', |
| 'File Inclusion', |
| 'Null Byte Injection', |
| 'Unicode Traversal' |
| ] |
| }, |
| |
| csrf: { |
| patterns: [ |
| /<form[^>]*method\s*=\s*["']?(?:post|put|delete)["']?[^>]*>/gi, |
| /\b(csrf_token|xsrf_token)\b/gi, |
| /\breferer\s*=/gi, |
| /\borigin\s*=/gi, |
| /\bwithCredentials\s*=/gi |
| ], |
| semantic: { |
| keywords: ['form', 'post', 'token', 'validate', 'verify'], |
| context: ['form', 'request', 'action', 'submit', 'method'], |
| severity: 7 |
| }, |
| variants: [ |
| 'Login CSRF', |
| 'Session Fixation', |
| 'Cross-Site Request Forgery', |
| 'One-Click Attack', |
| 'Smart CSRF' |
| ] |
| }, |
| |
| deserialization: { |
| patterns: [ |
| /\b(unserialize|json_decode|yaml_parse|pickle_loads)\s*\(/gi, |
| /\bphar:\/\//gi, |
| /O:\d+:/gi, |
| /a:\d+:/gi, |
| /\b@eval\s*\(/gi, |
| /\b__wakeup\b/gi, |
| /\b__destruct\b/gi |
| ], |
| semantic: { |
| keywords: ['serialize', 'deserialize', 'pickle', 'unserialize', 'object'], |
| context: ['object', 'class', 'method', 'function', 'callback'], |
| severity: 9 |
| }, |
| variants: [ |
| 'PHP Deserialization', |
| 'Python Pickle Injection', |
| 'Java Deserialization', |
| '.NET Deserialization', |
| 'Ruby YAML Deserialization' |
| ] |
| }, |
| |
| server_side_request_forgery: { |
| patterns: [ |
| /\b(file_get_contents|curl_exec|wget|fsockopen)\s*\(\s*\$_(?:GET|POST|REQUEST)/gi, |
| /\b(urlopen|urlretrieve)\s*\(/gi, |
| /\b(HttpRequest|WebClient)\s*\(/gi, |
| /https?:\/\/localhost/gi, |
| /file:\/\//gi, |
| /dict:\/\//gi |
| ], |
| semantic: { |
| keywords: ['request', 'url', 'fetch', 'get', 'download', 'include'], |
| context: ['http', 'request', 'url', 'fetch', 'download'], |
| severity: 9 |
| }, |
| variants: [ |
| 'Basic SSRF', |
| 'Blind SSRF', |
| 'Semi-Blind SSRF', |
| 'XXE (XML External Entity)', |
| 'Open Redirect' |
| ] |
| } |
| }; |
| } |
|
|
| async analyzeCode(code, options = {}) { |
| if (!this.initialized) { |
| await this.initialize(); |
| } |
|
|
| const analysisId = this.generateAnalysisId(code); |
| |
| |
| if (this.detectionCache.has(analysisId) && !options.force) { |
| console.log('📋 Returning cached analysis result'); |
| return this.detectionCache.get(analysisId); |
| } |
|
|
| console.log('🔍 Starting comprehensive vulnerability analysis...'); |
|
|
| const analysisResults = { |
| id: analysisId, |
| timestamp: Date.now(), |
| code: code, |
| vulnerabilities: [], |
| riskScore: 0, |
| confidence: 0, |
| recommendations: [], |
| analysisTime: 0, |
| methods: [] |
| }; |
|
|
| const startTime = performance.now(); |
|
|
| try { |
| |
| const [ |
| patternResults, |
| semanticResults, |
| contextualResults, |
| mlResults, |
| nlpResults |
| ] = await Promise.allSettled([ |
| this.patternRecognizer.analyze(code, this.vulnerabilityPatterns), |
| this.semanticAnalyzer.analyze(code), |
| this.contextAnalyzer.analyze(code), |
| this.mlClassifier.classify(code), |
| this.nlpEngine.analyze(code) |
| ]); |
|
|
| |
| if (patternResults.status === 'fulfilled') { |
| analysisResults.vulnerabilities.push(...patternResults.value); |
| analysisResults.methods.push('pattern_recognition'); |
| } |
|
|
| if (semanticResults.status === 'fulfilled') { |
| analysisResults.vulnerabilities.push(...semanticResults.value); |
| analysisResults.methods.push('semantic_analysis'); |
| } |
|
|
| if (contextualResults.status === 'fulfilled') { |
| analysisResults.vulnerabilities.push(...contextualResults.value); |
| analysisResults.methods.push('contextual_analysis'); |
| } |
|
|
| if (mlResults.status === 'fulfilled') { |
| analysisResults.vulnerabilities.push(...mlResults.value); |
| analysisResults.methods.push('machine_learning'); |
| } |
|
|
| if (nlpResults.status === 'fulfilled') { |
| analysisResults.vulnerabilities.push(...nlpResults.value); |
| analysisResults.methods.push('nlp_analysis'); |
| } |
|
|
| |
| analysisResults.vulnerabilities = this.deduplicateVulnerabilities( |
| analysisResults.vulnerabilities |
| ); |
|
|
| |
| analysisResults.riskScore = this.calculateRiskScore(analysisResults.vulnerabilities); |
|
|
| |
| analysisResults.confidence = this.calculateConfidence(analysisResults); |
|
|
| |
| analysisResults.recommendations = this.generateRecommendations( |
| analysisResults.vulnerabilities |
| ); |
|
|
| const endTime = performance.now(); |
| analysisResults.analysisTime = endTime - startTime; |
|
|
| |
| this.detectionCache.set(analysisId, analysisResults); |
|
|
| |
| this.learningData.push({ |
| code: code, |
| vulnerabilities: analysisResults.vulnerabilities, |
| timestamp: Date.now() |
| }); |
|
|
| console.log(`✅ Analysis completed in ${analysisResults.analysisTime.toFixed(2)}ms`); |
| return analysisResults; |
|
|
| } catch (error) { |
| console.error('Analysis failed:', error); |
| throw new Error(`Vulnerability analysis failed: ${error.message}`); |
| } |
| } |
|
|
| deduplicateVulnerabilities(vulnerabilities) { |
| const seen = new Set(); |
| return vulnerabilities.filter(vuln => { |
| const key = `${vuln.type}-${vuln.line}-${vuln.startColumn}-${vuln.endColumn}`; |
| if (seen.has(key)) { |
| return false; |
| } |
| seen.add(key); |
| return true; |
| }); |
| } |
|
|
| calculateRiskScore(vulnerabilities) { |
| if (vulnerabilities.length === 0) return 0; |
|
|
| const weightedScore = vulnerabilities.reduce((score, vuln) => { |
| const baseScore = vuln.severity || 5; |
| const confidenceMultiplier = vuln.confidence || 0.5; |
| const contextMultiplier = vuln.contextScore || 1; |
| |
| return score + (baseScore * confidenceMultiplier * contextMultiplier); |
| }, 0); |
|
|
| return Math.min(100, weightedScore); |
| } |
|
|
| calculateConfidence(analysisResults) { |
| const methodCount = analysisResults.methods.length; |
| const vulnerabilityCount = analysisResults.vulnerabilities.length; |
| const avgConfidence = analysisResults.vulnerabilities.reduce( |
| (sum, vuln) => sum + (vuln.confidence || 0.5), 0 |
| ) / Math.max(vulnerabilityCount, 1); |
|
|
| |
| const methodBonus = Math.min(0.3, (methodCount - 1) * 0.1); |
| |
| return Math.min(0.99, avgConfidence + methodBonus); |
| } |
|
|
| generateRecommendations(vulnerabilities) { |
| const recommendations = []; |
| const vulnTypes = [...new Set(vulnerabilities.map(v => v.type))]; |
|
|
| for (const vulnType of vulnTypes) { |
| const vulnGroup = vulnerabilities.filter(v => v.type === vulnType); |
| const maxSeverity = Math.max(...vulnGroup.map(v => v.severity || 5)); |
|
|
| switch (vulnType) { |
| case 'sql_injection': |
| recommendations.push({ |
| type: 'SQL Injection Prevention', |
| priority: maxSeverity >= 8 ? 'Critical' : 'High', |
| actions: [ |
| 'Use parameterized queries for all database operations', |
| 'Implement input validation and sanitization', |
| 'Use ORM frameworks when possible', |
| 'Apply principle of least privilege for database accounts' |
| ], |
| code: `// Safe example |
| const query = 'SELECT * FROM users WHERE id = ? AND password_hash = ?'; |
| const result = db.execute(query, [userId, passwordHash]);` |
| }); |
| break; |
|
|
| case 'xss': |
| recommendations.push({ |
| type: 'XSS Prevention', |
| priority: maxSeverity >= 8 ? 'Critical' : 'High', |
| actions: [ |
| 'Implement Content Security Policy (CSP)', |
| 'Use output encoding for all user data', |
| 'Avoid innerHTML for user content', |
| 'Use textContent instead of innerHTML', |
| 'Validate and sanitize all inputs' |
| ], |
| code: `// Safe example |
| element.textContent = userInput; // Instead of element.innerHTML = userInput |
| |
| // CSP header |
| Content-Security-Policy: default-src 'self'; script-src 'self';` |
| }); |
| break; |
|
|
| case 'command_injection': |
| recommendations.push({ |
| type: 'Command Injection Prevention', |
| priority: 'Critical', |
| actions: [ |
| 'Avoid shell command execution with user input', |
| 'Use APIs instead of system calls when possible', |
| 'Implement strict input validation', |
| 'Use allowlists instead of blocklists', |
| 'Escape shell metacharacters' |
| ], |
| code: `// Safe example - avoid |
| // system("ls " + userInput); // UNSAFE |
| |
| // Instead use |
| const allowedCommands = ['list', 'info', 'status']; |
| if (allowedCommands.includes(userInput)) { |
| executeCommand(userInput); |
| }` |
| }); |
| break; |
|
|
| case 'csrf': |
| recommendations.push({ |
| type: 'CSRF Prevention', |
| priority: 'High', |
| actions: [ |
| 'Implement CSRF tokens for all state-changing operations', |
| 'Use SameSite cookies', |
| 'Validate Referer and Origin headers', |
| 'Use POST for state-changing operations', |
| 'Implement rate limiting' |
| ], |
| code: `// Safe example |
| // Generate CSRF token |
| const csrfToken = generateSecureToken(); |
| |
| // Include in forms |
| <form method="POST"> |
| <input type="hidden" name="csrf_token" value="${csrfToken}"> |
| </form> |
| |
| // Validate on server |
| if (!validateCSRFToken(request.csrf_token, session.csrf_token)) { |
| throw new Error('Invalid CSRF token'); |
| }` |
| }); |
| break; |
|
|
| case 'deserialization': |
| recommendations.push({ |
| type: 'Deserialization Prevention', |
| priority: 'Critical', |
| actions: [ |
| 'Avoid deserializing untrusted data', |
| 'Use safe serialization formats (JSON)', |
| 'Implement integrity checks', |
| 'Validate object types before deserialization', |
| 'Use type-safe deserialization libraries' |
| ], |
| code: `// Safe example |
| // Instead of unsafe deserialization |
| // unserialize(userInput); // UNSAFE |
| |
| // Use JSON |
| const data = JSON.parse(userInput); // Safe |
| |
| // For PHP, use safe deserialization |
| $object = Symfony\Component\Yaml\Yaml::parse($userInput);` |
| }); |
| break; |
| } |
| } |
|
|
| return recommendations; |
| } |
|
|
| generateAnalysisId(code) { |
| return 'analysis_' + this.simpleHash(code); |
| } |
|
|
| simpleHash(str) { |
| let hash = 0; |
| for (let i = 0; i < str.length; i++) { |
| const char = str.charCodeAt(i); |
| hash = ((hash << 5) - hash) + char; |
| hash = hash & hash; |
| } |
| return Math.abs(hash).toString(36); |
| } |
|
|
| setupRealTimeDetection() { |
| |
| if (typeof window !== 'undefined') { |
| |
| const observer = new MutationObserver((mutations) => { |
| mutations.forEach((mutation) => { |
| mutation.addedNodes.forEach((node) => { |
| if (node.nodeType === Node.ELEMENT_NODE) { |
| this.analyzeElement(node); |
| } |
| }); |
| }); |
| }); |
|
|
| observer.observe(document.body, { |
| childList: true, |
| subtree: true |
| }); |
|
|
| |
| const originalCreateElement = document.createElement; |
| document.createElement = function(tagName) { |
| const element = originalCreateElement.call(this, tagName); |
| if (tagName.toLowerCase() === 'script') { |
| this.analyzeElement(element); |
| } |
| return element; |
| }; |
| } |
| } |
|
|
| async analyzeElement(element) { |
| const html = element.outerHTML || ''; |
| if (html.length > 0) { |
| try { |
| const results = await this.analyzeCode(html, { force: true }); |
| if (results.vulnerabilities.length > 0) { |
| console.warn('🚨 Real-time vulnerability detected:', results.vulnerabilities); |
| this.handleRealTimeVulnerability(results); |
| } |
| } catch (error) { |
| |
| } |
| } |
| } |
|
|
| handleRealTimeVulnerability(results) { |
| |
| if (typeof window !== 'undefined' && window.dispatchEvent) { |
| window.dispatchEvent(new CustomEvent('vulnerabilityDetected', { |
| detail: results |
| })); |
| } |
| } |
|
|
| |
| async getVulnerabilityPatterns() { |
| return this.vulnerabilityPatterns; |
| } |
|
|
| async getAnalysisHistory() { |
| return Array.from(this.detectionCache.values()); |
| } |
|
|
| async exportResults(format = 'json') { |
| const results = Array.from(this.detectionCache.values()); |
| |
| switch (format) { |
| case 'json': |
| return JSON.stringify(results, null, 2); |
| case 'csv': |
| return this.convertToCSV(results); |
| case 'html': |
| return this.convertToHTML(results); |
| default: |
| return JSON.stringify(results, null, 2); |
| } |
| } |
|
|
| convertToCSV(results) { |
| const headers = ['ID', 'Timestamp', 'Risk Score', 'Confidence', 'Vulnerabilities', 'Methods']; |
| const rows = results.map(result => [ |
| result.id, |
| new Date(result.timestamp).toISOString(), |
| result.riskScore, |
| result.confidence, |
| result.vulnerabilities.length, |
| result.methods.join(';') |
| ]); |
|
|
| return [headers, ...rows].map(row => row.join(',')).join('\n'); |
| } |
|
|
| convertToHTML(results) { |
| let html = ` |
| <!DOCTYPE html> |
| <html dir="rtl" lang="ar"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>نتائج تحليل الثغرات الأمنية</title> |
| <style> |
| body { font-family: Arial, sans-serif; margin: 20px; } |
| .vulnerability { border: 1px solid #ccc; margin: 10px 0; padding: 15px; border-radius: 5px; } |
| .critical { border-color: #ff0000; background-color: #ffe6e6; } |
| .high { border-color: #ff8800; background-color: #fff0e6; } |
| .medium { border-color: #ffff00; background-color: #ffffe6; } |
| .low { border-color: #00ff00; background-color: #e6ffe6; } |
| .severity { font-weight: bold; } |
| </style> |
| </head> |
| <body> |
| <h1>نتائج تحليل الثغرات الأمنية</h1> |
| <p>تم إنشاء التقرير في: ${new Date().toLocaleString('ar')}</p> |
| `; |
|
|
| results.forEach(result => { |
| html += `<div class="vulnerability">`; |
| html += `<h3>التحليل: ${result.id}</h3>`; |
| html += `<p><strong>درجة المخاطر:</strong> ${result.riskScore}</p>`; |
| html += `<p><strong>مستوى الثقة:</strong> ${(result.confidence * 100).toFixed(1)}%</p>`; |
| html += `<p><strong>عدد الثغرات:</strong> ${result.vulnerabilities.length}</p>`; |
| html += `<p><strong>طرق التحليل:</strong> ${result.methods.join(', ')}</p>`; |
| |
| if (result.vulnerabilities.length > 0) { |
| html += '<h4>الثغرات المكتشفة:</h4><ul>'; |
| result.vulnerabilities.forEach(vuln => { |
| html += `<li>${vuln.type} - الخط ${vuln.line} - الثقة: ${(vuln.confidence * 100).toFixed(1)}%</li>`; |
| }); |
| html += '</ul>'; |
| } |
| |
| html += `</div>`; |
| }); |
|
|
| html += '</body></html>'; |
| return html; |
| } |
|
|
| dispose() { |
| this.detectionCache.clear(); |
| this.learningData = []; |
| } |
| } |
|
|
| |
| |
| |
| class NLPVulnerabilityEngine { |
| async initialize() { |
| console.log('🧠 Initializing NLP Vulnerability Engine...'); |
| this.vocabulary = this.buildSecurityVocabulary(); |
| } |
|
|
| buildSecurityVocabulary() { |
| return { |
| dangerous: ['eval', 'exec', 'system', 'shell_exec', 'passthru', 'popen', 'proc_open'], |
| sql: ['select', 'insert', 'update', 'delete', 'union', 'drop', 'create', 'alter'], |
| xss: ['script', 'javascript', 'onclick', 'onload', 'innerHTML', 'document.write'], |
| injection: ['include', 'require', 'file_get_contents', 'curl_exec', 'wget'], |
| traversal: ['../', '..\\', '%2e%2e', 'file://', 'dict://'] |
| }; |
| } |
|
|
| async analyze(code) { |
| const results = []; |
| const tokens = this.tokenize(code); |
| |
| for (const [category, words] of Object.entries(this.vocabulary)) { |
| const matches = this.findContextualMatches(tokens, words, code); |
| if (matches.length > 0) { |
| results.push(...matches); |
| } |
| } |
| |
| return results; |
| } |
|
|
| tokenize(code) { |
| return code |
| .toLowerCase() |
| .replace(/[^\w\s]/g, ' ') |
| .split(/\s+/) |
| .filter(token => token.length > 0); |
| } |
|
|
| findContextualMatches(tokens, dangerousWords, originalCode) { |
| const results = []; |
| |
| tokens.forEach((token, index) => { |
| if (dangerousWords.includes(token)) { |
| |
| const context = this.getContext(tokens, index, 3); |
| const confidence = this.calculateContextualConfidence(token, context); |
| |
| if (confidence > 0.6) { |
| results.push({ |
| type: this.getVulnerabilityType(token), |
| confidence: confidence, |
| line: this.getLineNumber(originalCode, token), |
| column: this.getColumnNumber(originalCode, token), |
| context: context.join(' '), |
| method: 'nlp' |
| }); |
| } |
| } |
| }); |
| |
| return results; |
| } |
|
|
| getContext(tokens, index, windowSize) { |
| const start = Math.max(0, index - windowSize); |
| const end = Math.min(tokens.length, index + windowSize + 1); |
| return tokens.slice(start, end); |
| } |
|
|
| calculateContextualConfidence(token, context) { |
| let confidence = 0.5; |
| |
| |
| const dangerousContext = ['input', 'user', 'request', 'get', 'post', 'param']; |
| const hasDangerousContext = context.some(word => dangerousContext.includes(word)); |
| |
| if (hasDangerousContext) confidence += 0.3; |
| |
| |
| const assignmentPattern = context.some((word, i) => |
| word === '=' && i > 0 && dangerousContext.includes(context[i-1]) |
| ); |
| if (assignmentPattern) confidence += 0.2; |
| |
| return Math.min(0.99, confidence); |
| } |
|
|
| getVulnerabilityType(token) { |
| const typeMap = { |
| 'eval': 'code_injection', |
| 'exec': 'command_injection', |
| 'system': 'command_injection', |
| 'shell_exec': 'command_injection', |
| 'select': 'sql_injection', |
| 'union': 'sql_injection', |
| 'script': 'xss', |
| 'javascript': 'xss', |
| 'onclick': 'xss', |
| 'innerHTML': 'xss', |
| '../': 'path_traversal', |
| '..\\': 'path_traversal' |
| }; |
| |
| return typeMap[token] || 'unknown'; |
| } |
|
|
| getLineNumber(code, token) { |
| const lines = code.split('\n'); |
| for (let i = 0; i < lines.length; i++) { |
| if (lines[i].includes(token)) { |
| return i + 1; |
| } |
| } |
| return 1; |
| } |
|
|
| getColumnNumber(code, token) { |
| const lines = code.split('\n'); |
| for (let i = 0; i < lines.length; i++) { |
| const column = lines[i].indexOf(token); |
| if (column !== -1) { |
| return column + 1; |
| } |
| } |
| return 1; |
| } |
| } |
|
|
| |
| |
| |
| class AdvancedPatternRecognizer { |
| async initialize() { |
| console.log('🎯 Initializing Advanced Pattern Recognizer...'); |
| } |
|
|
| async analyze(code, patterns) { |
| const results = []; |
| |
| for (const [vulnType, vulnData] of Object.entries(patterns)) { |
| for (const pattern of vulnData.patterns) { |
| const matches = [...code.matchAll(new RegExp(pattern.source, pattern.flags))]; |
| |
| matches.forEach(match => { |
| const confidence = this.calculatePatternConfidence(match, vulnData); |
| |
| results.push({ |
| type: vulnType, |
| confidence: confidence, |
| line: this.getLineFromMatch(code, match), |
| column: this.getColumnFromMatch(code, match), |
| match: match[0], |
| startIndex: match.index, |
| endIndex: match.index + match[0].length, |
| severity: vulnData.semantic.severity, |
| method: 'pattern_recognition' |
| }); |
| }); |
| } |
| } |
| |
| return results; |
| } |
|
|
| calculatePatternConfidence(match, vulnData) { |
| let confidence = 0.7; |
| |
| |
| const matchStr = match[0]; |
| const contextBoost = this.getContextualBoost(matchStr, vulnData.semantic.keywords); |
| confidence += contextBoost; |
| |
| return Math.min(0.99, confidence); |
| } |
|
|
| getContextualBoost(matchStr, keywords) { |
| let boost = 0; |
| |
| |
| keywords.forEach(keyword => { |
| if (matchStr.toLowerCase().includes(keyword)) { |
| boost += 0.1; |
| } |
| }); |
| |
| return Math.min(0.2, boost); |
| } |
|
|
| getLineFromMatch(code, match) { |
| const lines = code.substring(0, match.index).split('\n'); |
| return lines.length; |
| } |
|
|
| getColumnFromMatch(code, match) { |
| const lines = code.substring(0, match.index).split('\n'); |
| const lastLine = lines[lines.length - 1]; |
| return lastLine.length + 1; |
| } |
| } |
|
|
| |
| |
| |
| class MLVulnerabilityClassifier { |
| async initialize() { |
| console.log('🤖 Initializing ML Vulnerability Classifier...'); |
| |
| this.model = { |
| weights: new Map(), |
| bias: 0.1 |
| }; |
| } |
|
|
| async classify(code) { |
| |
| const features = this.extractFeatures(code); |
| const prediction = this.predict(features); |
| |
| return [{ |
| type: prediction.threatType, |
| confidence: prediction.confidence, |
| severity: this.getSeverityScore(prediction.threatType), |
| method: 'machine_learning', |
| features: features |
| }]; |
| } |
|
|
| extractFeatures(code) { |
| return { |
| length: code.length, |
| tokenCount: this.countTokens(code), |
| complexity: this.calculateComplexity(code), |
| suspiciousPatterns: this.countSuspiciousPatterns(code), |
| contextScore: this.calculateContextScore(code) |
| }; |
| } |
|
|
| countTokens(code) { |
| return code |
| .replace(/[^\w]/g, ' ') |
| .split(/\s+/) |
| .filter(token => token.length > 0).length; |
| } |
|
|
| calculateComplexity(code) { |
| |
| const complexityKeywords = ['if', 'else', 'for', 'while', 'switch', 'case', 'try', 'catch']; |
| let complexity = 1; |
| |
| complexityKeywords.forEach(keyword => { |
| const matches = code.match(new RegExp('\\b' + keyword + '\\b', 'g')); |
| if (matches) complexity += matches.length; |
| }); |
| |
| return complexity; |
| } |
|
|
| countSuspiciousPatterns(code) { |
| const suspicious = ['eval', 'exec', 'system', 'shell', 'cmd', 'powershell']; |
| let count = 0; |
| |
| suspicious.forEach(pattern => { |
| const matches = code.match(new RegExp('\\b' + pattern + '\\b', 'gi')); |
| if (matches) count += matches.length; |
| }); |
| |
| return count; |
| } |
|
|
| calculateContextScore(code) { |
| |
| let score = 0; |
| const contextPatterns = [ |
| /input/i, |
| /user/i, |
| /request/i, |
| /form/i, |
| /database/i, |
| /query/i, |
| /file/i, |
| /path/i |
| ]; |
| |
| contextPatterns.forEach(pattern => { |
| if (pattern.test(code)) score += 0.1; |
| }); |
| |
| return Math.min(1.0, score); |
| } |
|
|
| predict(features) { |
| |
| const threatScore = ( |
| features.suspiciousPatterns * 0.3 + |
| features.complexity * 0.2 + |
| features.contextScore * 0.4 + |
| (features.length > 1000 ? 0.1 : 0) |
| ); |
| |
| const threatType = threatScore > 0.7 ? 'high_risk_code' : |
| threatScore > 0.4 ? 'medium_risk_code' : 'low_risk_code'; |
| |
| return { |
| threatType: threatType, |
| confidence: Math.min(0.95, threatScore * 1.2) |
| }; |
| } |
|
|
| getSeverityScore(threatType) { |
| const scoreMap = { |
| 'high_risk_code': 8, |
| 'medium_risk_code': 5, |
| 'low_risk_code': 2 |
| }; |
| return scoreMap[threatType] || 3; |
| } |
| } |
|
|
| |
| |
| |
| class SemanticCodeAnalyzer { |
| async initialize() { |
| console.log('🔬 Initializing Semantic Code Analyzer...'); |
| } |
|
|
| async analyze(code) { |
| const results = []; |
| const semanticPatterns = this.getSemanticPatterns(); |
| |
| for (const [patternName, pattern] of Object.entries(semanticPatterns)) { |
| const matches = this.findSemanticMatches(code, pattern); |
| if (matches.length > 0) { |
| results.push(...matches); |
| } |
| } |
| |
| return results; |
| } |
|
|
| getSemanticPatterns() { |
| return { |
| dangerous_function_calls: { |
| functions: ['eval', 'exec', 'system', 'shell_exec', 'passthru', 'popen'], |
| context: ['user', 'input', 'request', 'param'], |
| severity: 9 |
| }, |
| unsafe_file_operations: { |
| functions: ['file_get_contents', 'fopen', 'include', 'require'], |
| context: ['user', 'input', 'path', 'file'], |
| severity: 8 |
| }, |
| dynamic_code_execution: { |
| patterns: ['eval\\s*\\(', 'exec\\s*\\(', 'system\\s*\\('], |
| context: ['variable', 'user', 'request'], |
| severity: 10 |
| } |
| }; |
| } |
|
|
| findSemanticMatches(code, pattern) { |
| const results = []; |
| |
| |
| if (pattern.functions) { |
| pattern.functions.forEach(func => { |
| const regex = new RegExp(`\\b${func}\\s*\\(`, 'gi'); |
| const matches = [...code.matchAll(regex)]; |
| |
| matches.forEach(match => { |
| const context = this.extractContext(code, match.index, 50); |
| const contextScore = this.calculateContextRelevance(context, pattern.context); |
| |
| if (contextScore > 0.6) { |
| results.push({ |
| type: this.getVulnerabilityType(func), |
| confidence: contextScore, |
| line: this.getLineNumber(code, match.index), |
| column: this.getColumnNumber(code, match.index), |
| match: match[0], |
| semantic: true, |
| severity: pattern.severity, |
| method: 'semantic_analysis' |
| }); |
| } |
| }); |
| }); |
| } |
| |
| |
| if (pattern.patterns) { |
| pattern.patterns.forEach(pat => { |
| const regex = new RegExp(pat, 'gi'); |
| const matches = [...code.matchAll(regex)]; |
| |
| matches.forEach(match => { |
| const context = this.extractContext(code, match.index, 30); |
| const contextScore = this.calculateContextRelevance(context, pattern.context); |
| |
| if (contextScore > 0.7) { |
| results.push({ |
| type: 'dynamic_code_execution', |
| confidence: contextScore, |
| line: this.getLineNumber(code, match.index), |
| column: this.getColumnNumber(code, match.index), |
| match: match[0], |
| semantic: true, |
| severity: pattern.severity, |
| method: 'semantic_analysis' |
| }); |
| } |
| }); |
| }); |
| } |
| |
| return results; |
| } |
|
|
| extractContext(code, index, windowSize) { |
| const start = Math.max(0, index - windowSize); |
| const end = Math.min(code.length, index + windowSize); |
| return code.substring(start, end); |
| } |
|
|
| calculateContextRelevance(context, keywords) { |
| let relevance = 0.3; |
| |
| keywords.forEach(keyword => { |
| const keywordCount = (context.match(new RegExp(keyword, 'gi')) || []).length; |
| relevance += keywordCount * 0.2; |
| }); |
| |
| return Math.min(0.99, relevance); |
| } |
|
|
| getVulnerabilityType(func) { |
| const typeMap = { |
| 'eval': 'code_injection', |
| 'exec': 'command_injection', |
| 'system': 'command_injection', |
| 'shell_exec': 'command_injection', |
| 'file_get_contents': 'file_inclusion', |
| 'fopen': 'file_inclusion', |
| 'include': 'file_inclusion', |
| 'require': 'file_inclusion' |
| }; |
| |
| return typeMap[func] || 'unknown_function'; |
| } |
|
|
| getLineNumber(code, index) { |
| return code.substring(0, index).split('\n').length; |
| } |
|
|
| getColumnNumber(code, index) { |
| const lines = code.substring(0, index).split('\n'); |
| return lines[lines.length - 1].length + 1; |
| } |
| } |
|
|
| |
| |
| |
| class ContextualAnalyzer { |
| async initialize() { |
| console.log('🔍 Initializing Contextual Analyzer...'); |
| } |
|
|
| async analyze(code) { |
| const results = []; |
| |
| |
| const context = this.analyzeCodeContext(code); |
| const dataFlow = this.analyzeDataFlow(code); |
| const controlFlow = this.analyzeControlFlow(code); |
| |
| |
| if (context.hasUserInput) { |
| results.push(...this.checkInputValidation(code)); |
| } |
| |
| if (context.hasDatabaseOperations) { |
| results.push(...this.checkDatabaseSecurity(code)); |
| } |
| |
| if (context.hasFileOperations) { |
| results.push(...this.checkFileSecurity(code)); |
| } |
| |
| if (context.hasNetworkOperations) { |
| results.push(...this.checkNetworkSecurity(code)); |
| } |
| |
| return results; |
| } |
|
|
| analyzeCodeContext(code) { |
| return { |
| hasUserInput: /input|request|get|post|param/i.test(code), |
| hasDatabaseOperations: /database|query|select|insert|update|delete/i.test(code), |
| hasFileOperations: /file|read|write|open|include|require/i.test(code), |
| hasNetworkOperations: /http|https|curl|fetch|ajax/i.test(code), |
| hasDynamicContent: /eval|exec|system|shell/i.test(code), |
| complexity: this.calculateCodeComplexity(code) |
| }; |
| } |
|
|
| calculateCodeComplexity(code) { |
| let complexity = 0; |
| const complexityIndicators = [ |
| /if\s*\(/g, /else/g, /for\s*\(/g, /while\s*\(/g, |
| /switch/g, /case/g, /try/g, /catch/g, /\?\s*[^:]+:/g |
| ]; |
| |
| complexityIndicators.forEach(pattern => { |
| const matches = code.match(pattern); |
| if (matches) complexity += matches.length; |
| }); |
| |
| return complexity; |
| } |
|
|
| analyzeDataFlow(code) { |
| |
| return { |
| sources: this.identifyDataSources(code), |
| sinks: this.identifyDataSinks(code), |
| transformations: this.identifyTransformations(code) |
| }; |
| } |
|
|
| identifyDataSources(code) { |
| const sources = []; |
| const sourcePatterns = [ |
| /\$_(?:GET|POST|REQUEST|COOKIE|SERVER)\[/g, |
| /input\s*\(/g, |
| /prompt\s*\(/g, |
| /readline\s*\(/g |
| ]; |
| |
| sourcePatterns.forEach(pattern => { |
| const matches = code.match(pattern); |
| if (matches) sources.push(...matches); |
| }); |
| |
| return sources; |
| } |
|
|
| identifyDataSinks(code) { |
| const sinks = []; |
| const sinkPatterns = [ |
| /innerHTML\s*=/g, |
| /document\.write\s*\(/g, |
| /eval\s*\(/g, |
| /exec\s*\(/g, |
| /system\s*\(/g, |
| /file_put_contents\s*\(/g |
| ]; |
| |
| sinkPatterns.forEach(pattern => { |
| const matches = code.match(pattern); |
| if (matches) sinks.push(...matches); |
| }); |
| |
| return sinks; |
| } |
|
|
| identifyTransformations(code) { |
| const transformations = []; |
| const transformPatterns = [ |
| /htmlspecialchars\s*\(/g, |
| /addslashes\s*\(/g, |
| /mysql_real_escape_string\s*\(/g, |
| /json_encode\s*\(/g, |
| /base64_encode\s*\(/g |
| ]; |
| |
| transformPatterns.forEach(pattern => { |
| const matches = code.match(pattern); |
| if (matches) transformations.push(...matches); |
| }); |
| |
| return transformations; |
| } |
|
|
| analyzeControlFlow(code) { |
| |
| return { |
| hasConditionals: /if\s*\(/.test(code), |
| hasLoops: /for\s*\(/.test(code) || /while\s*\(/.test(code), |
| hasExceptions: /try\s*\{/.test(code), |
| depth: this.calculateNestingDepth(code) |
| }; |
| } |
|
|
| calculateNestingDepth(code) { |
| let maxDepth = 0; |
| let currentDepth = 0; |
| |
| for (const char of code) { |
| if (char === '{') { |
| currentDepth++; |
| maxDepth = Math.max(maxDepth, currentDepth); |
| } else if (char === '}') { |
| currentDepth--; |
| } |
| } |
| |
| return maxDepth; |
| } |
|
|
| checkInputValidation(code) { |
| const results = []; |
| |
| |
| if (/\$_(?:GET|POST|REQUEST)/.test(code) && !/filter_var|htmlspecialchars|addslashes/.test(code)) { |
| results.push({ |
| type: 'missing_input_validation', |
| confidence: 0.8, |
| severity: 7, |
| method: 'contextual_analysis', |
| message: 'User input used without proper validation' |
| }); |
| } |
| |
| return results; |
| } |
|
|
| checkDatabaseSecurity(code) { |
| const results = []; |
| |
| |
| if (/\$_(?:GET|POST|REQUEST)/.test(code) && /query|select|insert|update|delete/i.test(code)) { |
| if (!/prepare|parameterized|bind_param/.test(code)) { |
| results.push({ |
| type: 'potential_sql_injection', |
| confidence: 0.7, |
| severity: 9, |
| method: 'contextual_analysis', |
| message: 'Potential SQL injection vulnerability detected' |
| }); |
| } |
| } |
| |
| return results; |
| } |
|
|
| checkFileSecurity(code) { |
| const results = []; |
| |
| |
| if (/\$_(?:GET|POST|REQUEST)/.test(code) && /(include|require)(_once)?\s*\(/i.test(code)) { |
| results.push({ |
| type: 'file_inclusion_vulnerability', |
| confidence: 0.8, |
| severity: 8, |
| method: 'contextual_analysis', |
| message: 'File inclusion with user input detected' |
| }); |
| } |
| |
| return results; |
| } |
|
|
| checkNetworkSecurity(code) { |
| const results = []; |
| |
| |
| if (/http:\/\//.test(code) && !/https:\/\//.test(code)) { |
| results.push({ |
| type: 'insecure_http_request', |
| confidence: 0.9, |
| severity: 6, |
| method: 'contextual_analysis', |
| message: 'Insecure HTTP request detected (should use HTTPS)' |
| }); |
| } |
| |
| return results; |
| } |
| } |
|
|
| |
| if (typeof module !== 'undefined' && module.exports) { |
| module.exports = { |
| AdvancedVulnerabilityDetector, |
| NLPVulnerabilityEngine, |
| AdvancedPatternRecognizer, |
| MLVulnerabilityClassifier, |
| SemanticCodeAnalyzer, |
| ContextualAnalyzer |
| }; |
| } |