Client-Side Security Monitoring

Client-Side Security Monitoring

Mobile applications must implement client-side monitoring carefully to balance security visibility with performance and privacy.

iOS Security Monitoring Implementation:

// iOS - Comprehensive security monitoring
import Foundation
import os.log
import CryptoKit

class SecurityMonitoringService {
    
    static let shared = SecurityMonitoringService()
    private let securityLog = OSLog(subsystem: "com.app.security", category: "monitoring")
    private let eventQueue = DispatchQueue(label: "security.monitoring", qos: .utility)
    private var eventBuffer: [SecurityEvent] = []
    private let bufferLimit = 100
    
    // Security event types
    enum SecurityEventType: String, CaseIterable {
        case authenticationFailure = "auth_failure"
        case authenticationSuccess = "auth_success"
        case suspiciousActivity = "suspicious_activity"
        case jailbreakDetected = "jailbreak_detected"
        case debuggerAttached = "debugger_attached"
        case certificatePinningFailure = "cert_pinning_failure"
        case tamperingDetected = "tampering_detected"
        case dataExfiltrationAttempt = "data_exfiltration"
        case maliciousPayload = "malicious_payload"
        case privilegeEscalation = "privilege_escalation"
    }
    
    // Monitor authentication events
    func monitorAuthentication() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleAuthEvent),
            name: .authenticationStatusChanged,
            object: nil
        )
        
        // Monitor biometric authentication
        BiometricAuthObserver.shared.onAuthAttempt = { [weak self] result in
            self?.logSecurityEvent(
                type: result.success ? .authenticationSuccess : .authenticationFailure,
                details: [
                    "method": "biometric",
                    "error": result.error?.localizedDescription ?? ""
                ],
                severity: result.success ? .info : .warning
            )
        }
    }
    
    // Runtime security monitoring
    func startRuntimeMonitoring() {
        // Jailbreak detection
        Timer.scheduledTimer(withTimeInterval: 300, repeats: true) { [weak self] _ in
            if JailbreakDetector.isJailbroken() {
                self?.handleSecurityThreat(.jailbreakDetected)
            }
        }
        
        // Debugger detection
        DispatchQueue.global().async { [weak self] in
            while true {
                if DebuggerDetector.isDebuggerAttached() {
                    self?.handleSecurityThreat(.debuggerAttached)
                }
                Thread.sleep(forTimeInterval: 5)
            }
        }
        
        // Hook detection
        startHookDetection()
    }
    
    // Network security monitoring
    class NetworkSecurityMonitor: URLProtocol {
        
        override class func canInit(with request: URLRequest) -> Bool {
            return true
        }
        
        override class func canonicalRequest(for request: URLRequest) -> URLRequest {
            // Monitor for suspicious requests
            SecurityMonitoringService.shared.analyzeRequest(request)
            return request
        }
        
        override func startLoading() {
            // Monitor actual network traffic
            let task = URLSession.shared.dataTask(with: request) { [weak self] data, response, error in
                guard let self = self else { return }
                
                // Analyze response
                if let httpResponse = response as? HTTPURLResponse {
                    SecurityMonitoringService.shared.analyzeResponse(
                        httpResponse,
                        data: data,
                        error: error
                    )
                }
                
                // Forward response
                if let data = data {
                    self.client?.urlProtocol(self, didLoad: data)
                }
                
                if let response = response {
                    self.client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
                }
                
                if let error = error {
                    self.client?.urlProtocol(self, didFailWithError: error)
                } else {
                    self.client?.urlProtocolDidFinishLoading(self)
                }
            }
            
            task.resume()
        }
        
        override func stopLoading() {
            // Clean up
        }
    }
    
    // Behavioral analysis
    class BehaviorAnalyzer {
        private var userBehaviorProfile = UserBehaviorProfile()
        private let anomalyDetector = AnomalyDetector()
        
        func analyzeUserBehavior(event: UserEvent) {
            // Update behavior profile
            userBehaviorProfile.addEvent(event)
            
            // Check for anomalies
            if let anomaly = anomalyDetector.detectAnomaly(
                event: event,
                profile: userBehaviorProfile
            ) {
                SecurityMonitoringService.shared.logSecurityEvent(
                    type: .suspiciousActivity,
                    details: [
                        "anomaly_type": anomaly.type.rawValue,
                        "confidence": anomaly.confidence,
                        "description": anomaly.description
                    ],
                    severity: anomaly.severity
                )
            }
        }
        
        // Machine learning-based anomaly detection
        func trainAnomalyDetectionModel() {
            let trainingData = collectTrainingData()
            
            // Use Core ML for on-device anomaly detection
            let model = try? UserBehaviorAnomalyDetector(
                configuration: MLModelConfiguration()
            )
            
            anomalyDetector.updateModel(model)
        }
    }
    
    // Security event logging
    func logSecurityEvent(
        type: SecurityEventType,
        details: [String: Any],
        severity: SecuritySeverity
    ) {
        let event = SecurityEvent(
            id: UUID().uuidString,
            timestamp: Date(),
            type: type,
            details: details,
            severity: severity,
            deviceInfo: collectDeviceInfo(),
            appInfo: collectAppInfo()
        )
        
        eventQueue.async { [weak self] in
            self?.processSecurityEvent(event)
        }
    }
    
    private func processSecurityEvent(_ event: SecurityEvent) {
        // Add to buffer
        eventBuffer.append(event)
        
        // Local logging
        os_log(
            "%{public}@: %{public}@",
            log: securityLog,
            type: event.severity.osLogType,
            event.type.rawValue,
            event.details.description
        )
        
        // Check if immediate reporting needed
        if event.severity == .critical || eventBuffer.count >= bufferLimit {
            reportSecurityEvents()
        }
    }
    
    // Secure event transmission
    private func reportSecurityEvents() {
        guard !eventBuffer.isEmpty else { return }
        
        let events = eventBuffer
        eventBuffer.removeAll()
        
        // Encrypt events
        let encryptedPayload = encryptEvents(events)
        
        // Send to security backend
        SecurityAPIClient.shared.reportEvents(encryptedPayload) { [weak self] result in
            switch result {
            case .success:
                // Successfully reported
                break
            case .failure(let error):
                // Re-queue events for retry
                self?.eventQueue.async {
                    self?.eventBuffer.insert(contentsOf: events, at: 0)
                }
                os_log("Failed to report security events: %{public}@", 
                       log: self?.securityLog ?? .default,
                       type: .error,
                       error.localizedDescription)
            }
        }
    }
    
    private func encryptEvents(_ events: [SecurityEvent]) -> Data {
        let encoder = JSONEncoder()
        encoder.dateEncodingStrategy = .iso8601
        
        guard let jsonData = try? encoder.encode(events) else {
            return Data()
        }
        
        // Encrypt with app-specific key
        let key = getSecurityReportingKey()
        guard let sealedBox = try? AES.GCM.seal(jsonData, using: key) else {
            return Data()
        }
        
        return sealedBox.combined ?? Data()
    }
}

// Security event structure
struct SecurityEvent: Codable {
    let id: String
    let timestamp: Date
    let type: SecurityMonitoringService.SecurityEventType
    let details: [String: Any]
    let severity: SecuritySeverity
    let deviceInfo: DeviceInfo
    let appInfo: AppInfo
    
    struct DeviceInfo: Codable {
        let deviceId: String
        let model: String
        let osVersion: String
        let isJailbroken: Bool
        let isVPNActive: Bool
    }
    
    struct AppInfo: Codable {
        let version: String
        let buildNumber: String
        let installDate: Date
        let lastUpdateDate: Date
    }
}

enum SecuritySeverity: String, Codable {
    case info, warning, error, critical
    
    var osLogType: OSLogType {
        switch self {
        case .info: return .info
        case .warning: return .default
        case .error: return .error
        case .critical: return .fault
        }
    }
}

Android Security Monitoring Implementation:

// Android - Production security monitoring
class SecurityMonitoringService(private val context: Context) {
    
    companion object {
        private const val TAG = "SecurityMonitoring"
        private const val BUFFER_SIZE = 100
        private const val REPORT_INTERVAL = 5 * 60 * 1000L // 5 minutes
    }
    
    private val securityEventBuffer = Collections.synchronizedList(
        mutableListOf<SecurityEvent>()
    )
    private val analyticsEngine = SecurityAnalyticsEngine(context)
    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    
    init {
        startMonitoring()
    }
    
    private fun startMonitoring() {
        // Start all monitoring components
        startAuthenticationMonitoring()
        startNetworkMonitoring()
        startAppIntegrityMonitoring()
        startBehaviorMonitoring()
        startPeriodicReporting()
    }
    
    // Authentication monitoring
    private fun startAuthenticationMonitoring() {
        AuthenticationManager.getInstance().addAuthListener { event ->
            when (event) {
                is AuthEvent.LoginAttempt -> {
                    logSecurityEvent(
                        SecurityEvent(
                            type = if (event.success) EventType.AUTH_SUCCESS else EventType.AUTH_FAILURE,
                            timestamp = System.currentTimeMillis(),
                            details = mapOf(
                                "method" to event.method,
                                "user_id" to event.userId.hashCode().toString(),
                                "ip_address" to event.ipAddress
                            ),
                            severity = if (event.success) Severity.INFO else Severity.WARNING
                        )
                    )
                    
                    // Check for brute force attempts
                    if (detectBruteForce(event.userId)) {
                        handleSecurityIncident(
                            SecurityIncident(
                                type = IncidentType.BRUTE_FORCE,
                                severity = Severity.HIGH,
                                userId = event.userId
                            )
                        )
                    }
                }
                
                is AuthEvent.SessionExpired -> {
                    logSecurityEvent(
                        SecurityEvent(
                            type = EventType.SESSION_EXPIRED,
                            timestamp = System.currentTimeMillis(),
                            severity = Severity.INFO
                        )
                    )
                }
            }
        }
    }
    
    // Network security monitoring
    private fun startNetworkMonitoring() {
        // OkHttp interceptor for monitoring
        val networkMonitorInterceptor = object : Interceptor {
            override fun intercept(chain: Interceptor.Chain): Response {
                val request = chain.request()
                val startTime = System.currentTimeMillis()
                
                // Pre-request analysis
                analyzeOutgoingRequest(request)
                
                return try {
                    val response = chain.proceed(request)
                    val duration = System.currentTimeMillis() - startTime
                    
                    // Post-response analysis
                    analyzeResponse(request, response, duration)
                    
                    response
                } catch (e: Exception) {
                    // Network failure analysis
                    analyzeNetworkFailure(request, e)
                    throw e
                }
            }
        }
        
        // Certificate pinning monitor
        CertificatePinningMonitor.setListener { host, error ->
            logSecurityEvent(
                SecurityEvent(
                    type = EventType.CERT_PINNING_FAILURE,
                    timestamp = System.currentTimeMillis(),
                    details = mapOf(
                        "host" to host,
                        "error" to error.message
                    ),
                    severity = Severity.CRITICAL
                )
            )
            
            // Potential MITM attack
            handleSecurityIncident(
                SecurityIncident(
                    type = IncidentType.POTENTIAL_MITM,
                    severity = Severity.CRITICAL,
                    details = mapOf("host" to host)
                )
            )
        }
    }
    
    // App integrity monitoring
    private fun startAppIntegrityMonitoring() {
        scope.launch {
            while (isActive) {
                // Check app signature
                if (!verifyAppSignature()) {
                    handleSecurityIncident(
                        SecurityIncident(
                            type = IncidentType.APP_TAMPERING,
                            severity = Severity.CRITICAL
                        )
                    )
                }
                
                // Check for root
                if (RootDetector.isDeviceRooted()) {
                    logSecurityEvent(
                        SecurityEvent(
                            type = EventType.ROOT_DETECTED,
                            timestamp = System.currentTimeMillis(),
                            severity = Severity.HIGH
                        )
                    )
                }
                
                // Check for debugging
                if (Debug.isDebuggerConnected()) {
                    handleSecurityIncident(
                        SecurityIncident(
                            type = IncidentType.DEBUGGER_ATTACHED,
                            severity = Severity.HIGH
                        )
                    )
                }
                
                // Check for hooks
                if (detectRuntimeHooks()) {
                    handleSecurityIncident(
                        SecurityIncident(
                            type = IncidentType.RUNTIME_MANIPULATION,
                            severity = Severity.CRITICAL
                        )
                    )
                }
                
                delay(60000) // Check every minute
            }
        }
    }
    
    // Behavioral monitoring
    private fun startBehaviorMonitoring() {
        val behaviorAnalyzer = UserBehaviorAnalyzer(context)
        
        // Monitor app usage patterns
        ActivityLifecycleMonitor.getInstance().addLifecycleCallback { activity, stage ->
            behaviorAnalyzer.recordActivity(
                UserActivity(
                    activityName = activity.javaClass.simpleName,
                    stage = stage,
                    timestamp = System.currentTimeMillis()
                )
            )
        }
        
        // Monitor data access patterns
        DataAccessMonitor.setListener { dataType, amount ->
            if (behaviorAnalyzer.isAnomalousDataAccess(dataType, amount)) {
                logSecurityEvent(
                    SecurityEvent(
                        type = EventType.ANOMALOUS_DATA_ACCESS,
                        timestamp = System.currentTimeMillis(),
                        details = mapOf(
                            "data_type" to dataType,
                            "amount" to amount.toString()
                        ),
                        severity = Severity.HIGH
                    )
                )
            }
        }
        
        // Monitor permission usage
        PermissionMonitor.trackPermissionUsage { permission, frequency ->
            if (behaviorAnalyzer.isAnomalousPermissionUsage(permission, frequency)) {
                logSecurityEvent(
                    SecurityEvent(
                        type = EventType.SUSPICIOUS_PERMISSION_USE,
                        timestamp = System.currentTimeMillis(),
                        details = mapOf(
                            "permission" to permission,
                            "frequency" to frequency.toString()
                        ),
                        severity = Severity.MEDIUM
                    )
                )
            }
        }
    }
    
    // Real-time threat detection
    inner class ThreatDetectionEngine {
        private val threatPatterns = loadThreatPatterns()
        private val mlModel = loadMLModel()
        
        fun analyzeForThreats(event: SecurityEvent): ThreatAssessment {
            // Rule-based detection
            val ruleBasedThreats = threatPatterns
                .filter { pattern -> pattern.matches(event) }
                .map { pattern -> 
                    Threat(
                        type = pattern.threatType,
                        confidence = pattern.confidence,
                        description = pattern.description
                    )
                }
            
            // ML-based detection
            val mlThreats = mlModel.predict(event.toFeatureVector())
                .filter { prediction -> prediction.confidence > 0.7 }
                .map { prediction ->
                    Threat(
                        type = prediction.threatType,
                        confidence = prediction.confidence,
                        description = "ML-detected: ${prediction.threatType}"
                    )
                }
            
            // Combine and deduplicate
            val allThreats = (ruleBasedThreats + mlThreats)
                .distinctBy { it.type }
                .sortedByDescending { it.confidence }
            
            return ThreatAssessment(
                threats = allThreats,
                overallRisk = calculateOverallRisk(allThreats),
                recommendedActions = determineActions(allThreats)
            )
        }
    }
    
    // Incident response
    private fun handleSecurityIncident(incident: SecurityIncident) {
        scope.launch {
            // Immediate response
            when (incident.type) {
                IncidentType.BRUTE_FORCE -> {
                    // Lock account
                    AccountManager.lockAccount(incident.userId)
                }
                
                IncidentType.APP_TAMPERING -> {
                    // Disable sensitive features
                    FeatureManager.disableSensitiveFeatures()
                    
                    // Alert user
                    showSecurityAlert("Security Warning", 
                        "App integrity compromised. Please reinstall from official store.")
                }
                
                IncidentType.POTENTIAL_MITM -> {
                    // Terminate all network connections
                    NetworkManager.terminateAllConnections()
                    
                    // Force re-authentication
                    AuthenticationManager.forceReauthentication()
                }
                
                IncidentType.DATA_EXFILTRATION -> {
                    // Block data access
                    DataAccessManager.blockAllAccess()
                    
                    // Wipe sensitive data
                    SecureStorage.wipeAll()
                }
            }
            
            // Report incident
            reportSecurityIncident(incident)
            
            // Update threat model
            ThreatModelManager.updateModel(incident)
        }
    }
    
    // Secure reporting
    private suspend fun reportSecurityEvents() {
        if (securityEventBuffer.isEmpty()) return
        
        val events = securityEventBuffer.toList()
        securityEventBuffer.clear()
        
        try {
            // Prepare secure payload
            val payload = SecurityPayload(
                events = events,
                deviceFingerprint = generateDeviceFingerprint(),
                timestamp = System.currentTimeMillis(),
                signature = signPayload(events)
            )
            
            // Encrypt payload
            val encryptedPayload = SecurityEncryption.encrypt(payload)
            
            // Send to security backend
            val response = SecurityAPI.reportEvents(encryptedPayload)
            
            if (response.isSuccessful) {
                // Process server instructions
                response.body()?.let { instructions ->
                    processServerInstructions(instructions)
                }
            } else {
                // Re-queue events
                securityEventBuffer.addAll(events)
            }
        } catch (e: Exception) {
            Log.e(TAG, "Failed to report security events", e)
            // Re-queue events
            securityEventBuffer.addAll(events)
        }
    }
    
    data class SecurityEvent(
        val type: EventType,
        val timestamp: Long,
        val details: Map<String, String> = emptyMap(),
        val severity: Severity
    )
    
    enum class EventType {
        AUTH_SUCCESS,
        AUTH_FAILURE,
        SESSION_EXPIRED,
        CERT_PINNING_FAILURE,
        ROOT_DETECTED,
        ANOMALOUS_DATA_ACCESS,
        SUSPICIOUS_PERMISSION_USE,
        NETWORK_ANOMALY
    }
}