# Insecure Logging

## **📋 Índice**

1. [Fundamentos do Logging no Android](#-fundamentos-do-logging-no-android)
2. [Métodos de Logging](#-métodos-de-logging)
3. [Mecanismos de Ataque](#-mecanismos-de-ataque)
4. [Técnicas de Exploração](#-técnicas-de-exploração)
5. [Vetores de Ataque](#-vetores-de-ataque)
6. [Ferramentas de Exploração](#-ferramentas-de-exploração)
7. [Impacto e Consequências](#-impacto-e-consequências)
8. [Detecção e Monitoramento](#-detecção-e-monitoramento)
9. [Mitigações e Hardening](#-mitigações-e-hardening)
10. [Checklists de Segurança](#-checklists-de-segurança)

***

## 🔍 **Fundamentos do Logging no Android**

### **O que é Insecure Logging?**

**Insecure Logging** refere-se à prática de registrar informações sensíveis em logs do sistema Android (logcat), que podem ser acessadas por outros aplicativos ou por um atacante com acesso físico ao dispositivo. Isso inclui senhas, tokens, dados pessoais, informações financeiras ou qualquer dado confidencial que vaze para os logs.

### **Princípio de Funcionamento**

```mermaid
graph TD
    subgraph "Aplicação"
        A[App] --> B[Log.d()]
        A --> C[Log.i()]
        A --> D[Log.e()]
        A --> E[System.out]
    end
    
    subgraph "Sistema"
        B --> F[Logcat Buffer]
        C --> F
        D --> F
        E --> F
    end
    
    subgraph "Acesso"
        F --> G[adb logcat]
        F --> H[Outros Apps]
        F --> I[Análise Forense]
        F --> J[Logs Persistidos]
    end
    
    subgraph "Consequências"
        G --> K[Vazamento de Dados]
        H --> K
        I --> K
        J --> K
    end
    
    style A fill:#ffcc99
    style F fill:#ff9999
    style K fill:#ff3333
```

### **Hierarquia de Logging**

```yaml
Níveis de Log no Android:

  🔴 ERROR (Log.e):
    - Erros que afetam a execução
    - Stack traces completos
    - Pode conter dados sensíveis em exceções

  🟠 WARN (Log.w):
    - Avisos de possíveis problemas
    - Configurações incorretas
    - Dados de debug

  🟡 INFO (Log.i):
    - Informações gerais
    - Fluxo da aplicação
    - Estados do sistema

  🟢 DEBUG (Log.d):
    - Informações de debug
    - Valores de variáveis
    - Dados de entrada/saída

  🔵 VERBOSE (Log.v):
    - Informações extremamente detalhadas
    - Rastreamento completo
    - Dados sensíveis frequentes
```

***

## 📝 **Métodos de Logging**

### **Métodos de Log no Android**

```java
// InsecureLogging.java - Exemplos de logging inseguro

public class InsecureLogging {
    
    private static final String TAG = "MyApp";
    
    // 1. Log de senha
    public void loginUser(String username, String password) {
        // 🔴 NUNCA fazer isso!
        Log.d(TAG, "Login attempt - Username: " + username + ", Password: " + password);
        Log.i(TAG, "User credentials: " + username + "/" + password);
        
        // Processo de login...
    }
    
    // 2. Log de token de autenticação
    public void authenticate(String token) {
        // 🔴 Token exposto
        Log.d(TAG, "Auth token: " + token);
        
        // Verificação...
    }
    
    // 3. Log de dados pessoais
    public void processUserData(User user) {
        // 🔴 Dados pessoais expostos
        Log.i(TAG, "Processing user: " + user.getName());
        Log.d(TAG, "User email: " + user.getEmail());
        Log.v(TAG, "User address: " + user.getAddress());
        Log.w(TAG, "User phone: " + user.getPhone());
        
        // Processamento...
    }
    
    // 4. Log de informações financeiras
    public void processPayment(CreditCard card) {
        // 🔴 Dados de cartão expostos
        Log.d(TAG, "Card number: " + card.getNumber());
        Log.d(TAG, "CVV: " + card.getCvv());
        Log.d(TAG, "Expiry: " + card.getExpiry());
        
        // Processamento...
    }
    
    // 5. Log de exceções com dados sensíveis
    public void riskyOperation(String sensitiveData) {
        try {
            // Operação que pode falhar
            throw new Exception("Error processing: " + sensitiveData);
        } catch (Exception e) {
            // 🔴 Exceção com dados sensíveis
            Log.e(TAG, "Exception occurred", e);
        }
    }
    
    // 6. Log de parâmetros de API
    public void callApi(String apiKey, String secret) {
        // 🔴 Chaves de API expostas
        Log.d(TAG, "API Key: " + apiKey);
        Log.d(TAG, "API Secret: " + secret);
        
        // Chamada de API...
    }
    
    // 7. System.out.println (também vai para logcat)
    public void debugInfo(String data) {
        // 🔴 System.out também é logado
        System.out.println("Debug: " + data);
        System.err.println("Error: " + data);
    }
}
```

### **Logging Seguro**

```java
// SecureLogging.java - Implementação segura

import android.util.Log;

public class SecureLogging {
    
    private static final String TAG = "MyApp";
    private static final boolean IS_DEBUG = BuildConfig.DEBUG;
    
    // 1. Log condicional (apenas debug)
    public static void d(String message) {
        if (IS_DEBUG) {
            // Log apenas em debug, sem dados sensíveis
            Log.d(TAG, message);
        }
    }
    
    // 2. Log seguro de exceções
    public static void e(String message, Throwable tr) {
        if (IS_DEBUG) {
            Log.e(TAG, message, tr);
        } else {
            // Em produção, log sem stack trace
            Log.e(TAG, "Error occurred");
        }
    }
    
    // 3. Redação de dados sensíveis
    public static void logUserAction(String username, String action) {
        if (IS_DEBUG) {
            // Apenas ação, sem dados sensíveis
            Log.d(TAG, "User action: " + action);
        }
    }
    
    // 4. Log de métricas (agregado, não individual)
    public static void logMetric(String metricName, long value) {
        // Métricas anônimas
        Log.i(TAG, metricName + ": " + value);
    }
    
    // 5. Função de redação
    public static String redact(String data) {
        if (data == null) return null;
        if (data.length() <= 8) return "***";
        return data.substring(0, 4) + "***" + data.substring(data.length() - 4);
    }
    
    // 6. Log seguro de autenticação
    public void secureLogin(String username, String password) {
        if (IS_DEBUG) {
            // Apenas username, senha redigida
            Log.d(TAG, "Login attempt - User: " + username);
        }
        // Não logar senha
    }
}
```

***

## ⚔️ **Mecanismos de Ataque**

### **Fluxo de Ataque**

```mermaid
sequenceDiagram
    participant A as Atacante
    participant D as Dispositivo
    participant App as App Alvo

    Note over A,D: 1. Acesso ao dispositivo
    A->>D: Conexão USB
    D->>D: Debug USB habilitado

    Note over A,App: 2. Captura de Logs
    A->>App: adb logcat
    App-->>A: Logs da aplicação

    Note over A,App: 3. Extração de Dados
    A->>A: Analisa logs
    A->>A: Extrai credenciais
    A->>A: Compromete conta
```

### **Vetores de Ataque**

```yaml
Vetores Comuns:

  🔴 Acesso USB:
    - Debug USB habilitado
    - Conexão física ao dispositivo
    - Leitura de logs via ADB

  🔴 Apps Maliciosos:
    - Permissão READ_LOGS (deprecated, mas ainda presente)
    - Acesso a logs de outros apps
    - Extração de dados sensíveis

  🔴 Logs Persistentes:
    - Logs armazenados em disco
    - Acesso via análise forense
    - Backup de logs

  🔴 Exceções:
    - Stack traces com dados sensíveis
    - Mensagens de erro detalhadas
    - Informações de debug

  🔴 System.out/err:
    - Redirecionamento para logcat
    - Uso comum em código legado
    - Fácil de esquecer
```

***

## 🔧 **Técnicas de Exploração**

### **Técnica 1: Monitoramento de Logcat**

```python
#!/usr/bin/env python3
# logcat_monitor.py - Monitoramento de logcat

import subprocess
import re
import sys
import time

class LogcatMonitor:
    """Monitoramento de logcat em tempo real"""
    
    @staticmethod
    def monitor_all_logs(duration=30):
        """Monitorar todos os logs por um período"""
        print(f"[*] Monitorando logcat por {duration}s")
        
        cmd = ['adb', 'logcat', '-v', 'time']
        
        start_time = time.time()
        try:
            process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
            
            while time.time() - start_time < duration:
                line = process.stdout.readline()
                if line:
                    print(line.strip())
                    
        except Exception as e:
            print(f"Erro: {e}")
        finally:
            process.terminate()
    
    @staticmethod
    def filter_by_package(package, duration=30):
        """Filtrar logs por pacote"""
        print(f"[*] Monitorando logs de {package} por {duration}s")
        
        cmd = ['adb', 'logcat', '-v', 'time', '-s', package]
        
        start_time = time.time()
        try:
            process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
            
            while time.time() - start_time < duration:
                line = process.stdout.readline()
                if line:
                    print(line.strip())
                    
        except Exception as e:
            print(f"Erro: {e}")
        finally:
            process.terminate()
    
    @staticmethod
    def search_sensitive_logs(package, keywords):
        """Buscar dados sensíveis nos logs"""
        print(f"[*] Buscando dados sensíveis nos logs de {package}")
        
        cmd = ['adb', 'logcat', '-d', '-s', package]
        result = subprocess.run(cmd, capture_output=True, text=True)
        
        sensitive_lines = []
        
        for line in result.stdout.split('\n'):
            line_lower = line.lower()
            for keyword in keywords:
                if keyword.lower() in line_lower:
                    sensitive_lines.append(line)
                    break
        
        if sensitive_lines:
            print(f"   Encontradas {len(sensitive_lines)} linhas sensíveis:")
            for line in sensitive_lines[:10]:
                print(f"      {line[:150]}")
        else:
            print("   Nenhum dado sensível encontrado")
        
        return sensitive_lines

# Uso
if __name__ == "__main__":
    print("📝 Logcat Monitor")
    print("=" * 60)
    
    if len(sys.argv) > 1:
        LogcatMonitor.search_sensitive_logs(sys.argv[1], 
            ['password', 'token', 'credit', 'ssn', 'secret', 'key', 'auth'])
    else:
        print("Uso: logcat_monitor.py <package>")
        LogcatMonitor.monitor_all_logs(10)
```

### **Técnica 2: Extração de Logs Persistentes**

```bash
#!/bin/bash
# extract_logs.sh - Extração de logs persistentes

# 1. Limpar logs atuais
adb logcat -c

# 2. Executar app e capturar logs
adb logcat -v time -s MyApp > app_logs.txt &

# 3. Executar ações no app
adb shell input tap 500 500
sleep 5

# 4. Parar captura
kill $!

# 5. Analisar logs
grep -i "password\|token\|credit\|secret" app_logs.txt

# 6. Extrair logs de sistema
adb logcat -d -b all > all_logs.txt

# 7. Filtrar por prioridade
adb logcat -d *:E > errors.txt  # Apenas erros
adb logcat -d *:W > warnings.txt # Apenas warnings

# 8. Exportar logs com timestamp
adb logcat -v time -d > logs_$(date +%Y%m%d_%H%M%S).txt
```

### **Técnica 3: Frida Script para Hook de Log**

```javascript
// frida_log_hook.js - Hook de funções de logging

Java.perform(function() {
    console.log("[*] Hooking Logging Functions");
    
    // 1. Hook Log.d
    var Log = Java.use("android.util.Log");
    
    Log.d.overload('java.lang.String', 'java.lang.String').implementation = function(tag, msg) {
        if (isSensitive(msg)) {
            console.log("[!] Sensitive data in Log.d: " + msg);
            // Bloquear log
            return 0;
        }
        console.log("[Log.d] " + tag + ": " + msg);
        return this.d(tag, msg);
    };
    
    // 2. Hook Log.i
    Log.i.overload('java.lang.String', 'java.lang.String').implementation = function(tag, msg) {
        if (isSensitive(msg)) {
            console.log("[!] Sensitive data in Log.i: " + msg);
            // Redact
            msg = redactSensitive(msg);
        }
        console.log("[Log.i] " + tag + ": " + msg);
        return this.i(tag, msg);
    };
    
    // 3. Hook Log.e
    Log.e.overload('java.lang.String', 'java.lang.String', 'java.lang.Throwable').implementation = function(tag, msg, tr) {
        if (isSensitive(msg)) {
            console.log("[!] Sensitive data in Log.e: " + msg);
            msg = "Error occurred (redacted)";
        }
        console.log("[Log.e] " + tag + ": " + msg);
        return this.e(tag, msg, tr);
    };
    
    // 4. Hook System.out.println
    var PrintStream = Java.use("java.io.PrintStream");
    
    PrintStream.println.overload('java.lang.String').implementation = function(str) {
        if (isSensitive(str)) {
            console.log("[!] Sensitive data in System.out: " + str);
            return;
        }
        return this.println(str);
    };
    
    function isSensitive(msg) {
        var sensitivePatterns = [
            "password", "token", "credit", "ssn", "secret",
            "api_key", "auth", "private", "confidential"
        ];
        
        var lowerMsg = msg.toLowerCase();
        for (var i = 0; i < sensitivePatterns.length; i++) {
            if (lowerMsg.indexOf(sensitivePatterns[i]) !== -1) {
                return true;
            }
        }
        return false;
    }
    
    function redactSensitive(msg) {
        // Redact passwords
        msg = msg.replace(/password['\"]?\\s*[=:]\\s*['\"]?[^'\"]+['\"]?/gi, "password=***");
        // Redact tokens
        msg = msg.replace(/token['\"]?\\s*[=:]\\s*['\"]?[^'\"]+['\"]?/gi, "token=***");
        // Redact credit cards
        msg = msg.replace(/\\b\\d{13,19}\\b/g, "****-****-****-****");
        return msg;
    }
});
```

### **Técnica 4: Análise de Crash Logs**

```python
#!/usr/bin/env python3
# crash_log_analyzer.py - Análise de logs de crash

import subprocess
import re
import sys

class CrashLogAnalyzer:
    """Análise de logs de crash para dados sensíveis"""
    
    @staticmethod
    def get_crash_logs(package, lines=500):
        """Obter logs de crash do pacote"""
        print(f"[*] Obtendo logs de crash de {package}")
        
        cmd = ['adb', 'logcat', '-d', '-s', 'AndroidRuntime', 'DEBUG']
        result = subprocess.run(cmd, capture_output=True, text=True)
        
        crashes = []
        in_crash = False
        current_crash = []
        
        for line in result.stdout.split('\n'):
            if 'FATAL EXCEPTION' in line or package in line:
                in_crash = True
                current_crash = []
            
            if in_crash:
                current_crash.append(line)
                if 'at ' in line and ')' in line:
                    crashes.append('\n'.join(current_crash))
                    in_crash = False
        
        print(f"   Encontrados {len(crashes)} crashes")
        
        # Analisar cada crash
        for i, crash in enumerate(crashes[:3]):
            print(f"\n   Crash {i+1}:")
            print(f"      {crash[:200]}...")
            
            # Buscar dados sensíveis
            sensitive = re.findall(r'password[=:][^\s]+|token[=:][^\s]+|credit[=:][^\s]+', crash, re.IGNORECASE)
            if sensitive:
                print(f"      ⚠️ Dados sensíveis encontrados: {sensitive}")
        
        return crashes
    
    @staticmethod
    def extract_stack_trace(log_file):
        """Extrair stack trace de arquivo de log"""
        print(f"\n[*] Extraindo stack traces de {log_file}")
        
        try:
            with open(log_file, 'r') as f:
                content = f.read()
            
            # Extrair stack traces
            stack_traces = re.findall(r'java\.lang\.[^\n]+\n(?:\s+at .+\n)+', content)
            
            print(f"   Encontrados {len(stack_traces)} stack traces")
            
            for i, trace in enumerate(stack_traces[:3]):
                print(f"\n   Stack Trace {i+1}:")
                lines = trace.split('\n')
                for line in lines[:5]:
                    print(f"      {line}")
                    
        except Exception as e:
            print(f"   Erro: {e}")

# Uso
if __name__ == "__main__":
    print("📝 Crash Log Analysis")
    print("=" * 60)
    
    if len(sys.argv) > 1:
        CrashLogAnalyzer.get_crash_logs(sys.argv[1])
    else:
        print("Uso: crash_log_analyzer.py <package>")
```

### **Técnica 5: Bypass de Redação de Logs**

```python
#!/usr/bin/env python3
# log_redaction_bypass.py - Bypass de redação de logs

import subprocess
import sys

class LogRedactionBypass:
    """Técnicas para bypass de redação de logs"""
    
    @staticmethod
    def test_encoding_bypass():
        """Testar bypass via encoding"""
        print("[*] Testando bypass de redação via encoding")
        
        payloads = [
            ("password=", "password%3D"),
            ("password=", "password\x3D"),
            ("password=", "password\\x3D"),
            ("password=", "password" + chr(61)),
            ("token=", "token%3D"),
            ("token=", "token\x3D")
        ]
        
        for original, encoded in payloads:
            print(f"   {original} -> {encoded}")
    
    @staticmethod
    def test_chunking_bypass():
        """Testar bypass via chunking"""
        print("\n[*] Testando bypass via chunking")
        
        chunks = [
            "pass", "word=", "secret",
            "tok", "en=", "value",
            "cred", "it=", "1234"
        ]
        
        for chunk in chunks:
            print(f"   {chunk}")
    
    @staticmethod
    def test_case_variation():
        """Testar variação de maiúsculas/minúsculas"""
        print("\n[*] Testando variação de maiúsculas/minúsculas")
        
        variations = [
            "Password",
            "PASSWORD",
            "PaSsWoRd",
            "pAsSwOrD",
            "passWORD"
        ]
        
        for var in variations:
            print(f"   {var}=value")

# Uso
if __name__ == "__main__":
    print("📝 Log Redaction Bypass Techniques")
    print("=" * 60)
    
    LogRedactionBypass.test_encoding_bypass()
    LogRedactionBypass.test_chunking_bypass()
    LogRedactionBypass.test_case_variation()
```

***

## 🔍 **Detecção e Monitoramento**

### **Script de Detecção de Insecure Logging**

```python
#!/usr/bin/env python3
# detect_insecure_logging.py - Detector de logging inseguro

import subprocess
import re
import sys

class InsecureLoggingDetector:
    """Detector de logging inseguro em apps Android"""
    
    @staticmethod
    def check_log_statements(apk_path):
        """Verificar declarações de log no código (análise estática)"""
        print(f"[*] Analisando {apk_path} para declarações de log")
        
        # Usar aapt para extrair informações
        cmd = ['aapt', 'dump', 'strings', apk_path]
        result = subprocess.run(cmd, capture_output=True, text=True)
        
        sensitive_patterns = [
            r'Log\.d\s*\(\s*["\'][^"\']*password',
            r'Log\.i\s*\(\s*["\'][^"\']*token',
            r'Log\.e\s*\(\s*["\'][^"\']*credit',
            r'System\.out\.println\s*\(.*password',
            r'print\s*\(.*token'
        ]
        
        found = []
        for pattern in sensitive_patterns:
            matches = re.findall(pattern, result.stdout, re.IGNORECASE)
            if matches:
                found.extend(matches)
                print(f"   ⚠️ Padrão encontrado: {pattern}")
        
        print(f"   Total de ocorrências suspeitas: {len(found)}")
        return found
    
    @staticmethod
    def check_runtime_logs(package, duration=10):
        """Verificar logs em tempo de execução"""
        print(f"\n[*] Verificando logs em tempo real de {package}")
        
        # Limpar logs
        subprocess.run(['adb', 'logcat', '-c'], capture_output=True)
        
        # Capturar logs
        cmd = ['adb', 'logcat', '-v', 'time', '-s', package]
        
        import time
        start_time = time.time()
        
        try:
            process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
            
            sensitive_lines = []
            while time.time() - start_time < duration:
                line = process.stdout.readline()
                if line:
                    if any(p in line.lower() for p in ['password', 'token', 'credit', 'secret']):
                        sensitive_lines.append(line)
                        print(f"   ⚠️ {line.strip()}")
            
            process.terminate()
            
            print(f"   Total de linhas sensíveis: {len(sensitive_lines)}")
            
        except Exception as e:
            print(f"   Erro: {e}")
    
    @staticmethod
    def check_android_manifest(apk_path):
        """Verificar permissões de log no manifest"""
        print(f"\n[*] Verificando permissões em {apk_path}")
        
        cmd = ['aapt', 'dump', 'badging', apk_path]
        result = subprocess.run(cmd, capture_output=True, text=True)
        
        if 'READ_LOGS' in result.stdout:
            print("   ⚠️ App tem permissão READ_LOGS (pode ler logs de outros apps)")
        
        if 'WRITE_EXTERNAL_STORAGE' in result.stdout:
            print("   ⚠️ App pode salvar logs em storage externo")

# Uso
if __name__ == "__main__":
    print("🔍 Insecure Logging Detection")
    print("=" * 60)
    
    if len(sys.argv) > 1:
        if sys.argv[1].endswith('.apk'):
            InsecureLoggingDetector.check_log_statements(sys.argv[1])
            InsecureLoggingDetector.check_android_manifest(sys.argv[1])
        else:
            InsecureLoggingDetector.check_runtime_logs(sys.argv[1])
    else:
        print("Uso: detect_insecure_logging.py <apk_path|package>")
```

***

## 🛡️ **Mitigações e Hardening**

### **Implementação Segura de Logging**

```java
// SecureLoggingImplementation.java - Implementação segura

import android.util.Log;
import androidx.annotation.NonNull;
import java.util.regex.Pattern;

public class SecureLogger {
    
    private static final String TAG = "MyApp";
    private static final boolean IS_DEBUG = BuildConfig.DEBUG;
    
    // Padrões de dados sensíveis
    private static final Pattern[] SENSITIVE_PATTERNS = {
        Pattern.compile("password[\"']?\\s*[=:]\\s*[\"']?[^\"']+[\"']?", Pattern.CASE_INSENSITIVE),
        Pattern.compile("token[\"']?\\s*[=:]\\s*[\"']?[^\"']+[\"']?", Pattern.CASE_INSENSITIVE),
        Pattern.compile("credit[\"']?\\s*[=:]\\s*[\"']?\\d{13,19}[\"']?", Pattern.CASE_INSENSITIVE),
        Pattern.compile("\\b\\d{3}[-.]?\\d{2}[-.]?\\d{4}\\b"), // SSN
        Pattern.compile("\\b\\d{16}\\b"), // Credit card
        Pattern.compile("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}") // Email
    };
    
    // 1. Log condicional (apenas debug)
    public static void debug(@NonNull String message) {
        if (IS_DEBUG) {
            String sanitized = sanitizeMessage(message);
            Log.d(TAG, sanitized);
        }
    }
    
    // 2. Log informativo
    public static void info(@NonNull String message) {
        if (IS_DEBUG) {
            String sanitized = sanitizeMessage(message);
            Log.i(TAG, sanitized);
        }
    }
    
    // 3. Log de erro seguro
    public static void error(@NonNull String message) {
        String sanitized = sanitizeMessage(message);
        Log.e(TAG, sanitized);
    }
    
    // 4. Log de erro com exceção
    public static void error(@NonNull String message, Throwable tr) {
        if (IS_DEBUG) {
            Log.e(TAG, message, tr);
        } else {
            Log.e(TAG, "Error occurred");
        }
    }
    
    // 5. Sanitização de mensagens
    private static String sanitizeMessage(String message) {
        if (message == null) return null;
        
        String sanitized = message;
        for (Pattern pattern : SENSITIVE_PATTERNS) {
            sanitized = pattern.matcher(sanitized).replaceAll("***");
        }
        return sanitized;
    }
    
    // 6. Funções específicas para dados sensíveis
    public static void logAuthAttempt(String username, boolean success) {
        if (IS_DEBUG) {
            Log.d(TAG, "Auth attempt - User: " + username + ", Success: " + success);
        }
        // Não logar senha
    }
    
    public static void logApiCall(String endpoint) {
        if (IS_DEBUG) {
            Log.d(TAG, "API call to: " + endpoint);
        }
        // Não logar parâmetros sensíveis
    }
    
    // 7. Limitar tamanho do log
    public static void logLongString(String tag, String message) {
        if (message == null) return;
        
        int maxLogSize = 4000;
        for (int i = 0; i <= message.length() / maxLogSize; i++) {
            int start = i * maxLogSize;
            int end = Math.min((i + 1) * maxLogSize, message.length());
            Log.d(tag, message.substring(start, end));
        }
    }
}
```

### **ProGuard Rules para Remover Logs**

```proguard
# proguard-rules.pro - Remover logs em produção

# Remover todas as chamadas de Log
-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
    public static *** i(...);
    public static *** w(...);
    public static *** e(...);
    public static *** wtf(...);
    public static *** println(...);
}

# Remover System.out/err
-assumenosideeffects class java.io.PrintStream {
    public *** println(...);
    public *** print(...);
}

# Remover chamadas de debug
-assumenosideeffects class com.example.SecureLogger {
    public static *** debug(...);
    public static *** info(...);
}
```

### **Build Variants para Logging Seguro**

```gradle
// build.gradle - Configuração de build variants

android {
    buildTypes {
        debug {
            debuggable true
            buildConfigField "boolean", "LOG_ENABLED", "true"
        }
        release {
            debuggable false
            buildConfigField "boolean", "LOG_ENABLED", "false"
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

// Uso no código
if (BuildConfig.LOG_ENABLED) {
    Log.d(TAG, "Debug message only in debug builds");
}
```

***

## 📋 **Checklists de Segurança**

### **Checklist para Desenvolvedores**

* [ ] Não logar senhas, tokens ou dados sensíveis
* [ ] Usar logs apenas em debug builds
* [ ] Sanitizar logs antes de escrever
* [ ] Remover logs em produção (ProGuard)
* [ ] Usar níveis de log apropriados
* [ ] Evitar System.out/err
* [ ] Limitar stack traces em produção

### **Checklist para Pentesters**

* [ ] Monitorar logcat durante execução do app
* [ ] Buscar por palavras-chave sensíveis
* [ ] Analisar crash logs
* [ ] Verificar permissão READ\_LOGS
* [ ] Testar bypass de redação
* [ ] Analisar logs persistentes

***

## 📊 **Conclusão**

```yaml
Insecure Logging:

  🔴 Principais Vetores:
    - Log de credenciais (senhas, tokens)
    - Log de dados pessoais
    - Log de informações financeiras
    - Exceções com dados sensíveis

  🛡️ Mitigações Essenciais:
    - Log apenas em debug
    - Sanitização de logs
    - Remover logs em produção
    - ProGuard para remoção
    - Build variants

  🎯 Prioridade:
    - CRÍTICA: Credenciais em logs
    - ALTA: Dados pessoais
    - MÉDIA: Informações de debug
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/tecnicas/sistemas-operacionais/android/insecure-logging.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
