Files
T
mukul975 27c6414ca5 Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills:
- scripts/agent.py: 80-150 line Python agents using real libraries (impacket,
  boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.)
- references/api-reference.md: real API documentation with method signatures
- LICENSE: MIT license for all skill folders
2026-03-10 21:02:12 +01:00

161 lines
6.4 KiB
Python

#!/usr/bin/env python3
"""Agent for analyzing intercepted mobile app traffic via mitmproxy for security testing."""
import json
import argparse
import sys
import os
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()