mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-08-08 03:20:19 +03:00
Initial commit - 611 cybersecurity skills across all subdomains
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
---
|
||||
name: analyzing-ios-app-security-with-objection
|
||||
description: >
|
||||
Performs runtime mobile security exploration of iOS applications using Objection, a Frida-powered
|
||||
toolkit that enables security testers to interact with app internals without jailbreaking. Use when
|
||||
assessing iOS app security posture, bypassing client-side protections, dumping keychain items,
|
||||
inspecting filesystem storage, and evaluating runtime behavior. Activates for requests involving
|
||||
iOS security testing, Objection runtime analysis, Frida-based iOS assessment, or mobile runtime
|
||||
exploration.
|
||||
domain: cybersecurity
|
||||
subdomain: mobile-security
|
||||
author: mahipal
|
||||
tags: [mobile-security, ios, objection, frida, owasp-mobile, penetration-testing]
|
||||
version: 1.0.0
|
||||
license: MIT
|
||||
---
|
||||
# Analyzing iOS App Security with Objection
|
||||
|
||||
## When to Use
|
||||
|
||||
Use this skill when:
|
||||
- Performing runtime security assessment of iOS applications during authorized penetration tests
|
||||
- Inspecting iOS keychain, filesystem, and memory for sensitive data exposure
|
||||
- Bypassing client-side security controls (SSL pinning, jailbreak detection) during security testing
|
||||
- Evaluating iOS app behavior at runtime without access to source code
|
||||
|
||||
**Do not use** this skill on production devices without explicit authorization -- Objection modifies app runtime behavior and may trigger security monitoring.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Python 3.10+ with pip
|
||||
- Objection installed: `pip install objection`
|
||||
- Frida installed: `pip install frida-tools`
|
||||
- Target iOS device (jailbroken with Frida server, or non-jailbroken with repackaged IPA)
|
||||
- For non-jailbroken: `objection patchipa` to inject Frida gadget into IPA
|
||||
- macOS recommended for iOS testing (Xcode, ideviceinstaller)
|
||||
- USB connection to target device or network Frida server
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 1: Prepare the Testing Environment
|
||||
|
||||
**For jailbroken devices:**
|
||||
```bash
|
||||
# Install Frida server on device via Cydia/Sileo
|
||||
# SSH to device and start Frida server
|
||||
ssh root@<device_ip> "/usr/sbin/frida-server -D"
|
||||
|
||||
# Verify Frida connectivity
|
||||
frida-ps -U # List processes on USB-connected device
|
||||
```
|
||||
|
||||
**For non-jailbroken devices (authorized testing):**
|
||||
```bash
|
||||
# Patch IPA with Frida gadget
|
||||
objection patchipa --source target.ipa --codesign-signature "Apple Development: test@example.com"
|
||||
|
||||
# Install patched IPA
|
||||
ideviceinstaller -i target-patched.ipa
|
||||
```
|
||||
|
||||
### Step 2: Attach Objection to Target App
|
||||
|
||||
```bash
|
||||
# Attach to running app by bundle ID
|
||||
objection --gadget "com.target.app" explore
|
||||
|
||||
# Or spawn the app fresh
|
||||
objection --gadget "com.target.app" explore --startup-command "ios hooking list classes"
|
||||
```
|
||||
|
||||
Once attached, Objection provides an interactive REPL for runtime exploration.
|
||||
|
||||
### Step 3: Assess Data Storage Security (MASVS-STORAGE)
|
||||
|
||||
```bash
|
||||
# Dump iOS Keychain items accessible to the app
|
||||
ios keychain dump
|
||||
|
||||
# List files in app sandbox
|
||||
ios plist cat Info.plist
|
||||
env # Show app environment paths
|
||||
|
||||
# Inspect NSUserDefaults for sensitive data
|
||||
ios nsuserdefaults get
|
||||
|
||||
# List SQLite databases
|
||||
sqlite connect app_data.db
|
||||
sqlite execute query "SELECT * FROM credentials"
|
||||
|
||||
# Check for sensitive data in pasteboard
|
||||
ios pasteboard monitor
|
||||
```
|
||||
|
||||
### Step 4: Evaluate Network Security (MASVS-NETWORK)
|
||||
|
||||
```bash
|
||||
# Disable SSL/TLS certificate pinning
|
||||
ios sslpinning disable
|
||||
|
||||
# Verify pinning is bypassed by observing traffic in Burp Suite proxy
|
||||
# Monitor network-related class method calls
|
||||
ios hooking watch class NSURLSession
|
||||
ios hooking watch class NSURLConnection
|
||||
```
|
||||
|
||||
### Step 5: Inspect Authentication and Authorization (MASVS-AUTH)
|
||||
|
||||
```bash
|
||||
# List all Objective-C classes
|
||||
ios hooking list classes
|
||||
|
||||
# Search for authentication-related classes
|
||||
ios hooking search classes Auth
|
||||
ios hooking search classes Login
|
||||
ios hooking search classes Token
|
||||
|
||||
# Hook authentication methods to observe parameters
|
||||
ios hooking watch method "+[AuthManager validateToken:]" --dump-args --dump-return
|
||||
|
||||
# Monitor biometric authentication calls
|
||||
ios hooking watch class LAContext
|
||||
```
|
||||
|
||||
### Step 6: Assess Binary Protections (MASVS-RESILIENCE)
|
||||
|
||||
```bash
|
||||
# Check jailbreak detection implementation
|
||||
ios jailbreak disable
|
||||
|
||||
# Simulate jailbreak detection bypass
|
||||
ios jailbreak simulate
|
||||
|
||||
# List loaded frameworks and libraries
|
||||
memory list modules
|
||||
|
||||
# Search memory for sensitive strings
|
||||
memory search "password" --string
|
||||
memory search "api_key" --string
|
||||
memory search "Bearer" --string
|
||||
|
||||
# Dump specific memory regions
|
||||
memory dump all dump_output/
|
||||
```
|
||||
|
||||
### Step 7: Review Platform Interaction (MASVS-PLATFORM)
|
||||
|
||||
```bash
|
||||
# List URL schemes registered by the app
|
||||
ios info binary
|
||||
ios bundles list_frameworks
|
||||
|
||||
# Hook URL scheme handlers
|
||||
ios hooking watch method "-[AppDelegate application:openURL:options:]" --dump-args
|
||||
|
||||
# Monitor clipboard access
|
||||
ios pasteboard monitor
|
||||
|
||||
# Check for custom keyboard restrictions
|
||||
ios hooking search classes UITextField
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
| Term | Definition |
|
||||
|------|-----------|
|
||||
| **Objection** | Runtime mobile exploration toolkit built on Frida that provides pre-built scripts for common security testing tasks |
|
||||
| **Frida Gadget** | Shared library injected into app process to enable Frida instrumentation without jailbreak |
|
||||
| **Keychain** | iOS secure credential storage system; Objection can dump items accessible to the target app's keychain access group |
|
||||
| **SSL Pinning Bypass** | Runtime modification of certificate validation logic to allow proxy interception of HTTPS traffic |
|
||||
| **Method Hooking** | Intercepting Objective-C/Swift method calls at runtime to observe arguments, return values, and modify behavior |
|
||||
|
||||
## Tools & Systems
|
||||
|
||||
- **Objection**: High-level Frida-powered mobile security exploration toolkit with pre-built commands
|
||||
- **Frida**: Dynamic instrumentation framework providing JavaScript injection into native app processes
|
||||
- **Frida-tools**: CLI utilities for Frida including frida-ps, frida-trace, and frida-discover
|
||||
- **ideviceinstaller**: Cross-platform tool for installing/managing iOS apps via USB
|
||||
- **Burp Suite**: HTTP proxy for intercepting traffic after SSL pinning bypass
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
- **App crashes on attach**: Some apps implement Frida detection. Use `--startup-command` to hook anti-Frida checks early in the app lifecycle.
|
||||
- **Keychain access scope**: Objection can only dump keychain items within the app's access group. System keychain items require separate jailbreak-level tools.
|
||||
- **Swift name mangling**: Swift method names are mangled in the runtime. Use `ios hooking list classes` with grep to find demangled names.
|
||||
- **Non-persistent changes**: All Objection modifications are runtime-only and reset on app restart. Document findings immediately.
|
||||
@@ -0,0 +1,80 @@
|
||||
# iOS Objection Security Assessment Report
|
||||
|
||||
## Engagement Information
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Application | [APP_NAME] |
|
||||
| Bundle ID | [BUNDLE_ID] |
|
||||
| iOS Version | [IOS_VERSION] |
|
||||
| Device | [DEVICE_MODEL] |
|
||||
| Device State | [Jailbroken/Non-Jailbroken] |
|
||||
| Assessment Date | [DATE] |
|
||||
| Analyst | [ANALYST] |
|
||||
| Objection Version | [VERSION] |
|
||||
|
||||
## Executive Summary
|
||||
|
||||
[Brief narrative of findings from Objection runtime analysis]
|
||||
|
||||
## Keychain Analysis
|
||||
|
||||
| Service | Account | Data Type | Protection Class | Risk |
|
||||
|---------|---------|-----------|-----------------|------|
|
||||
| [SERVICE] | [ACCOUNT] | [TYPE] | [CLASS] | [RISK] |
|
||||
|
||||
**Findings**: [Description of sensitive data found in keychain]
|
||||
|
||||
## Data Storage Assessment
|
||||
|
||||
### NSUserDefaults
|
||||
| Key | Contains Sensitive Data | Risk |
|
||||
|-----|----------------------|------|
|
||||
| [KEY] | [YES/NO] | [RISK] |
|
||||
|
||||
### SQLite Databases
|
||||
| Database | Encrypted | Sensitive Tables | Risk |
|
||||
|----------|-----------|-----------------|------|
|
||||
| [DB_NAME] | [YES/NO] | [TABLES] | [RISK] |
|
||||
|
||||
### Filesystem
|
||||
| Path | Contents | Protection | Risk |
|
||||
|------|----------|-----------|------|
|
||||
| [PATH] | [DESCRIPTION] | [ATTRIBUTE] | [RISK] |
|
||||
|
||||
## Network Security
|
||||
|
||||
| Check | Result | Details |
|
||||
|-------|--------|---------|
|
||||
| SSL Pinning Present | [YES/NO] | [IMPLEMENTATION_DETAILS] |
|
||||
| SSL Pinning Bypass | [SUCCESS/FAIL] | [METHOD_USED] |
|
||||
| ATS Configuration | [STRICT/RELAXED] | [EXCEPTIONS] |
|
||||
|
||||
## Binary Protection Assessment
|
||||
|
||||
| Protection | Status | Details |
|
||||
|-----------|--------|---------|
|
||||
| Jailbreak Detection | [Present/Absent] | [BYPASS_DIFFICULTY] |
|
||||
| Frida Detection | [Present/Absent] | [DETAILS] |
|
||||
| Debug Detection | [Present/Absent] | [DETAILS] |
|
||||
| Code Obfuscation | [Yes/No] | [DETAILS] |
|
||||
|
||||
## Memory Analysis
|
||||
|
||||
| Search Pattern | Found | Risk | Details |
|
||||
|---------------|-------|------|---------|
|
||||
| Passwords | [YES/NO] | [RISK] | [DETAILS] |
|
||||
| Auth Tokens | [YES/NO] | [RISK] | [DETAILS] |
|
||||
| API Keys | [YES/NO] | [RISK] | [DETAILS] |
|
||||
| JWTs | [YES/NO] | [RISK] | [DETAILS] |
|
||||
|
||||
## Recommendations
|
||||
|
||||
### Critical
|
||||
1. [RECOMMENDATION]
|
||||
|
||||
### High
|
||||
1. [RECOMMENDATION]
|
||||
|
||||
### Medium
|
||||
1. [RECOMMENDATION]
|
||||
@@ -0,0 +1,43 @@
|
||||
# Standards Reference: iOS App Security with Objection
|
||||
|
||||
## OWASP Mobile Top 10 2024 Mapping
|
||||
|
||||
| OWASP ID | Risk | Objection Testing Coverage |
|
||||
|----------|------|---------------------------|
|
||||
| M1 | Improper Credential Usage | Keychain dumping, memory string search for hardcoded credentials |
|
||||
| M3 | Insecure Authentication/Authorization | Hook authentication methods, bypass biometric checks |
|
||||
| M5 | Insecure Communication | SSL pinning bypass, network class hooking |
|
||||
| M7 | Insufficient Binary Protections | Jailbreak detection bypass, Frida detection assessment |
|
||||
| M8 | Security Misconfiguration | Info.plist review, URL scheme analysis, ATS configuration |
|
||||
| M9 | Insecure Data Storage | NSUserDefaults inspection, SQLite database access, file system review |
|
||||
|
||||
## OWASP MASVS v2.0 Control Mapping
|
||||
|
||||
| MASVS Category | Objection Commands | Assessment Area |
|
||||
|----------------|-------------------|-----------------|
|
||||
| MASVS-STORAGE | `ios keychain dump`, `ios nsuserdefaults get`, `sqlite connect` | Sensitive data in keychain, NSUserDefaults, databases |
|
||||
| MASVS-CRYPTO | `memory search`, hook crypto framework calls | Key storage, algorithm selection |
|
||||
| MASVS-AUTH | Hook LAContext, authentication classes | Biometric bypass, session management |
|
||||
| MASVS-NETWORK | `ios sslpinning disable`, hook NSURLSession | Certificate pinning, cleartext traffic |
|
||||
| MASVS-PLATFORM | Hook URL scheme handlers, pasteboard monitor | Deep link security, clipboard exposure |
|
||||
| MASVS-CODE | `memory list modules`, binary inspection | Debugging symbols, framework analysis |
|
||||
| MASVS-RESILIENCE | `ios jailbreak disable`, Frida detection hooks | Anti-tampering, anti-debugging |
|
||||
|
||||
## OWASP MASTG Test Cases
|
||||
|
||||
| Test ID | Description | Objection Approach |
|
||||
|---------|-------------|-------------------|
|
||||
| MASTG-TEST-0053 | Testing Local Storage for Sensitive Data | `ios keychain dump`, filesystem inspection |
|
||||
| MASTG-TEST-0057 | Testing Backups for Sensitive Data | Check backup exclusion attributes |
|
||||
| MASTG-TEST-0060 | Testing Custom URL Schemes | Hook `application:openURL:options:` |
|
||||
| MASTG-TEST-0063 | Testing for Sensitive Data in Logs | Monitor NSLog calls via hooking |
|
||||
| MASTG-TEST-0066 | Testing Enforced App Transport Security | Inspect Info.plist ATS configuration |
|
||||
|
||||
## Apple Platform Security Requirements
|
||||
|
||||
| Requirement | Assessment Method |
|
||||
|-------------|-------------------|
|
||||
| Keychain Access Control | Verify kSecAttrAccessible values via keychain dump |
|
||||
| App Transport Security | Check Info.plist for NSAllowsArbitraryLoads exceptions |
|
||||
| Data Protection API | Verify file protection attributes on sensitive files |
|
||||
| Secure Enclave Usage | Hook SecKey operations for biometric-protected keys |
|
||||
@@ -0,0 +1,83 @@
|
||||
# Workflows: iOS App Security with Objection
|
||||
|
||||
## Workflow 1: iOS Runtime Security Assessment
|
||||
|
||||
```
|
||||
[Setup Environment] --> [Prepare Device] --> [Attach Objection] --> [Runtime Analysis]
|
||||
| | | |
|
||||
v v v v
|
||||
[Install Frida] [Jailbroken: Start [Connect via USB] [Data Storage Check]
|
||||
[Install Objection] frida-server] [Spawn target app] [Network Security]
|
||||
[Non-JB: Patch IPA] [Auth Mechanism Review]
|
||||
[Binary Protection Test]
|
||||
|
|
||||
v
|
||||
[Document Findings]
|
||||
[Generate Report]
|
||||
```
|
||||
|
||||
## Workflow 2: SSL Pinning Bypass for Traffic Interception
|
||||
|
||||
```
|
||||
[Configure Burp Proxy] --> [Set device proxy] --> [Attach Objection]
|
||||
|
|
||||
v
|
||||
[ios sslpinning disable]
|
||||
|
|
||||
v
|
||||
[Navigate app in browser/UI]
|
||||
|
|
||||
v
|
||||
[Capture HTTPS traffic in Burp]
|
||||
[Analyze API endpoints]
|
||||
[Test authentication flows]
|
||||
[Check for sensitive data in transit]
|
||||
```
|
||||
|
||||
## Workflow 3: Keychain and Data Storage Assessment
|
||||
|
||||
```
|
||||
[Attach Objection] --> [ios keychain dump] --> [Analyze keychain items]
|
||||
| |
|
||||
v v
|
||||
[ios nsuserdefaults get] [Check protection classes]
|
||||
| [Identify sensitive tokens]
|
||||
v [Verify encryption at rest]
|
||||
[List app sandbox files]
|
||||
|
|
||||
v
|
||||
[sqlite connect *.db]
|
||||
[Query sensitive tables]
|
||||
|
|
||||
v
|
||||
[memory search "password"]
|
||||
[memory search "token"]
|
||||
[memory search "secret"]
|
||||
```
|
||||
|
||||
## Workflow 4: Jailbreak Detection Assessment
|
||||
|
||||
```
|
||||
[Attach Objection] --> [ios jailbreak disable] --> [Navigate app]
|
||||
| |
|
||||
v [App functions normally?]
|
||||
[Hook detection methods] / \
|
||||
[Monitor file checks] [Yes] [No]
|
||||
[Monitor Cydia URL scheme] | |
|
||||
| [Detection [Additional detection
|
||||
v bypassed] methods exist]
|
||||
[Document detection |
|
||||
methods found] [Hook deeper: search
|
||||
[Assess bypass for custom checks]
|
||||
difficulty] [Frida script for
|
||||
targeted bypass]
|
||||
```
|
||||
|
||||
## Decision Matrix: Testing Approach
|
||||
|
||||
| Device State | IPA Access | Approach |
|
||||
|-------------|-----------|----------|
|
||||
| Jailbroken | Not needed | Direct Frida server + Objection attach |
|
||||
| Non-jailbroken | Available | Patch IPA with `objection patchipa` |
|
||||
| Non-jailbroken | Not available | Request IPA from client or use device management |
|
||||
| Emulator | N/A | Limited: Frida on Corellium or similar platform |
|
||||
@@ -0,0 +1,294 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Objection iOS Security Assessment Automation
|
||||
|
||||
Automates common Objection commands for iOS app security testing.
|
||||
Runs keychain dump, storage inspection, SSL pinning check, and jailbreak detection analysis.
|
||||
|
||||
Usage:
|
||||
python process.py --bundle-id com.target.app [--device-id UDID] [--output report.json]
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
import re
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class ObjectionAssessor:
|
||||
"""Automates Objection-based iOS security assessment tasks."""
|
||||
|
||||
def __init__(self, bundle_id: str, device_id: str = None):
|
||||
self.bundle_id = bundle_id
|
||||
self.device_id = device_id
|
||||
self.findings = []
|
||||
|
||||
def _run_objection_command(self, command: str, timeout: int = 30) -> str:
|
||||
"""Execute an Objection command and return output."""
|
||||
cmd = ["objection", "--gadget", self.bundle_id, "run", command]
|
||||
if self.device_id:
|
||||
cmd.insert(1, "--serial")
|
||||
cmd.insert(2, self.device_id)
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=timeout,
|
||||
)
|
||||
return result.stdout + result.stderr
|
||||
except subprocess.TimeoutExpired:
|
||||
return f"TIMEOUT: Command '{command}' exceeded {timeout}s"
|
||||
except FileNotFoundError:
|
||||
return "ERROR: Objection not found. Install with: pip install objection"
|
||||
|
||||
def _run_frida_command(self, script: str, timeout: int = 15) -> str:
|
||||
"""Execute a Frida script snippet."""
|
||||
cmd = ["frida", "-U", "-n", self.bundle_id, "-e", script]
|
||||
if self.device_id:
|
||||
cmd.extend(["-D", self.device_id])
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=timeout,
|
||||
)
|
||||
return result.stdout
|
||||
except (subprocess.TimeoutExpired, FileNotFoundError):
|
||||
return ""
|
||||
|
||||
def check_frida_connectivity(self) -> dict:
|
||||
"""Verify Frida can connect to the device."""
|
||||
cmd = ["frida-ps", "-U"]
|
||||
if self.device_id:
|
||||
cmd.extend(["-D", self.device_id])
|
||||
|
||||
try:
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
|
||||
connected = result.returncode == 0
|
||||
processes = len(result.stdout.strip().split("\n")) - 1 if connected else 0
|
||||
return {
|
||||
"connected": connected,
|
||||
"process_count": processes,
|
||||
"target_running": self.bundle_id in result.stdout,
|
||||
}
|
||||
except (subprocess.TimeoutExpired, FileNotFoundError):
|
||||
return {"connected": False, "process_count": 0, "target_running": False}
|
||||
|
||||
def dump_keychain(self) -> dict:
|
||||
"""Dump keychain items accessible to the app."""
|
||||
output = self._run_objection_command("ios keychain dump")
|
||||
items = []
|
||||
current_item = {}
|
||||
|
||||
for line in output.split("\n"):
|
||||
line = line.strip()
|
||||
if "Service" in line and ":" in line:
|
||||
if current_item:
|
||||
items.append(current_item)
|
||||
current_item = {"service": line.split(":", 1)[-1].strip()}
|
||||
elif "Account" in line and ":" in line:
|
||||
current_item["account"] = line.split(":", 1)[-1].strip()
|
||||
elif "Data" in line and ":" in line:
|
||||
data = line.split(":", 1)[-1].strip()
|
||||
current_item["data_preview"] = data[:50] + "..." if len(data) > 50 else data
|
||||
current_item["data_length"] = len(data)
|
||||
|
||||
if current_item:
|
||||
items.append(current_item)
|
||||
|
||||
finding = {
|
||||
"check": "keychain_dump",
|
||||
"category": "MASVS-STORAGE",
|
||||
"owasp_mobile": "M9",
|
||||
"items_found": len(items),
|
||||
"items": items[:20],
|
||||
"severity": "HIGH" if items else "INFO",
|
||||
"description": f"Found {len(items)} keychain items accessible to the application",
|
||||
}
|
||||
self.findings.append(finding)
|
||||
return finding
|
||||
|
||||
def check_nsuserdefaults(self) -> dict:
|
||||
"""Inspect NSUserDefaults for sensitive data."""
|
||||
output = self._run_objection_command("ios nsuserdefaults get")
|
||||
sensitive_patterns = [
|
||||
"password", "token", "secret", "key", "auth",
|
||||
"session", "credential", "api_key", "apikey",
|
||||
]
|
||||
|
||||
sensitive_entries = []
|
||||
for line in output.split("\n"):
|
||||
line_lower = line.lower()
|
||||
for pattern in sensitive_patterns:
|
||||
if pattern in line_lower:
|
||||
sensitive_entries.append(line.strip())
|
||||
break
|
||||
|
||||
finding = {
|
||||
"check": "nsuserdefaults",
|
||||
"category": "MASVS-STORAGE",
|
||||
"owasp_mobile": "M9",
|
||||
"sensitive_entries": len(sensitive_entries),
|
||||
"entries": sensitive_entries[:10],
|
||||
"severity": "HIGH" if sensitive_entries else "PASS",
|
||||
"description": f"Found {len(sensitive_entries)} potentially sensitive NSUserDefaults entries",
|
||||
}
|
||||
self.findings.append(finding)
|
||||
return finding
|
||||
|
||||
def check_ssl_pinning(self) -> dict:
|
||||
"""Assess SSL pinning implementation."""
|
||||
output = self._run_objection_command("ios sslpinning disable")
|
||||
pinning_detected = "pinning" in output.lower() or "hook" in output.lower()
|
||||
|
||||
finding = {
|
||||
"check": "ssl_pinning",
|
||||
"category": "MASVS-NETWORK",
|
||||
"owasp_mobile": "M5",
|
||||
"pinning_detected": pinning_detected,
|
||||
"bypass_output": output[:500],
|
||||
"severity": "MEDIUM" if not pinning_detected else "INFO",
|
||||
"description": "SSL pinning " + ("detected and bypassed" if pinning_detected else "not detected"),
|
||||
}
|
||||
self.findings.append(finding)
|
||||
return finding
|
||||
|
||||
def check_jailbreak_detection(self) -> dict:
|
||||
"""Assess jailbreak detection implementation."""
|
||||
output = self._run_objection_command("ios jailbreak disable")
|
||||
detection_found = "hook" in output.lower() or "bypass" in output.lower()
|
||||
|
||||
finding = {
|
||||
"check": "jailbreak_detection",
|
||||
"category": "MASVS-RESILIENCE",
|
||||
"owasp_mobile": "M7",
|
||||
"detection_implemented": detection_found,
|
||||
"bypass_output": output[:500],
|
||||
"severity": "MEDIUM" if not detection_found else "INFO",
|
||||
"description": "Jailbreak detection " + ("found" if detection_found else "not found or not implemented"),
|
||||
}
|
||||
self.findings.append(finding)
|
||||
return finding
|
||||
|
||||
def search_sensitive_memory(self) -> dict:
|
||||
"""Search app memory for sensitive strings."""
|
||||
patterns = ["password", "Bearer ", "eyJ", "api_key", "secret"]
|
||||
memory_findings = []
|
||||
|
||||
for pattern in patterns:
|
||||
output = self._run_objection_command(f'memory search "{pattern}" --string')
|
||||
matches = output.count("Found")
|
||||
if matches > 0:
|
||||
memory_findings.append({
|
||||
"pattern": pattern,
|
||||
"matches": matches,
|
||||
})
|
||||
|
||||
finding = {
|
||||
"check": "memory_search",
|
||||
"category": "MASVS-STORAGE",
|
||||
"owasp_mobile": "M9",
|
||||
"patterns_with_matches": len(memory_findings),
|
||||
"details": memory_findings,
|
||||
"severity": "HIGH" if memory_findings else "PASS",
|
||||
"description": f"Found sensitive patterns in memory for {len(memory_findings)} search terms",
|
||||
}
|
||||
self.findings.append(finding)
|
||||
return finding
|
||||
|
||||
def get_app_info(self) -> dict:
|
||||
"""Gather basic app information."""
|
||||
output = self._run_objection_command("ios info binary")
|
||||
env_output = self._run_objection_command("env")
|
||||
|
||||
return {
|
||||
"bundle_id": self.bundle_id,
|
||||
"binary_info": output[:1000],
|
||||
"environment": env_output[:1000],
|
||||
}
|
||||
|
||||
def generate_report(self) -> dict:
|
||||
"""Generate consolidated assessment report."""
|
||||
severity_counts = {"HIGH": 0, "MEDIUM": 0, "LOW": 0, "INFO": 0, "PASS": 0}
|
||||
for f in self.findings:
|
||||
sev = f.get("severity", "INFO")
|
||||
severity_counts[sev] = severity_counts.get(sev, 0) + 1
|
||||
|
||||
return {
|
||||
"assessment": {
|
||||
"target": self.bundle_id,
|
||||
"date": datetime.now().isoformat(),
|
||||
"tool": "Objection (Frida-powered)",
|
||||
"type": "iOS Runtime Security Assessment",
|
||||
},
|
||||
"summary": {
|
||||
"total_checks": len(self.findings),
|
||||
"severity_breakdown": severity_counts,
|
||||
"critical_findings": [
|
||||
f for f in self.findings if f.get("severity") in ("HIGH", "CRITICAL")
|
||||
],
|
||||
},
|
||||
"findings": self.findings,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Objection iOS Security Assessment Automation"
|
||||
)
|
||||
parser.add_argument("--bundle-id", required=True, help="iOS app bundle identifier")
|
||||
parser.add_argument("--device-id", help="Device UDID for targeting specific device")
|
||||
parser.add_argument("--output", default="objection_report.json", help="Output report path")
|
||||
parser.add_argument("--checks", nargs="+",
|
||||
default=["keychain", "nsuserdefaults", "ssl", "jailbreak", "memory"],
|
||||
help="Checks to run")
|
||||
args = parser.parse_args()
|
||||
|
||||
assessor = ObjectionAssessor(args.bundle_id, args.device_id)
|
||||
|
||||
# Verify connectivity
|
||||
connectivity = assessor.check_frida_connectivity()
|
||||
if not connectivity["connected"]:
|
||||
print("[-] ERROR: Cannot connect to device via Frida")
|
||||
print(" Ensure Frida server is running on device or IPA is patched")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"[+] Connected to device. Target running: {connectivity['target_running']}")
|
||||
|
||||
# Run selected checks
|
||||
check_map = {
|
||||
"keychain": assessor.dump_keychain,
|
||||
"nsuserdefaults": assessor.check_nsuserdefaults,
|
||||
"ssl": assessor.check_ssl_pinning,
|
||||
"jailbreak": assessor.check_jailbreak_detection,
|
||||
"memory": assessor.search_sensitive_memory,
|
||||
}
|
||||
|
||||
for check in args.checks:
|
||||
if check in check_map:
|
||||
print(f"[*] Running check: {check}")
|
||||
result = check_map[check]()
|
||||
print(f" Severity: {result['severity']} - {result['description']}")
|
||||
|
||||
# Generate report
|
||||
report = assessor.generate_report()
|
||||
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(report, f, indent=2)
|
||||
print(f"\n[+] Report saved: {args.output}")
|
||||
|
||||
# Summary
|
||||
high_count = report["summary"]["severity_breakdown"].get("HIGH", 0)
|
||||
if high_count > 0:
|
||||
print(f"[!] {high_count} HIGH severity findings require attention")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user