owasp-testing.tsā¢30.4 kB
import axios from 'axios';
import { ScanResult } from './recon.js';
import { ExtractedParameter } from './parameter-extraction.js';
export interface OWASPTestResult {
owasp_category: string;
owasp_id: string;
test_name: string;
vulnerability_found: boolean;
severity: 'info' | 'low' | 'medium' | 'high' | 'critical';
description: string;
evidence: string[];
affected_urls: string[];
remediation: string;
cwe_id?: string;
references: string[];
}
export interface OWASPTestConfiguration {
target_url: string;
authentication?: {
type: 'none' | 'basic' | 'cookie' | 'token';
credentials?: Record<string, string>;
};
scope: 'full' | 'passive' | 'active';
excluded_categories?: string[];
custom_payloads?: Record<string, string[]>;
}
export class OWASPTestingEngine {
async runOWASPTop10Tests(config: OWASPTestConfiguration): Promise<ScanResult> {
try {
console.error(`š Running OWASP Top 10 tests for ${config.target_url}`);
const testResults: OWASPTestResult[] = [];
// OWASP Top 10 2021 Categories
const owaspCategories = [
'A01:2021-Broken Access Control',
'A02:2021-Cryptographic Failures',
'A03:2021-Injection',
'A04:2021-Insecure Design',
'A05:2021-Security Misconfiguration',
'A06:2021-Vulnerable and Outdated Components',
'A07:2021-Identification and Authentication Failures',
'A08:2021-Software and Data Integrity Failures',
'A09:2021-Security Logging and Monitoring Failures',
'A10:2021-Server-Side Request Forgery (SSRF)'
];
for (const category of owaspCategories) {
if (config.excluded_categories?.includes(category)) {
console.error(` Skipping ${category} (excluded)`);
continue;
}
console.error(` Testing ${category}`);
const categoryResults = await this.testOWASPCategory(category, config);
testResults.push(...categoryResults);
}
// Analyze results
const criticalFindings = testResults.filter(r => r.severity === 'critical');
const highFindings = testResults.filter(r => r.severity === 'high');
const vulnerabilities = testResults.filter(r => r.vulnerability_found);
return {
target: config.target_url,
timestamp: new Date().toISOString(),
tool: 'owasp_top10_testing',
results: {
total_tests: testResults.length,
vulnerabilities_found: vulnerabilities.length,
critical_issues: criticalFindings.length,
high_risk_issues: highFindings.length,
owasp_compliance_score: this.calculateComplianceScore(testResults),
test_results: testResults,
executive_summary: this.generateExecutiveSummary(testResults),
recommendations: this.generateOWASPRecommendations(testResults)
},
status: 'success'
};
} catch (error) {
return {
target: config.target_url,
timestamp: new Date().toISOString(),
tool: 'owasp_top10_testing',
results: {},
status: 'error',
error: error instanceof Error ? error.message : String(error)
};
}
}
private async testOWASPCategory(category: string, config: OWASPTestConfiguration): Promise<OWASPTestResult[]> {
const results: OWASPTestResult[] = [];
switch (category) {
case 'A01:2021-Broken Access Control':
results.push(...await this.testBrokenAccessControl(config));
break;
case 'A02:2021-Cryptographic Failures':
results.push(...await this.testCryptographicFailures(config));
break;
case 'A03:2021-Injection':
results.push(...await this.testInjectionVulnerabilities(config));
break;
case 'A04:2021-Insecure Design':
results.push(...await this.testInsecureDesign(config));
break;
case 'A05:2021-Security Misconfiguration':
results.push(...await this.testSecurityMisconfiguration(config));
break;
case 'A06:2021-Vulnerable and Outdated Components':
results.push(...await this.testVulnerableComponents(config));
break;
case 'A07:2021-Identification and Authentication Failures':
results.push(...await this.testAuthenticationFailures(config));
break;
case 'A08:2021-Software and Data Integrity Failures':
results.push(...await this.testIntegrityFailures(config));
break;
case 'A09:2021-Security Logging and Monitoring Failures':
results.push(...await this.testLoggingMonitoringFailures(config));
break;
case 'A10:2021-Server-Side Request Forgery (SSRF)':
results.push(...await this.testSSRF(config));
break;
}
return results;
}
private async testBrokenAccessControl(config: OWASPTestConfiguration): Promise<OWASPTestResult[]> {
const results: OWASPTestResult[] = [];
// Test 1: Directory Traversal
const traversalPayloads = [
'../../../etc/passwd',
'..\\..\\..\\windows\\system32\\drivers\\etc\\hosts',
'....//....//....//etc/passwd',
'%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd'
];
for (const payload of traversalPayloads) {
try {
const testUrl = `${config.target_url}?file=${encodeURIComponent(payload)}`;
const response = await axios.get(testUrl, { timeout: 5000 });
if (response.data.includes('root:') || response.data.includes('127.0.0.1')) {
results.push({
owasp_category: 'A01:2021-Broken Access Control',
owasp_id: 'A01',
test_name: 'Directory Traversal',
vulnerability_found: true,
severity: 'high',
description: 'Application allows directory traversal attacks',
evidence: [`Response contains sensitive file content: ${payload}`],
affected_urls: [testUrl],
remediation: 'Implement proper file access controls and input validation',
cwe_id: 'CWE-22',
references: ['https://owasp.org/Top10/A01_2021-Broken_Access_Control/']
});
break;
}
} catch {
// Continue testing
}
}
// Test 2: Forced Browsing
const adminPaths = [
'/admin',
'/administrator',
'/admin.php',
'/admin/index.php',
'/wp-admin',
'/management',
'/control-panel'
];
for (const path of adminPaths) {
try {
const testUrl = `${config.target_url.replace(/\/$/, '')}${path}`;
const response = await axios.get(testUrl, {
timeout: 5000,
validateStatus: () => true
});
if (response.status === 200 &&
(response.data.includes('admin') ||
response.data.includes('dashboard') ||
response.data.includes('control panel'))) {
results.push({
owasp_category: 'A01:2021-Broken Access Control',
owasp_id: 'A01',
test_name: 'Forced Browsing to Admin Interface',
vulnerability_found: true,
severity: 'medium',
description: 'Administrative interface accessible without authentication',
evidence: [`Admin interface found at: ${path}`],
affected_urls: [testUrl],
remediation: 'Implement proper authentication and authorization controls',
cwe_id: 'CWE-425',
references: ['https://owasp.org/Top10/A01_2021-Broken_Access_Control/']
});
}
} catch {
// Continue testing
}
}
return results;
}
private async testCryptographicFailures(config: OWASPTestConfiguration): Promise<OWASPTestResult[]> {
const results: OWASPTestResult[] = [];
// Test 1: Weak SSL/TLS Configuration
try {
const httpsUrl = config.target_url.replace('http://', 'https://');
// Test for HTTP availability when HTTPS exists
if (config.target_url.startsWith('https://')) {
const httpUrl = config.target_url.replace('https://', 'http://');
try {
const httpResponse = await axios.get(httpUrl, { timeout: 5000 });
if (httpResponse.status === 200) {
results.push({
owasp_category: 'A02:2021-Cryptographic Failures',
owasp_id: 'A02',
test_name: 'Insecure HTTP Access',
vulnerability_found: true,
severity: 'medium',
description: 'Application accessible over unencrypted HTTP',
evidence: ['HTTP version of site is accessible'],
affected_urls: [httpUrl],
remediation: 'Redirect all HTTP traffic to HTTPS and implement HSTS',
cwe_id: 'CWE-319',
references: ['https://owasp.org/Top10/A02_2021-Cryptographic_Failures/']
});
}
} catch {
// HTTP not accessible - good
}
}
// Test SSL/TLS headers
const response = await axios.get(httpsUrl, { timeout: 5000 });
const headers = response.headers;
if (!headers['strict-transport-security']) {
results.push({
owasp_category: 'A02:2021-Cryptographic Failures',
owasp_id: 'A02',
test_name: 'Missing HSTS Header',
vulnerability_found: true,
severity: 'low',
description: 'HTTP Strict Transport Security (HSTS) header not implemented',
evidence: ['Strict-Transport-Security header missing'],
affected_urls: [httpsUrl],
remediation: 'Implement HSTS header with appropriate max-age value',
cwe_id: 'CWE-319',
references: ['https://owasp.org/Top10/A02_2021-Cryptographic_Failures/']
});
}
} catch {
// HTTPS not available
}
return results;
}
private async testInjectionVulnerabilities(config: OWASPTestConfiguration): Promise<OWASPTestResult[]> {
const results: OWASPTestResult[] = [];
// Test 1: SQL Injection
const sqlPayloads = [
"' OR '1'='1",
"'; DROP TABLE users; --",
"' UNION SELECT null, version() --",
"admin'--",
"' AND (SELECT COUNT(*) FROM information_schema.tables) > 0 --"
];
for (const payload of sqlPayloads) {
try {
const testUrl = `${config.target_url}?id=${encodeURIComponent(payload)}`;
const response = await axios.get(testUrl, {
timeout: 5000,
validateStatus: () => true
});
// Check for SQL error messages
const sqlErrors = [
'sql syntax error',
'mysql_fetch',
'ora-01756',
'microsoft sql',
'sqlite_step',
'postgresql'
];
const responseText = response.data.toLowerCase();
if (sqlErrors.some(error => responseText.includes(error))) {
results.push({
owasp_category: 'A03:2021-Injection',
owasp_id: 'A03',
test_name: 'SQL Injection',
vulnerability_found: true,
severity: 'high',
description: 'Application vulnerable to SQL injection attacks',
evidence: [`SQL error triggered by payload: ${payload}`],
affected_urls: [testUrl],
remediation: 'Use parameterized queries and input validation',
cwe_id: 'CWE-89',
references: ['https://owasp.org/Top10/A03_2021-Injection/']
});
break;
}
} catch {
// Continue testing
}
}
// Test 2: XSS (Cross-Site Scripting)
const xssPayloads = [
'<script>alert("XSS")</script>',
'<img src="x" onerror="alert(1)">',
'<svg onload="alert(\'XSS\')">',
'javascript:alert("XSS")',
'"><script>alert(document.cookie)</script>'
];
for (const payload of xssPayloads) {
try {
const testUrl = `${config.target_url}?search=${encodeURIComponent(payload)}`;
const response = await axios.get(testUrl, { timeout: 5000 });
if (response.data.includes(payload) ||
response.data.includes(payload.replace(/[<>]/g, ''))) {
results.push({
owasp_category: 'A03:2021-Injection',
owasp_id: 'A03',
test_name: 'Cross-Site Scripting (XSS)',
vulnerability_found: true,
severity: 'high',
description: 'Application vulnerable to XSS attacks',
evidence: [`XSS payload reflected: ${payload}`],
affected_urls: [testUrl],
remediation: 'Implement proper output encoding and CSP headers',
cwe_id: 'CWE-79',
references: ['https://owasp.org/Top10/A03_2021-Injection/']
});
break;
}
} catch {
// Continue testing
}
}
return results;
}
private async testInsecureDesign(config: OWASPTestConfiguration): Promise<OWASPTestResult[]> {
const results: OWASPTestResult[] = [];
// Test for business logic flaws - this is more conceptual
// We'll test for common design issues
// Test 1: Missing Rate Limiting
try {
const startTime = Date.now();
const requests = [];
// Send 10 rapid requests
for (let i = 0; i < 10; i++) {
requests.push(axios.get(config.target_url, { timeout: 5000 }));
}
await Promise.all(requests);
const endTime = Date.now();
const duration = endTime - startTime;
// If all requests succeeded quickly, rate limiting might be missing
if (duration < 2000) { // All requests completed in under 2 seconds
results.push({
owasp_category: 'A04:2021-Insecure Design',
owasp_id: 'A04',
test_name: 'Missing Rate Limiting',
vulnerability_found: true,
severity: 'medium',
description: 'Application appears to lack rate limiting controls',
evidence: ['10 rapid requests all succeeded without delays'],
affected_urls: [config.target_url],
remediation: 'Implement rate limiting and request throttling',
cwe_id: 'CWE-770',
references: ['https://owasp.org/Top10/A04_2021-Insecure_Design/']
});
}
} catch {
// Rate limiting might be working
}
return results;
}
private async testSecurityMisconfiguration(config: OWASPTestConfiguration): Promise<OWASPTestResult[]> {
const results: OWASPTestResult[] = [];
try {
const response = await axios.get(config.target_url, { timeout: 5000 });
const headers = response.headers;
// Test for missing security headers
const securityHeaders = [
{ name: 'x-frame-options', severity: 'medium' as const },
{ name: 'x-content-type-options', severity: 'low' as const },
{ name: 'x-xss-protection', severity: 'low' as const },
{ name: 'content-security-policy', severity: 'high' as const },
{ name: 'referrer-policy', severity: 'low' as const }
];
for (const header of securityHeaders) {
if (!headers[header.name]) {
results.push({
owasp_category: 'A05:2021-Security Misconfiguration',
owasp_id: 'A05',
test_name: `Missing ${header.name} Header`,
vulnerability_found: true,
severity: header.severity,
description: `Security header ${header.name} is not implemented`,
evidence: [`${header.name} header missing from response`],
affected_urls: [config.target_url],
remediation: `Implement ${header.name} header with appropriate values`,
references: ['https://owasp.org/Top10/A05_2021-Security_Misconfiguration/']
});
}
}
// Test for information disclosure
if (headers.server) {
results.push({
owasp_category: 'A05:2021-Security Misconfiguration',
owasp_id: 'A05',
test_name: 'Server Information Disclosure',
vulnerability_found: true,
severity: 'low',
description: 'Server banner reveals software information',
evidence: [`Server header: ${headers.server}`],
affected_urls: [config.target_url],
remediation: 'Hide or modify server banner information',
cwe_id: 'CWE-200',
references: ['https://owasp.org/Top10/A05_2021-Security_Misconfiguration/']
});
}
if (headers['x-powered-by']) {
results.push({
owasp_category: 'A05:2021-Security Misconfiguration',
owasp_id: 'A05',
test_name: 'Technology Stack Disclosure',
vulnerability_found: true,
severity: 'low',
description: 'X-Powered-By header reveals technology information',
evidence: [`X-Powered-By header: ${headers['x-powered-by']}`],
affected_urls: [config.target_url],
remediation: 'Remove X-Powered-By header',
cwe_id: 'CWE-200',
references: ['https://owasp.org/Top10/A05_2021-Security_Misconfiguration/']
});
}
} catch {
// Cannot test headers
}
return results;
}
private async testVulnerableComponents(config: OWASPTestConfiguration): Promise<OWASPTestResult[]> {
const results: OWASPTestResult[] = [];
// This would typically integrate with CVE databases
// For now, we'll test for common indicators
try {
const response = await axios.get(config.target_url, { timeout: 5000 });
const content = response.data.toLowerCase();
// Check for jQuery versions
const jqueryMatch = content.match(/jquery[\/\s-]v?(\d+\.\d+\.\d+)/);
if (jqueryMatch) {
const version = jqueryMatch[1];
const versionNum = parseFloat(version);
if (versionNum < 3.5) {
results.push({
owasp_category: 'A06:2021-Vulnerable and Outdated Components',
owasp_id: 'A06',
test_name: 'Outdated jQuery Version',
vulnerability_found: true,
severity: 'medium',
description: `Outdated jQuery version ${version} detected`,
evidence: [`jQuery version ${version} found in response`],
affected_urls: [config.target_url],
remediation: 'Update jQuery to the latest stable version',
references: ['https://owasp.org/Top10/A06_2021-Vulnerable_and_Outdated_Components/']
});
}
}
// Check for WordPress indicators
if (content.includes('wp-content') || content.includes('wp-includes')) {
// Try to detect WordPress version
const wpVersionMatch = content.match(/wordpress[\/\s](\d+\.\d+)/);
if (wpVersionMatch) {
const version = parseFloat(wpVersionMatch[1]);
if (version < 6.0) {
results.push({
owasp_category: 'A06:2021-Vulnerable and Outdated Components',
owasp_id: 'A06',
test_name: 'Outdated WordPress Version',
vulnerability_found: true,
severity: 'high',
description: `Outdated WordPress version ${version} detected`,
evidence: [`WordPress version ${version} identified`],
affected_urls: [config.target_url],
remediation: 'Update WordPress to the latest version',
references: ['https://owasp.org/Top10/A06_2021-Vulnerable_and_Outdated_Components/']
});
}
}
}
} catch {
// Cannot analyze content
}
return results;
}
private async testAuthenticationFailures(config: OWASPTestConfiguration): Promise<OWASPTestResult[]> {
const results: OWASPTestResult[] = [];
// Test for common authentication issues
const loginPaths = ['/login', '/signin', '/auth', '/admin/login'];
for (const path of loginPaths) {
try {
const loginUrl = `${config.target_url.replace(/\/$/, '')}${path}`;
const response = await axios.get(loginUrl, {
timeout: 5000,
validateStatus: () => true
});
if (response.status === 200 &&
(response.data.includes('password') || response.data.includes('login'))) {
// Test for weak default credentials
const defaultCreds = [
{ username: 'admin', password: 'admin' },
{ username: 'admin', password: 'password' },
{ username: 'admin', password: '123456' },
{ username: 'root', password: 'root' },
{ username: 'test', password: 'test' }
];
for (const cred of defaultCreds) {
try {
const loginResponse = await axios.post(loginUrl, {
username: cred.username,
password: cred.password
}, {
timeout: 5000,
validateStatus: () => true
});
// Check for successful login indicators
if (loginResponse.status === 200 &&
(loginResponse.data.includes('dashboard') ||
loginResponse.data.includes('welcome') ||
loginResponse.headers['set-cookie'])) {
results.push({
owasp_category: 'A07:2021-Identification and Authentication Failures',
owasp_id: 'A07',
test_name: 'Weak Default Credentials',
vulnerability_found: true,
severity: 'critical',
description: `Default credentials accepted: ${cred.username}/${cred.password}`,
evidence: [`Login successful with ${cred.username}/${cred.password}`],
affected_urls: [loginUrl],
remediation: 'Change default credentials and implement strong password policy',
cwe_id: 'CWE-521',
references: ['https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/']
});
break;
}
} catch {
// Continue testing
}
}
}
} catch {
// Login path not found
}
}
return results;
}
private async testIntegrityFailures(config: OWASPTestConfiguration): Promise<OWASPTestResult[]> {
const results: OWASPTestResult[] = [];
try {
const response = await axios.get(config.target_url, { timeout: 5000 });
const content = response.data;
// Check for unsigned JavaScript includes
const scriptTags = content.match(/<script[^>]*src=["']([^"']+)["'][^>]*>/gi);
if (scriptTags) {
for (const scriptTag of scriptTags) {
if (!scriptTag.includes('integrity=') &&
(scriptTag.includes('cdn') || scriptTag.includes('external'))) {
results.push({
owasp_category: 'A08:2021-Software and Data Integrity Failures',
owasp_id: 'A08',
test_name: 'Missing Subresource Integrity',
vulnerability_found: true,
severity: 'medium',
description: 'External scripts loaded without integrity checks',
evidence: [`Script tag without integrity: ${scriptTag}`],
affected_urls: [config.target_url],
remediation: 'Implement Subresource Integrity (SRI) for external scripts',
cwe_id: 'CWE-353',
references: ['https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures/']
});
}
}
}
} catch {
// Cannot analyze content
}
return results;
}
private async testLoggingMonitoringFailures(config: OWASPTestConfiguration): Promise<OWASPTestResult[]> {
const results: OWASPTestResult[] = [];
// This is more of a policy/configuration test
// We can only test for basic indicators
try {
// Test for error handling
const errorUrl = `${config.target_url}/nonexistent-page-12345`;
const response = await axios.get(errorUrl, {
timeout: 5000,
validateStatus: () => true
});
if (response.status === 404) {
// Check if error page reveals sensitive information
if (response.data.includes('stack trace') ||
response.data.includes('file path') ||
response.data.includes('database') ||
response.data.includes('exception')) {
results.push({
owasp_category: 'A09:2021-Security Logging and Monitoring Failures',
owasp_id: 'A09',
test_name: 'Verbose Error Messages',
vulnerability_found: true,
severity: 'low',
description: 'Error pages reveal sensitive system information',
evidence: ['Error page contains detailed system information'],
affected_urls: [errorUrl],
remediation: 'Implement custom error pages that don\'t reveal system details',
cwe_id: 'CWE-209',
references: ['https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/']
});
}
}
} catch {
// Cannot test error handling
}
return results;
}
private async testSSRF(config: OWASPTestConfiguration): Promise<OWASPTestResult[]> {
const results: OWASPTestResult[] = [];
// Test for SSRF vulnerabilities
const ssrfPayloads = [
'http://127.0.0.1:80',
'http://localhost:22',
'http://169.254.169.254/latest/meta-data/',
'file:///etc/passwd',
'http://internal.domain.com'
];
for (const payload of ssrfPayloads) {
try {
const testUrl = `${config.target_url}?url=${encodeURIComponent(payload)}`;
const response = await axios.get(testUrl, {
timeout: 10000,
validateStatus: () => true
});
// Check for SSRF indicators
if (response.data.includes('root:') ||
response.data.includes('ami-id') ||
response.data.includes('instance-id') ||
response.data.includes('127.0.0.1') ||
response.status === 200 && response.data.length > 100) {
results.push({
owasp_category: 'A10:2021-Server-Side Request Forgery (SSRF)',
owasp_id: 'A10',
test_name: 'Server-Side Request Forgery',
vulnerability_found: true,
severity: 'high',
description: 'Application vulnerable to SSRF attacks',
evidence: [`SSRF payload successful: ${payload}`],
affected_urls: [testUrl],
remediation: 'Implement URL validation and restrict internal network access',
cwe_id: 'CWE-918',
references: ['https://owasp.org/Top10/A10_2021-Server-Side_Request_Forgery_%28SSRF%29/']
});
break;
}
} catch {
// Continue testing
}
}
return results;
}
private calculateComplianceScore(results: OWASPTestResult[]): number {
const totalTests = results.length;
const passedTests = results.filter(r => !r.vulnerability_found).length;
return totalTests > 0 ? Math.round((passedTests / totalTests) * 100) : 0;
}
private generateExecutiveSummary(results: OWASPTestResult[]): any {
const vulnerabilities = results.filter(r => r.vulnerability_found);
const criticalCount = vulnerabilities.filter(r => r.severity === 'critical').length;
const highCount = vulnerabilities.filter(r => r.severity === 'high').length;
const mediumCount = vulnerabilities.filter(r => r.severity === 'medium').length;
let riskLevel = 'Low';
if (criticalCount > 0) riskLevel = 'Critical';
else if (highCount > 0) riskLevel = 'High';
else if (mediumCount > 0) riskLevel = 'Medium';
return {
overall_risk_level: riskLevel,
total_vulnerabilities: vulnerabilities.length,
severity_breakdown: {
critical: criticalCount,
high: highCount,
medium: mediumCount,
low: vulnerabilities.filter(r => r.severity === 'low').length
},
most_critical_findings: vulnerabilities
.filter(r => r.severity === 'critical' || r.severity === 'high')
.slice(0, 5)
.map(r => r.test_name),
compliance_status: this.calculateComplianceScore(results) >= 80 ? 'Good' : 'Needs Improvement'
};
}
private generateOWASPRecommendations(results: OWASPTestResult[]): string[] {
const recommendations = new Set<string>();
const vulnerabilities = results.filter(r => r.vulnerability_found);
if (vulnerabilities.some(v => v.test_name.includes('SQL Injection'))) {
recommendations.add('Implement parameterized queries and input validation');
}
if (vulnerabilities.some(v => v.test_name.includes('XSS'))) {
recommendations.add('Implement proper output encoding and Content Security Policy');
}
if (vulnerabilities.some(v => v.test_name.includes('Missing') && v.test_name.includes('Header'))) {
recommendations.add('Implement comprehensive security headers');
}
if (vulnerabilities.some(v => v.test_name.includes('Default Credentials'))) {
recommendations.add('Change all default credentials and implement strong password policies');
}
if (vulnerabilities.some(v => v.test_name.includes('Directory Traversal'))) {
recommendations.add('Implement proper file access controls and input validation');
}
if (vulnerabilities.some(v => v.test_name.includes('SSRF'))) {
recommendations.add('Implement URL validation and restrict internal network access');
}
recommendations.add('Regular security testing and code review');
recommendations.add('Implement Web Application Firewall (WAF)');
recommendations.add('Security awareness training for development team');
return Array.from(recommendations);
}
}