File size: 9,344 Bytes
5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 60b5448 5c55fe0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | """
Security Header Analyzer
=========================
Detects missing or misconfigured HTTP security headers and cookies.
OWASP: A02, A05 (2021)
"""
import httpx
from base import Finding, Severity, VulnerabilityPlugin
HEADER_CHECKS = {
"Content-Security-Policy": {
"severity": Severity.MEDIUM,
"description": "No Content-Security-Policy header found. This allows XSS attacks to load arbitrary scripts from any origin.",
"owasp": "A05:2021 - Security Misconfiguration",
"cwe": "CWE-693",
"remediation": "Add a restrictive CSP:\nContent-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'",
"cvss": 6.1,
"tags": ["headers", "csp", "xss"],
},
"Strict-Transport-Security": {
"severity": Severity.HIGH,
"description": "Missing HSTS header. Browsers may connect over plain HTTP, enabling man-in-the-middle attacks and cookie theft.",
"owasp": "A02:2021 - Cryptographic Failures",
"cwe": "CWE-319",
"remediation": "Add: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload",
"cvss": 7.4,
"tags": ["headers", "hsts", "tls"],
},
"X-Frame-Options": {
"severity": Severity.MEDIUM,
"description": "Missing X-Frame-Options allows the page to be embedded in an iframe β enabling clickjacking attacks.",
"owasp": "A05:2021 - Security Misconfiguration",
"cwe": "CWE-1021",
"remediation": "Add: X-Frame-Options: DENY\nOr use CSP: Content-Security-Policy: frame-ancestors 'none'",
"cvss": 4.3,
"tags": ["headers", "clickjacking"],
},
"X-Content-Type-Options": {
"severity": Severity.LOW,
"description": "Missing X-Content-Type-Options allows MIME-type sniffing, which can enable content injection attacks.",
"owasp": "A05:2021 - Security Misconfiguration",
"cwe": "CWE-16",
"remediation": "Add: X-Content-Type-Options: nosniff",
"cvss": 3.7,
"tags": ["headers", "mime-sniffing"],
},
"Referrer-Policy": {
"severity": Severity.LOW,
"description": "No Referrer-Policy set. Sensitive URL parameters may leak to third parties via the Referer header.",
"owasp": "A05:2021 - Security Misconfiguration",
"cwe": "CWE-116",
"remediation": "Add: Referrer-Policy: strict-origin-when-cross-origin",
"cvss": 3.1,
"tags": ["headers", "privacy"],
},
"Permissions-Policy": {
"severity": Severity.LOW,
"description": "No Permissions-Policy header. Browser features like camera, microphone, and geolocation are unrestricted.",
"owasp": "A05:2021 - Security Misconfiguration",
"cwe": "CWE-16",
"remediation": "Add: Permissions-Policy: geolocation=(), microphone=(), camera=()",
"cvss": 2.6,
"tags": ["headers", "permissions"],
},
"Cross-Origin-Opener-Policy": {
"severity": Severity.LOW,
"description": "Missing COOP header. The page can be opened by cross-origin pages enabling XS-Leaks attacks.",
"owasp": "A05:2021 - Security Misconfiguration",
"cwe": "CWE-346",
"remediation": "Add: Cross-Origin-Opener-Policy: same-origin",
"cvss": 3.1,
"tags": ["headers", "cors", "xs-leaks"],
},
"Cross-Origin-Resource-Policy": {
"severity": Severity.LOW,
"description": "Missing CORP header allows cross-origin sites to embed this resource, enabling side-channel attacks.",
"owasp": "A05:2021 - Security Misconfiguration",
"cwe": "CWE-346",
"remediation": "Add: Cross-Origin-Resource-Policy: same-origin",
"cvss": 3.1,
"tags": ["headers", "cors"],
},
}
WEAK_CSP_PATTERNS = [
("unsafe-inline", 5.4),
("unsafe-eval", 5.4),
("data:", 4.3),
("*", 6.1),
("http:", 4.3),
]
INSECURE_COOKIE_FLAGS = {
"HttpOnly": ("Cookie readable by JavaScript β XSS can steal session tokens", Severity.MEDIUM, 4.3),
"Secure": ("Cookie sent over plain HTTP β susceptible to interception", Severity.MEDIUM, 5.4),
"SameSite": ("Missing SameSite attribute β vulnerable to CSRF attacks", Severity.LOW, 4.3),
}
SERVER_LEAKS = {
"server": "Server header reveals web server software and version β aids fingerprinting",
"x-powered-by": "X-Powered-By header reveals backend technology stack",
"x-aspnet-version": "X-AspNet-Version header reveals .NET version in use",
"x-aspnetmvc-version": "X-AspNetMvc-Version reveals ASP.NET MVC version",
}
class SecurityHeaderPlugin(VulnerabilityPlugin):
name = "security_headers"
description = "Checks for missing/misconfigured security headers, weak CSP, insecure cookies, and server info leaks"
async def run(self, target: str) -> list[Finding]:
findings: list[Finding] = []
try:
r = await self.client.get(target.rstrip("/"), timeout=12, follow_redirects=True)
except Exception:
return []
headers_lower = {k.lower(): v for k, v in r.headers.items()}
# ββ Required security headers ββββββββββββββββββββββββββββββββββββββββββ
for header, cfg in HEADER_CHECKS.items():
if header.lower() not in headers_lower:
findings.append(Finding(
plugin=self.name,
title=f"Missing {header}",
severity=cfg["severity"],
description=cfg["description"],
evidence={"header": header, "present": False},
owasp=cfg["owasp"],
cwe=cfg["cwe"],
remediation=cfg["remediation"],
endpoint=target,
cvss_estimate=cfg["cvss"],
tags=cfg["tags"],
))
# ββ Weak CSP directives ββββββββββββββββββββββββββββββββββββββββββββββββ
csp = headers_lower.get("content-security-policy", "")
if csp:
for pattern, cvss in WEAK_CSP_PATTERNS:
if pattern in csp:
findings.append(Finding(
plugin=self.name,
title=f"Weak CSP: '{pattern}' directive present",
severity=Severity.MEDIUM,
description=f"The Content-Security-Policy contains '{pattern}' which significantly weakens XSS protection.",
evidence={"csp_value": csp, "weak_directive": pattern},
owasp="A05:2021 - Security Misconfiguration",
cwe="CWE-1021",
remediation=f"Remove '{pattern}' from your CSP. Use nonces or hashes for inline scripts.",
endpoint=target,
cvss_estimate=cvss,
tags=["headers", "csp", "xss"],
))
# ββ Insecure cookies βββββββββββββββββββββββββββββββββββββββββββββββββββ
for cookie_header in r.headers.get_list("set-cookie"):
cookie_name = cookie_header.split("=")[0].strip()
for flag, (desc, sev, cvss) in INSECURE_COOKIE_FLAGS.items():
if flag.lower() not in cookie_header.lower():
findings.append(Finding(
plugin=self.name,
title=f"Insecure cookie: missing {flag}",
severity=sev,
description=f"Cookie '{cookie_name}': {desc}",
evidence={"cookie_name": cookie_name, "raw": cookie_header, "missing_flag": flag},
owasp="A05:2021 - Security Misconfiguration",
cwe="CWE-614",
remediation=f"Set the {flag} flag on all session and auth cookies.",
endpoint=target,
cvss_estimate=cvss,
tags=["cookies", "session"],
))
# ββ Server info leakage ββββββββββββββββββββββββββββββββββββββββββββββββ
for leak_header, desc in SERVER_LEAKS.items():
val = headers_lower.get(leak_header)
if val:
findings.append(Finding(
plugin=self.name,
title=f"Server information disclosure: {leak_header}",
severity=Severity.LOW,
description=desc,
evidence={"header": leak_header, "value": val},
owasp="A05:2021 - Security Misconfiguration",
cwe="CWE-200",
remediation=f"Remove or suppress the '{leak_header}' response header in your web server config.",
endpoint=target,
cvss_estimate=3.1,
tags=["headers", "information-disclosure", "fingerprinting"],
))
return findings |