mobile security

Analyzing iOS App Security with Objection

Runtime iOS app security testing with Objection (Frida): inspect keychain and filesystem data, explore app internals at runtime, and validate/bypass client-side protections during authorized mobile assessments.

fridaiosmobile-securityobjectionowasp-mobilepenetration-testing
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

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:

# 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):

# 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

# 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)

# 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)

# 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)

# 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)

# 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)

# 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.
Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 3

api-reference.md3.4 KB

API Reference: iOS App Security with Objection

Objection CLI

Launch

objection -g com.example.app explore          # Attach to running app
objection -g com.example.app explore -s "command"  # Run startup command
objection patchipa --source app.ipa           # Patch IPA with Frida gadget

Keychain & Data Storage

ios keychain dump                    # Dump keychain items
ios keychain dump --json             # JSON output
ios cookies get                      # List HTTP cookies
ios nsuserdefaults get               # Read NSUserDefaults
ios plist cat Info.plist             # Read plist file

SSL Pinning

ios sslpinning disable               # Bypass SSL pinning
ios sslpinning disable --quiet        # Quiet mode

Jailbreak Detection

ios jailbreak disable                 # Bypass jailbreak detection
ios jailbreak simulate                # Simulate jailbroken device

Hooking

ios hooking list classes                        # List all classes
ios hooking list classes --include Auth          # Filter classes
ios hooking list class_methods ClassName         # List methods
ios hooking watch method "-[Class method]"       # Watch method calls
ios hooking set return_value "-[Class isJB]" false  # Override return

Filesystem

ls /                                  # List app sandbox root
ls /Documents                         # List Documents directory
file download /path/to/file local.out  # Download file
file upload local.file /remote/path    # Upload file

Memory

memory dump all dump.bin              # Dump all memory
memory search "password"              # Search memory for string
memory list modules                   # List loaded modules
memory list exports libModule.dylib   # List module exports

Frida CLI

Syntax

frida -U -n AppName                   # Attach by name
frida -U -f com.app.id                # Spawn and attach
frida -U -n AppName -l script.js      # Load script
frida-ps -U                           # List running processes
frida-ls-devices                      # List connected devices

Common Frida Scripts

// Hook method and log arguments
ObjC.choose(ObjC.classes.ClassName, {
    onMatch: function(instance) {
        Interceptor.attach(instance['- methodName:'].implementation, {
            onEnter: function(args) {
                console.log('arg1:', ObjC.Object(args[2]));
            }
        });
    }, onComplete: function() {}
});

OWASP Mobile Top 10 (2024)

ID Category Objection Check
M1 Improper Credential Usage ios keychain dump
M2 Inadequate Supply Chain Security Binary analysis
M3 Insecure Authentication Hook auth classes
M4 Insufficient Input/Output Validation Hook input methods
M5 Insecure Communication ios sslpinning disable
M6 Inadequate Privacy Controls ios nsuserdefaults get
M7 Insufficient Binary Protections Check PIE, ARC, stack canary
M8 Security Misconfiguration ios plist cat Info.plist
M9 Insecure Data Storage Filesystem + keychain review
M10 Insufficient Cryptography Hook crypto classes

iOS App Sandbox Paths

Path Contents
/Documents User-generated data
/Library/Caches Cached data
/Library/Preferences Plist settings
/tmp Temporary files
/Library/Cookies Cookie storage
standards.md2.6 KB

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
workflows.md4.1 KB

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

Scripts 2

agent.py7.1 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""iOS app security analysis agent using Objection/Frida concepts.

Performs runtime security assessment of iOS apps including SSL pinning bypass,
keychain dumping, filesystem inspection, and jailbreak detection bypass.
"""

import subprocess
import json
import sys


def run_objection(command, app_id=None, timeout=30):
    """Execute an Objection command against a target app."""
    cmd = ["objection"]
    if app_id:
        cmd.extend(["-g", app_id])
    cmd.extend(["explore", "-c", command])
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
        return result.stdout, result.returncode
    except FileNotFoundError:
        return "objection not installed (pip install objection)", 1
    except subprocess.TimeoutExpired:
        return "Command timed out", 1


def run_frida(script_code, app_id, timeout=30):
    """Execute a Frida script against target app."""
    cmd = ["frida", "-U", "-n", app_id, "-e", script_code]
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
        return result.stdout, result.returncode
    except FileNotFoundError:
        return "frida not installed (pip install frida-tools)", 1
    except subprocess.TimeoutExpired:
        return "Command timed out", 1


def dump_keychain(app_id):
    """Dump keychain items accessible by the application."""
    return run_objection("ios keychain dump", app_id)


def dump_cookies(app_id):
    """Dump HTTP cookies stored by the application."""
    return run_objection("ios cookies get", app_id)


def list_classes(app_id, filter_str=None):
    """List Objective-C classes loaded in the app."""
    cmd = "ios hooking list classes"
    if filter_str:
        cmd += f" --include {filter_str}"
    return run_objection(cmd, app_id)


def check_ssl_pinning(app_id):
    """Check and bypass SSL certificate pinning."""
    return run_objection("ios sslpinning disable", app_id)


def check_jailbreak_detection(app_id):
    """Check for and bypass jailbreak detection."""
    return run_objection("ios jailbreak disable", app_id)


def inspect_filesystem(app_id, path="/"):
    """Inspect the application's filesystem sandbox."""
    return run_objection(f"ls {path}", app_id)


def dump_plist(app_id):
    """Dump application plist configuration files."""
    return run_objection("ios plist cat Info.plist", app_id)


def check_pasteboard(app_id):
    """Check pasteboard/clipboard for sensitive data."""
    return run_objection("ios pasteboard monitor", app_id)


def search_binary_strings(app_id, pattern):
    """Search for strings in the app binary."""
    return run_objection(f"memory search '{pattern}'", app_id)


OWASP_MOBILE_CHECKS = {
    "M1_Improper_Platform_Usage": {
        "checks": ["ios keychain dump", "ios plist cat Info.plist"],
        "description": "Check for misuse of platform security features",
    },
    "M2_Insecure_Data_Storage": {
        "checks": ["ios keychain dump", "ios cookies get", "ios nsuserdefaults get"],
        "description": "Check for sensitive data in insecure storage",
    },
    "M3_Insecure_Communication": {
        "checks": ["ios sslpinning disable"],
        "description": "Test SSL/TLS implementation and certificate pinning",
    },
    "M4_Insecure_Authentication": {
        "checks": ["ios hooking list classes --include Auth",
                    "ios hooking list classes --include Login"],
        "description": "Analyze authentication mechanisms",
    },
    "M5_Insufficient_Cryptography": {
        "checks": ["ios hooking list classes --include Crypto",
                    "ios hooking list classes --include AES"],
        "description": "Review cryptographic implementations",
    },
    "M8_Code_Tampering": {
        "checks": ["ios jailbreak disable"],
        "description": "Test runtime integrity and jailbreak detection",
    },
    "M9_Reverse_Engineering": {
        "checks": ["ios hooking list classes"],
        "description": "Assess reverse engineering protections",
    },
}


def run_owasp_assessment(app_id):
    """Run OWASP Mobile Top 10 security checks."""
    results = {}
    for category, config in OWASP_MOBILE_CHECKS.items():
        category_results = {"description": config["description"], "findings": []}
        for check in config["checks"]:
            output, rc = run_objection(check, app_id)
            category_results["findings"].append({
                "command": check,
                "status": "success" if rc == 0 else "failed",
                "output_preview": output[:200] if output else "",
            })
        results[category] = category_results
    return results


FRIDA_SCRIPTS = {
    "ssl_pinning_bypass": """
ObjC.choose(ObjC.classes.NSURLSessionConfiguration, {
    onMatch: function(instance) {
        instance['- setTLSMinimumSupportedProtocol:'](0);
    }, onComplete: function() {}
});
""",
    "jailbreak_bypass": """
var paths = ['/Applications/Cydia.app', '/usr/sbin/sshd', '/etc/apt'];
Interceptor.attach(ObjC.classes.NSFileManager['- fileExistsAtPath:'].implementation, {
    onEnter: function(args) { this.path = ObjC.Object(args[2]).toString(); },
    onLeave: function(retval) {
        if (paths.some(p => this.path.includes(p))) retval.replace(0);
    }
});
""",
    "keychain_dump": """
var kSecClass = ObjC.classes.__NSDictionary.dictionaryWithObject_forKey_(
    ObjC.classes.__NSCFConstantString.alloc().initWithUTF8String_('genp'),
    ObjC.classes.__NSCFConstantString.alloc().initWithUTF8String_('class')
);
console.log('Keychain query prepared');
""",
}


def generate_report(app_id, assessment_results):
    """Generate iOS security assessment report."""
    findings_count = sum(
        len(cat["findings"]) for cat in assessment_results.values()
    )
    return {
        "app_identifier": app_id,
        "assessment_framework": "OWASP Mobile Top 10",
        "categories_tested": len(assessment_results),
        "total_checks": findings_count,
        "results": assessment_results,
    }


if __name__ == "__main__":
    print("=" * 60)
    print("iOS App Security Analysis Agent (Objection/Frida)")
    print("Runtime analysis, SSL bypass, keychain dump, OWASP checks")
    print("=" * 60)

    app_id = sys.argv[1] if len(sys.argv) > 1 else None

    if not app_id:
        print("\n[DEMO] Usage: python agent.py <app_bundle_id>")
        print("  e.g. python agent.py com.example.app")
        print("\nAvailable checks:")
        for category, config in OWASP_MOBILE_CHECKS.items():
            print(f"  {category}: {config['description']}")
        print("\nFrida scripts available:")
        for name in FRIDA_SCRIPTS:
            print(f"  {name}")
        sys.exit(0)

    print(f"\n[*] Target: {app_id}")
    print("[*] Running OWASP Mobile Top 10 assessment...")

    results = run_owasp_assessment(app_id)
    report = generate_report(app_id, results)

    for category, data in results.items():
        status_counts = {"success": 0, "failed": 0}
        for f in data["findings"]:
            status_counts[f["status"]] += 1
        print(f"\n  [{category}] {data['description']}")
        print(f"    Checks: {status_counts['success']} passed, {status_counts['failed']} failed")

    print(f"\n{json.dumps(report, indent=2, default=str)}")
process.py10.8 KB
Display-only source. This catalog never executes bundled scripts.
#!/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()

Assets 1

template.mdtext/markdown · 2.1 KB
Keep exploring