Files
Anthropic-Cybersecurity-Skills/skills/exploiting-deeplink-vulnerabilities/scripts/agent.py
T
mukul975 c21af3347e Complete folder anatomy for all 649 cybersecurity skills + update LICENSE to Mahipal
- Add scripts/agent.py and references/api-reference.md to all remaining skills
- Update all 648 LICENSE files: copyright now reads 'Mahipal'
- Add implementing-security-monitoring-with-datadog (new skill with full anatomy)
- All 649 skills now have: SKILL.md, LICENSE, scripts/agent.py, references/api-reference.md
2026-03-11 00:22:12 +01:00

148 lines
4.8 KiB
Python

#!/usr/bin/env python3
"""Agent for testing deep link / custom URL scheme vulnerabilities in mobile apps."""
import argparse
import json
import os
import re
import subprocess
import sys
from datetime import datetime, timezone
ANDROID_SCHEME_PATTERN = re.compile(
r'<intent-filter[^>]*>.*?<data\s+android:scheme="([^"]+)".*?</intent-filter>',
re.DOTALL
)
ANDROID_HOST_PATTERN = re.compile(r'android:host="([^"]+)"')
IOS_SCHEME_PATTERN = re.compile(r'<string>(\w+)</string>\s*</array>\s*<key>CFBundleURLName')
IOS_UNIVERSAL_PATTERN = re.compile(r'"applinks:\s*([\w.-]+)"')
def analyze_android_manifest(manifest_path):
"""Parse AndroidManifest.xml for deep link configurations."""
findings = []
try:
with open(manifest_path, "r", errors="replace") as f:
content = f.read()
except FileNotFoundError:
return findings
for match in ANDROID_SCHEME_PATTERN.finditer(content):
block = match.group(0)
scheme = match.group(1)
hosts = ANDROID_HOST_PATTERN.findall(block)
exported = "android:exported=\"true\"" in block or "android:exported" not in block
findings.append({
"scheme": scheme,
"hosts": hosts,
"exported": exported,
"block": block[:200],
"risk": "HIGH" if exported and scheme not in ("https", "http") else "MEDIUM",
})
return findings
def analyze_ios_plist(plist_path):
"""Parse iOS Info.plist for URL scheme and universal link configurations."""
findings = []
try:
with open(plist_path, "r", errors="replace") as f:
content = f.read()
except FileNotFoundError:
return findings
for match in IOS_SCHEME_PATTERN.finditer(content):
findings.append({
"type": "custom_url_scheme",
"scheme": match.group(1),
"risk": "HIGH",
"note": "Custom URL schemes lack origin verification",
})
for match in IOS_UNIVERSAL_PATTERN.finditer(content):
findings.append({
"type": "universal_link",
"domain": match.group(1),
"risk": "LOW",
"note": "Universal links verify domain ownership",
})
return findings
def test_deep_link_injection(scheme, host, path, payload):
"""Construct and test a deep link injection payload."""
test_url = f"{scheme}://{host}{path}{payload}"
return {
"test_url": test_url,
"payload": payload,
"vectors": [
"Open redirect via deep link",
"JavaScript execution in WebView",
"Parameter injection",
"Intent redirection (Android)",
],
}
def check_adb_deep_link(package, uri):
"""Test Android deep link via ADB."""
cmd = ["adb", "shell", "am", "start", "-W",
"-a", "android.intent.action.VIEW",
"-d", uri, package]
try:
result = subprocess.check_output(cmd, text=True, errors="replace", timeout=15)
return {"uri": uri, "status": "launched", "output": result[:300]}
except (subprocess.SubprocessError, FileNotFoundError):
return {"uri": uri, "status": "failed"}
def main():
parser = argparse.ArgumentParser(
description="Test deep link / URL scheme vulnerabilities (authorized testing only)"
)
parser.add_argument("--android-manifest", help="Path to AndroidManifest.xml")
parser.add_argument("--ios-plist", help="Path to Info.plist")
parser.add_argument("--test-scheme", help="URL scheme to test")
parser.add_argument("--test-host", help="Host for deep link test")
parser.add_argument("--output", "-o", help="Output JSON report")
args = parser.parse_args()
print("[*] Deep Link Vulnerability Testing Agent")
report = {"timestamp": datetime.now(timezone.utc).isoformat(), "findings": []}
if args.android_manifest:
android = analyze_android_manifest(args.android_manifest)
report["findings"].extend(android)
print(f"[*] Android deep links found: {len(android)}")
if args.ios_plist:
ios = analyze_ios_plist(args.ios_plist)
report["findings"].extend(ios)
print(f"[*] iOS URL schemes found: {len(ios)}")
if args.test_scheme and args.test_host:
payloads = [
"?redirect=https://evil.com",
"#javascript:alert(1)",
"?token=stolen&callback=https://evil.com",
"/../../sensitive-path",
]
for p in payloads:
result = test_deep_link_injection(args.test_scheme, args.test_host, "/", p)
report["findings"].append(result)
report["risk_level"] = "HIGH" if report["findings"] else "LOW"
if args.output:
with open(args.output, "w") as f:
json.dump(report, f, indent=2)
print(f"[*] Report saved to {args.output}")
else:
print(json.dumps(report, indent=2))
if __name__ == "__main__":
main()