MMNA Logo

iOS Module 2

Security Course

📝 MODULE 2 OF 3
🛡️ Development Module

Secure Coding & Application Hardening

Development Security Practices

Master secure Swift/Objective-C development: input validation, hardcoded secrets risks, Keychain storage. Learn application hardening, code obfuscation, runtime integrity checks. Understand threat modeling, secure development lifecycle, App Store compliance. Build secure applications from foundation.

Secure Swift Coding Awareness

Foundation of secure development

✍️ Input Validation Mindset

Never trust user input. All data from users, network, files must be validated. Input validation prevents injection attacks, buffer overflows, logic errors. Security-first mindset: assume attacker controls input.

Input Validation Best Practices

  • Whitelist Approach: Define what IS allowed, reject everything else. More secure than blacklist (allowing all except known bad).
  • Type Checking: Verify input type matches expected. String when expecting number? Reject. Swift type system helps enforce at compile time.
  • Length Checks: Validate input length. Too-long input might indicate buffer overflow attack. Set reasonable maximums.
  • Format Validation: Email format, phone number format, URL format. Use regex cautiously (can be expensive).
  • Range Checks: Numeric input within expected range? Age 0-120 valid, age 500 invalid. Prevents logic errors.
  • Encoding Awareness: Different encodings (UTF-8, Unicode) can cause issues. Validate character encoding.

Common Input Attacks

  • SQL Injection: Attackers inject SQL commands via input. Example: search field gets `"; DROP TABLE users;--`. Parameterized queries prevent this.
  • Command Injection: Injecting shell commands. Example: filename input used in `system()` call. Attacker enters `$(rm -rf /)` as filename.
  • Path Traversal: Filename input like `../../etc/passwd` accessing files outside intended directory. Validate paths.
  • Buffer Overflow: Input longer than buffer capacity. Overwrites adjacent memory. Swift prevents via array bounds checking.
  • XSS (Web Context): Web views displaying user input as HTML. Attackers inject `
🔍 Input Validation Rule: Validate at entry point. Don't rely on downstream functions to validate. Defense in depth: validate at multiple layers. Makes finding vulnerabilities harder for attackers.

🚨 Hardcoded Secrets Vulnerability

Never hardcode sensitive data: API keys, passwords, encryption keys, database credentials. If hardcoded, anyone with app code access gets secrets. Attackers decompile apps extracting hardcoded secrets.

Hardcoded Secrets Risks

  • App Code Exposure: Apps can be downloaded, decompiled, analyzed. Hardcoded secrets easily extracted.
  • Git History Leakage: Developers commit secrets to Git. Even if removed later, Git history contains secrets. Attackers access Git finding old commits.
  • Build Artifacts: Compiled binaries contain hardcoded strings. Reverse engineering reveals secrets.
  • Logs Exposure: Secrets logged for debugging. Logs stored on device, transmitted to servers. Compromised logs reveal secrets.
  • Screenshot Inclusion: Screenshots containing sensitive data included in app documentation. Anyone with documentation gets secrets.

Secure Secret Management

  • Environment Variables: Secrets passed via environment variables at build/runtime. Not in code.
  • Configuration Files: Secrets in separate config files, not compiled into app. Config read at runtime.
  • Remote Configuration: Fetch secrets from secure server at runtime. Server authenticates app before providing secrets.
  • Hardware-Backed Storage: Secrets stored in Secure Enclave/TEE. Inaccessible even if app compromised.
  • Secret Rotation: Periodically change secrets. Limits damage if old secret compromised.
# ❌ BAD - Hardcoded
let apiKey = "sk_live_abc123xyz"
let databasePassword = "SecurePass123"

# ✅ GOOD - Environment
let apiKey = ProcessInfo.processInfo.environment["API_KEY"]
let pass = fetchSecretFromKeychain("database_pass")
🔐 Secrets Rule: Never hardcode anything sensitive. Use Keychain for credential storage on device. Use secure backend APIs for runtime secret distribution. Treat all code as potentially compromised.

🔑 Secure Storage: Keychain Awareness

iOS Keychain: secure credential storage. Encrypted at rest using device encryption key. Accessible only by app that stored it (or apps with entitlements). Secure alternative to UserDefaults.

Keychain Fundamentals

  • Hardware Encryption: Keychain uses device encryption key. Data encrypted at device level. Even if device storage accessed, data remains encrypted.
  • Access Control: App that stores credential can retrieve it. Other apps blocked by default. Keychain Access Groups allow sharing between apps.
  • Availability: Keychain data available only when device unlocked. Requires biometric/passcode authentication.
  • Persistent Storage: Survives app uninstall (unless explicitly cleared). Useful for authentication tokens lasting beyond app session.
  • iCloud Sync: Optional iCloud sync for credentials. Synced securely across user's devices. Requires user permission.

What to Store in Keychain

  • Authentication Tokens: OAuth tokens, JWT tokens. Must survive app restarts.
  • Passwords: User passwords for app login. Never store plaintext.
  • Encryption Keys: App-specific encryption keys. Master encryption keys especially.
  • API Keys: Third-party API keys not part of app logic. Protect like passwords.
  • PII: Personally identifiable info (email, SSN). Encrypt with Keychain.

What NOT to Store in Keychain

  • Large Blobs: Keychain designed for small data (passwords, tokens). Large files use encrypted FileProtection instead.
  • Cache Data: Non-sensitive cache stored in NSCache or temp directories.
  • Public Data: Non-sensitive data stored in UserDefaults or Core Data.
# Store in Keychain
let password = "UserPassword123"
let passwordData = password.data(using: .utf8)!
let query: [String: Any] = [
  kSecClass: kSecClassGenericPassword,
  kSecAttrAccount: "user@example.com",
  kSecValueData: passwordData
]
SecItemAdd(query as CFDictionary, nil)

# Retrieve from Keychain
var result: CFTypeRef?
SecItemCopyMatching(query as CFDictionary, &result)
💼 Keychain Best Practice: Store all credentials in Keychain. Never UserDefaults for sensitive data. Implement proper access control. Use biometric authentication when possible for additional security layer.
Validation Layers
Validate input at multiple points: client-side Swift validation + server-side validation. Defense in depth prevents bypass attacks.
🔒
Secure Defaults
Safe defaults for security settings. Require opt-in for less secure options. Default to most restrictive permissions.
⚠️
Error Handling
Never expose sensitive error details. "Invalid credentials" not "User not found" (leaks if username exists). Generic errors to users, logging for debugging.
🔐
Encryption Standard
Use CryptoKit for encryption. Avoid custom crypto. Standard algorithms (AES-256) thoroughly tested. Custom implementations often flawed.
🛡️
Memory Clearing
Clear sensitive data from memory after use. Sensitive strings, passwords, keys. Prevents memory disclosure attacks.
📡
TLS Only
All network communication over HTTPS/TLS. Enable certificate pinning for API endpoints. Prevents man-in-the-middle attacks.

Application Hardening Concepts

Protecting apps from reverse engineering and tampering

🔐 Code Obfuscation Awareness

Code obfuscation: making code difficult to understand/reverse engineer. Attackers decompile apps extracting logic, stealing algorithms, finding vulnerabilities. Obfuscation raises barrier to entry.

Obfuscation Techniques

  • Name Mangling: Rename variables/functions to meaningless names: `a, b, f1, f2`. Makes decompiled code harder to understand.
  • Control Flow Obfuscation: Add dummy code, unnecessary branching. Makes control flow analysis harder.
  • String Encryption: Encrypt hardcoded strings, decrypt at runtime. Prevents simple string searching in binary.
  • Code Flattening: Remove loop/control structures, replace with gotos. Makes logic flow unclear.
  • API Hiding: Hide API calls behind indirection. Direct API calls easily found in reversing, indirection makes finding harder.
  • Junk Code: Add meaningless code not affecting logic. Increases binary size, obfuscates real logic.

Obfuscation Limitations

  • Not Unbreakable: Obfuscation only raises difficulty, determined attackers can still deobfuscate.
  • Runtime Analysis: Obfuscated code obvious when running. Debuggers show real behavior regardless of obfuscation.
  • Performance Cost: Obfuscation adds overhead. Heavy obfuscation can slow apps significantly.
  • Debug Difficulty: Developers debugging obfuscated code have harder time. Need to balance security with debuggability.
🎯 Obfuscation Strategy: Obfuscate sensitive algorithms only. Don't obfuscate entire app (performance impact). Combine with other protections: runtime checks, certificate pinning, secure backend. Obfuscation alone insufficient.

🛡️ Runtime Integrity Checks (High-Level)

Runtime checks: app verifying its own integrity while running. Detects tampering, jailbreaks, debuggers. Stops compromised apps from executing sensitive code.

Runtime Integrity Checks

  • Code Signature Verification: App verifies its code signature hasn't been tampered. Validates all bundle contents match signature.
  • Checksum Validation: Calculate checksum of app binary, compare with expected. Mismatch indicates binary tampering.
  • Jailbreak Detection: Check for jailbreak indicators: Cydia app presence, unusual file access, runtime modifications. Block execution on jailbroken devices.
  • Debugger Detection: Detect attached debuggers. Attackers use debuggers stepping through code, modifying variables. Block/crash if debugged.
  • Instrumentation Detection: Detect frida/xposed runtime instrumentation. Attackers inject code at runtime changing behavior.
  • File System Integrity: Monitor app bundle files for changes. Detect injected code or modified resources.
  • API Hooking Detection: Detect if critical APIs hooked. Hooked APIs indicate attacker trying to intercept calls.

Integrity Check Implementation

  • Early Validation: Check integrity early in app launch. Before loading sensitive code.
  • Continuous Checks: Periodic integrity checks during app execution. Not just at startup.
  • Fail Secure: If integrity check fails, don't try to recover. App should crash/terminate. Don't continue with potentially compromised app.
  • Anti-Hooking: Store sensitive functions in memory at runtime. Hook attacks target code at startup, runtime storage avoids some hooks.
  • Self-Debugging: App attaches debugger to itself. Prevents external debuggers attaching (only one debugger allowed).
⚠️ Integrity Check Caution: Integrity checks slow app startup. Balance security with UX. Don't block all users based on single integrity failure (legitimate causes exist). Use for sensitive operations (payment, authentication) rather than startup block.
🔒
Certificate Pinning
App stores expected certificate. Validates server certificate matches. Prevents MITM attacks even if certificate authority compromised.
🚫
Disable Debugging
Release builds should disable debugging capabilities. No NSLog in production. Remove debug symbols. Reduces attack surface.
🔍
Threat Modeling
Identify potential threats to app. What attacks possible? What data at risk? Prioritize hardening based on threats.
Anti-Tampering
Detect app modifications. Modified app behaves unexpectedly. Can fail gracefully or crash, preventing exploits.
🛡️
Sandboxing Awareness
App runs in sandbox. Design around sandbox restrictions. Request minimum permissions needed. Defense in depth.
📊
Security Testing
Test security controls. Penetration testing, fuzzing input, attempting bypass. Professional testers find vulnerabilities early.

Secure Development Lifecycle

Integrating security throughout development

🎯 Threat Modeling Basics

Threat modeling: systematic process identifying potential threats to application. "What could go wrong?" framework. Enables prioritizing security efforts based on actual risks.

Threat Modeling Process

  • Asset Identification: What does app protect? User data types? Credentials? Payment info? Intellectual property?
  • Threat Identification: What attacks threaten these assets? Who attacks? (competitors, malicious users, hackers). What's their capability?
  • Vulnerability Identification: What weaknesses enable threats? Missing input validation? Weak encryption? Poor authentication?
  • Risk Assessment: Likelihood × Impact = Risk. High likelihood + high impact = high risk. Prioritize addressing high-risk items.
  • Mitigation Planning: For each risk, what controls reduce risk? Encryption, authentication, rate limiting, etc.
  • Implementation Verification: Build, implement, verify controls actually reduce identified risks. Test threat scenarios.

Common Threat Categories (STRIDE)

  • Spoofing: Attacker pretends to be legitimate user/app. Mitigated by authentication.
  • Tampering: Attacker modifies data in transit or at rest. Mitigated by encryption, signatures, integrity checks.
  • Repudiation: Attacker denies actions they took. Mitigated by logging, audit trails.
  • Information Disclosure: Sensitive data exposed. Mitigated by encryption, access controls.
  • Denial of Service: Attacker prevents legitimate access. Mitigated by rate limiting, resource controls.
  • Elevation of Privilege: Attacker gains unauthorized elevated access. Mitigated by principle of least privilege.
🔍 Threat Modeling Mindset: Think like attacker. "How would I attack this app?" Framework-based approach (STRIDE, PASTA) ensures systematic coverage. Document threats/mitigations. Revisit after major changes. Threat modeling informs all other security activities.

📱 App Review Process Awareness

Apple's App Store review: gatekeeping security. Apps reviewed before release ensuring policy compliance, no obvious malware. Understanding review process enables building compliant secure apps.

App Review Criteria

  • Functionality: App must work as described. No crashes, hangs, broken features.
  • Performance: Apps must run smoothly. Excessive battery drain, memory leaks flagged.
  • Privacy Compliance: Privacy policy required. Must disclose data collection. Permissions must match actual collection.
  • Data Security: Sensitive data encrypted. No hardcoded credentials. Secure storage practices.
  • Network Security: HTTPS/TLS required for all network communication. Certificate pinning encouraged.
  • Code Quality: No obvious exploitable bugs. Reviewers attempt known exploits (buffer overflows, format strings).
  • Third-Party SDKs: SDKs scanned for suspicious behavior. SDKs collecting excessive data flagged.
  • Permissions Justification: Every permission requested must be justified. Requesting camera without camera feature = rejection.

Common Rejection Reasons

  • Vague Privacy Policy: Privacy policy must clearly explain data practices. Generic policy = rejection.
  • Unnecessary Permissions: Requesting camera, microphone, location without justified use = rejection.
  • Cryptic Code: Highly obfuscated code flagged as potentially malicious. Some obfuscation OK, extreme obfuscation = rejection.
  • Suspicious Behavior: Apps calling unusual system functions, accessing restricted APIs flagged.
  • Outdated SDK: Using very old SDKs with known vulnerabilities = rejection.
  • Test Content: Leaving test accounts, debug code in submission = rejection.
Review Success: Clear, specific privacy policy. Justifiable permissions requests. Clean, professional code. Working features. Modern SDKs. Secure practices. Most security-first apps pass review first try. Violations delay or prevent release.

🔄 Secure Development Lifecycle (SDLC)

Secure SDLC: integrating security into every development phase. Not bolting security on at end. Security from design through deployment, maintenance.

SDLC Phases

  • Requirements: Define security requirements upfront. What data sensitive? What attacks prevent? Requirements drive design.
  • Design: Threat model design. Identify security controls needed. Architecture supporting security (cryptography, authentication).
  • Development: Code securely using secure coding practices. Input validation, error handling, crypto correctly.
  • Testing: Security testing: penetration testing, fuzzing, vulnerability scanning. Find vulnerabilities before release.
  • Deployment: Secure deployment process. Code signing, integrity verification. Secure configuration.
  • Maintenance: Monitor for vulnerabilities. Security patches deployed quickly. Respond to incidents.

Security Best Practices in SDLC

  • Security Training: Developers learn secure coding, common vulnerabilities, security tools.
  • Code Review: Security-focused code review. Reviewers check for vulnerabilities before merging.
  • Static Analysis: Automated tools scanning code finding common vulnerabilities (unused variables, potential overflow).
  • Dynamic Testing: Apps tested while running. Fuzzing random input, monitoring behavior.
  • Dependency Management: Track third-party libraries. Update when security patches released. Scan for known vulnerabilities.
  • Incident Response: Plan for security incidents. If vulnerability discovered post-release, rapid patch deployment.
🎓 SDLC Principle: Security is everyone's responsibility. Developers, testers, product managers, operations all play roles. Security integrated from day one, not afterthought. Secure apps built, not secured after development.
📋
Security Checklist
Comprehensive security checklist before release. Input validation? Encryption? Authentication? Permissions justified? All checked.
🔍
Penetration Testing
Professional testers attempt to break app. Find vulnerabilities developers missed. Fixes deployed before release.
🛠️
Security Tools
Static analysis tools, dynamic testing tools, dependency scanners. Automate vulnerability detection. Integrate with CI/CD.
📊
Metrics & Monitoring
Track security metrics: vulnerabilities found, time to patch, test coverage. Monitor production apps for anomalies.
🚀
Continuous Deployment
Automated security testing in CI/CD pipeline. Vulnerabilities caught early. Fixes deployed rapidly when found.
📢
Responsible Disclosure
Report vulnerabilities responsibly. Give developers time to patch before public disclosure. Protects users.
🎓
Module 2 Complete
Congratulations on mastering Secure Coding & Application Hardening!

Knowledge Achieved:
✓ Secure Swift coding practices
✓ Input validation mindset
✓ Secure credential storage
✓ Keychain integration
✓ Code obfuscation concepts
✓ Runtime integrity checks
✓ Threat modeling basics
✓ App Store compliance
✓ Secure SDLC integration

Ready for Module 3: Malware Defense
📝 Development Complete - Next: Advanced Defense