148 lines
7.1 KiB
Python
148 lines
7.1 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
from .models import Finding
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class TestDefinition:
|
|
id: str
|
|
name: str
|
|
module: str
|
|
category: str
|
|
wstg: tuple[str, ...] = ()
|
|
asvs: tuple[str, ...] = ()
|
|
cwe: tuple[str, ...] = ()
|
|
api_security: tuple[str, ...] = ()
|
|
|
|
def references(self) -> dict[str, list[dict[str, str]]]:
|
|
return {
|
|
"OWASP_WSTG": [reference("OWASP_WSTG", value) for value in self.wstg],
|
|
"OWASP_ASVS": [reference("OWASP_ASVS", value) for value in self.asvs],
|
|
"CWE": [reference("CWE", value) for value in self.cwe],
|
|
"OWASP_API_SECURITY": [reference("OWASP_API_SECURITY", value) for value in self.api_security],
|
|
}
|
|
|
|
|
|
WSTG_URLS = {
|
|
"WSTG-INFO-06": "https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/01-Information_Gathering/06-Identify_Application_Entry_Points",
|
|
"WSTG-INFO-07": "https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/01-Information_Gathering/07-Map_Execution_Paths_Through_Application",
|
|
"WSTG-INFO-05": "https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/01-Information_Gathering/05-Review_Webpage_Content_for_Information_Leakage",
|
|
"WSTG-CONF-04": "https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/02-Configuration_and_Deployment_Management_Testing/04-Review_Old_Backup_and_Unreferenced_Files_for_Sensitive_Information",
|
|
"WSTG-CONF-05": "https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/02-Configuration_and_Deployment_Management_Testing/05-Enumerate_Infrastructure_and_Application_Admin_Interfaces",
|
|
"WSTG-CONF-07": "https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/02-Configuration_and_Deployment_Management_Testing/07-Test_HTTP_Strict_Transport_Security",
|
|
"WSTG-ATHZ-02": "https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/05-Authorization_Testing/02-Testing_for_Bypassing_Authorization_Schema",
|
|
"WSTG-CLNT-04": "https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/11-Client-side_Testing/04-Testing_for_Client-side_URL_Redirect",
|
|
}
|
|
|
|
API_SECURITY_URLS = {
|
|
"API1:2023": "https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/",
|
|
"API3:2023": "https://owasp.org/API-Security/editions/2023/en/0xa3-broken-object-property-level-authorization/",
|
|
"API8:2023": "https://owasp.org/API-Security/editions/2023/en/0xa8-security-misconfiguration/",
|
|
"API9:2023": "https://owasp.org/API-Security/editions/2023/en/0xa9-improper-inventory-management/",
|
|
"API10:2023": "https://owasp.org/API-Security/editions/2023/en/0xaa-unsafe-consumption-of-apis/",
|
|
}
|
|
|
|
|
|
def reference(family: str, identifier: str) -> dict[str, str]:
|
|
if family == "OWASP_WSTG":
|
|
return {"id": identifier, "version": "4.2", "url": WSTG_URLS[identifier]}
|
|
if family == "OWASP_ASVS":
|
|
return {
|
|
"id": identifier,
|
|
"version": "5.0.0",
|
|
"url": "https://owasp.org/www-project-application-security-verification-standard/",
|
|
}
|
|
if family == "CWE":
|
|
number = identifier.removeprefix("CWE-")
|
|
return {"id": identifier, "url": f"https://cwe.mitre.org/data/definitions/{number}.html"}
|
|
return {
|
|
"id": identifier,
|
|
"version": "2023",
|
|
"url": API_SECURITY_URLS[identifier],
|
|
}
|
|
|
|
|
|
TEST_REGISTRY: tuple[TestDefinition, ...] = (
|
|
TestDefinition(
|
|
"RFV2-COMP-001", "Correlate disclosed component versions with known vulnerabilities",
|
|
"cve_intelligence", "known-vulnerable-component",
|
|
("WSTG-INFO-05",), ("v5.0.0-14.2.1",), ("CWE-1104",), ("API9:2023",),
|
|
),
|
|
TestDefinition(
|
|
"RFV2-MAP-001", "Build application entry-point inventory", "application_mapping", "attack-surface-inventory",
|
|
("WSTG-INFO-06", "WSTG-INFO-07"), ("v5.0.0-8.1.1", "v5.0.0-13.4.5"), ("CWE-1059",), ("API9:2023",),
|
|
),
|
|
TestDefinition(
|
|
"RFV2-CONF-001", "Review browser security headers", "http_headers", "security-headers",
|
|
("WSTG-CONF-07",),
|
|
("v5.0.0-3.4.1", "v5.0.0-3.4.3", "v5.0.0-3.4.4", "v5.0.0-3.4.5"),
|
|
("CWE-693",), ("API8:2023",),
|
|
),
|
|
TestDefinition(
|
|
"RFV2-INFO-002", "Identify credential-entry surfaces", "surface_analysis", "credential-surface",
|
|
("WSTG-INFO-06",), ("v5.0.0-6.1.3",), ("CWE-200",), ("API9:2023",),
|
|
),
|
|
TestDefinition(
|
|
"RFV2-CLNT-001", "Identify client-side redirects", "surface_analysis", "client-redirect",
|
|
("WSTG-CLNT-04",), ("v5.0.0-1.2.2",), ("CWE-601",), ("API10:2023",),
|
|
),
|
|
TestDefinition(
|
|
"RFV2-CONF-002", "Discover exposed application paths", "path_discovery", "discovered-path",
|
|
("WSTG-CONF-04", "WSTG-CONF-05"), ("v5.0.0-13.4.5",), ("CWE-200",), ("API9:2023",),
|
|
),
|
|
TestDefinition(
|
|
"RFV2-DATA-001", "Detect sensitive data in client-accessible responses", "sensitive_exposure", "sensitive-data-exposure",
|
|
("WSTG-INFO-05",), ("v5.0.0-13.4.7", "v5.0.0-14.2.3"), ("CWE-200", "CWE-798"), ("API3:2023", "API8:2023"),
|
|
),
|
|
TestDefinition(
|
|
"RFV2-BROW-001", "Corroborate headers in a browser runtime", "browser_runtime", "browser-security-headers",
|
|
("WSTG-CONF-07",), ("v5.0.0-3.4.1", "v5.0.0-3.4.3"), ("CWE-693",), ("API8:2023",),
|
|
),
|
|
TestDefinition(
|
|
"RFV2-BROW-002", "Inventory browser-observed endpoints", "browser_runtime", "browser-endpoints",
|
|
("WSTG-INFO-06", "WSTG-INFO-07"), ("v5.0.0-8.1.1",), ("CWE-1059",), ("API9:2023",),
|
|
),
|
|
TestDefinition(
|
|
"RFV2-ATHZ-001", "Identify unauthenticated service surfaces", "authorization_surface", "unauthenticated-service",
|
|
("WSTG-ATHZ-02",), ("v5.0.0-8.2.1",), ("CWE-862",), ("API1:2023",),
|
|
),
|
|
TestDefinition(
|
|
"RFV2-CORR-001", "Correlate exposed surfaces and weak hardening", "correlation", "exposed-surface",
|
|
("WSTG-INFO-06",), ("v5.0.0-13.4.5",), ("CWE-693",), ("API8:2023",),
|
|
),
|
|
)
|
|
|
|
_BY_KEY = {(item.module, item.category): item for item in TEST_REGISTRY}
|
|
|
|
|
|
def enrich_finding(finding: "Finding") -> "Finding":
|
|
definition = _BY_KEY.get((finding.module, finding.category))
|
|
if definition:
|
|
finding.test_id = definition.id
|
|
dynamic = finding.standards
|
|
finding.standards = definition.references()
|
|
for family, references in dynamic.items():
|
|
existing = {item.get("id") for item in finding.standards.setdefault(family, [])}
|
|
finding.standards[family].extend(item for item in references if item.get("id") not in existing)
|
|
return finding
|
|
|
|
|
|
def registry_document() -> dict:
|
|
return {
|
|
"schema_version": "1.0",
|
|
"tests": [
|
|
{
|
|
"id": item.id,
|
|
"name": item.name,
|
|
"module": item.module,
|
|
"category": item.category,
|
|
"references": item.references(),
|
|
}
|
|
for item in TEST_REGISTRY
|
|
],
|
|
}
|