#!/usr/bin/env python3 """Agent for analyzing intercepted mobile app traffic via mitmproxy for security testing.""" import json import argparse import re from datetime import datetime from urllib.parse import urlparse def load_har_file(har_path): """Load and parse an HTTP Archive (HAR) file from proxy capture.""" with open(har_path) as f: data = json.load(f) entries = data.get("log", {}).get("entries", []) print(f"[*] Loaded {len(entries)} requests from {har_path}") return entries def find_insecure_requests(entries): """Identify HTTP (non-HTTPS) requests from mobile app.""" findings = [] for e in entries: url = e.get("request", {}).get("url", "") if url.startswith("http://"): findings.append({"url": url, "method": e["request"].get("method"), "issue": "Cleartext HTTP request", "severity": "HIGH"}) print(f"\n[*] Insecure HTTP requests: {len(findings)}") for f in findings[:10]: print(f" [!] {f['method']} {f['url'][:80]}") return findings def detect_sensitive_data_leakage(entries): """Scan request/response bodies for sensitive data patterns.""" patterns = { "email": r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", "phone": r"\b\d{3}[-.]?\d{3}[-.]?\d{4}\b", "ssn": r"\b\d{3}-\d{2}-\d{4}\b", "credit_card": r"\b(?:4\d{3}|5[1-5]\d{2}|3[47]\d{2}|6011)\d{12}\b", "api_key": r"(?:api[_-]?key|apikey|token)[\"']?\s*[:=]\s*[\"']?([a-zA-Z0-9_-]{20,})", "jwt": r"eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+", } findings = [] for e in entries: url = e.get("request", {}).get("url", "") body = e.get("request", {}).get("postData", {}).get("text", "") resp_body = e.get("response", {}).get("content", {}).get("text", "") combined = f"{body} {resp_body}" for name, pattern in patterns.items(): matches = re.findall(pattern, combined) if matches: findings.append({"url": url[:80], "data_type": name, "count": len(matches), "severity": "HIGH"}) print(f"\n[*] Sensitive data leakage findings: {len(findings)}") for f in findings[:10]: print(f" [!] {f['data_type']} in {f['url']} ({f['count']} occurrences)") return findings def check_auth_headers(entries): """Analyze authentication headers and token handling.""" findings = [] for e in entries: headers = {h["name"].lower(): h["value"] for h in e.get("request", {}).get("headers", [])} url = e.get("request", {}).get("url", "") if "authorization" in headers: auth = headers["authorization"] if auth.startswith("Basic "): findings.append({"url": url[:80], "issue": "Basic auth over network", "severity": "HIGH"}) elif auth.startswith("Bearer "): token = auth.split(" ", 1)[1] if len(token) < 20: findings.append({"url": url[:80], "issue": "Short bearer token", "severity": "MEDIUM"}) resp_headers = {h["name"].lower(): h["value"] for h in e.get("response", {}).get("headers", [])} if "set-cookie" in resp_headers: cookie = resp_headers["set-cookie"] if "secure" not in cookie.lower() or "httponly" not in cookie.lower(): findings.append({"url": url[:80], "issue": "Cookie missing Secure/HttpOnly", "severity": "MEDIUM"}) print(f"\n[*] Auth/cookie findings: {len(findings)}") return findings def check_certificate_pinning(entries): """Check for certificate pinning indicators in traffic.""" domains = set() for e in entries: url = e.get("request", {}).get("url", "") parsed = urlparse(url) if parsed.scheme == "https": domains.add(parsed.hostname) print(f"\n[*] HTTPS domains contacted: {len(domains)}") for d in sorted(domains)[:20]: print(f" {d}") print(" [*] Note: Certificate pinning bypass verified by successful interception") return list(domains) def check_api_security_headers(entries): """Check API response security headers.""" findings = [] checked_hosts = set() for e in entries: url = e.get("request", {}).get("url", "") host = urlparse(url).hostname if host in checked_hosts: continue checked_hosts.add(host) resp_headers = {h["name"].lower(): h["value"] for h in e.get("response", {}).get("headers", [])} missing = [] for hdr in ["strict-transport-security", "x-content-type-options", "x-frame-options", "content-security-policy"]: if hdr not in resp_headers: missing.append(hdr) if missing: findings.append({"host": host, "missing_headers": missing, "severity": "MEDIUM"}) print(f"\n[*] Security header findings: {len(findings)}") return findings def generate_report(all_findings, output_path): """Generate mobile traffic analysis report.""" report = {"analysis_date": datetime.now().isoformat(), "total_findings": len(all_findings), "findings": all_findings} with open(output_path, "w") as f: json.dump(report, f, indent=2, default=str) print(f"\n[*] Report saved to {output_path}") def main(): parser = argparse.ArgumentParser(description="Mobile Traffic Interception Analysis Agent") parser.add_argument("action", choices=["analyze", "insecure", "leakage", "auth", "full"]) parser.add_argument("--har", required=True, help="Path to HAR file from proxy capture") parser.add_argument("-o", "--output", default="mobile_traffic_report.json") args = parser.parse_args() entries = load_har_file(args.har) findings = [] if args.action in ("insecure", "full"): findings.extend(find_insecure_requests(entries)) if args.action in ("leakage", "full"): findings.extend(detect_sensitive_data_leakage(entries)) if args.action in ("auth", "full"): findings.extend(check_auth_headers(entries)) if args.action in ("analyze", "full"): check_certificate_pinning(entries) findings.extend(check_api_security_headers(entries)) if args.action == "full": generate_report(findings, args.output) if __name__ == "__main__": main()