Analyze HTTP headers for security issues.
| 6 | |
| 7 | |
| 8 | class HeaderAnalyzer(OSINTModule): |
| 9 | """Analyze HTTP headers for security issues.""" |
| 10 | |
| 11 | name = "headers" |
| 12 | description = "Analyze HTTP response headers for security misconfigurations" |
| 13 | |
| 14 | SECURITY_HEADERS = { |
| 15 | "strict-transport-security": {"name": "HSTS", "severity": Severity.MEDIUM}, |
| 16 | "content-security-policy": {"name": "CSP", "severity": Severity.MEDIUM}, |
| 17 | "x-frame-options": {"name": "X-Frame-Options", "severity": Severity.LOW}, |
| 18 | "x-content-type-options": {"name": "X-Content-Type-Options", "severity": Severity.LOW}, |
| 19 | "x-xss-protection": {"name": "X-XSS-Protection", "severity": Severity.LOW}, |
| 20 | "referrer-policy": {"name": "Referrer-Policy", "severity": Severity.LOW}, |
| 21 | "permissions-policy": {"name": "Permissions-Policy", "severity": Severity.LOW}, |
| 22 | } |
| 23 | |
| 24 | INFO_DISCLOSURE_HEADERS = [ |
| 25 | "server", "x-powered-by", "x-aspnet-version", "x-aspnetmvc-version", |
| 26 | "x-generator", "x-drupal-cache", "x-runtime", "x-version", |
| 27 | ] |
| 28 | |
| 29 | async def run(self, target: Target) -> ScanResult: |
| 30 | """Analyze HTTP headers for security issues.""" |
| 31 | result = self.create_result(target) |
| 32 | url = self._build_url(target) |
| 33 | self.logger.info(f"Analyzing headers for {url}") |
| 34 | |
| 35 | try: |
| 36 | async with HTTPClient() as client: |
| 37 | response = await client.get(url) |
| 38 | headers = dict(response.headers) |
| 39 | headers_lower = {k.lower(): v for k, v in headers.items()} |
| 40 | |
| 41 | result.raw_data["url"] = str(response.url) |
| 42 | result.raw_data["status_code"] = response.status_code |
| 43 | result.raw_data["headers"] = headers |
| 44 | |
| 45 | missing_headers = [] |
| 46 | present_headers = [] |
| 47 | |
| 48 | for header, info in self.SECURITY_HEADERS.items(): |
| 49 | if header in headers_lower: |
| 50 | present_headers.append({"header": info["name"], "value": headers_lower[header]}) |
| 51 | else: |
| 52 | missing_headers.append({"header": info["name"], "severity": info["severity"]}) |
| 53 | |
| 54 | if missing_headers: |
| 55 | medium_missing = [h for h in missing_headers if h["severity"] == Severity.MEDIUM] |
| 56 | if medium_missing: |
| 57 | result.add_finding( |
| 58 | title="Missing Important Security Headers", |
| 59 | description=f"Missing {len(medium_missing)} important security header(s)", |
| 60 | severity=Severity.MEDIUM, |
| 61 | data={"missing": [h["header"] for h in medium_missing]}, |
| 62 | ) |
| 63 | |
| 64 | if present_headers: |
| 65 | result.add_finding( |
no outgoing calls