Sicherheit von Kotlin-Anwendungen: Top-10-Schwachstellen für Anfänger
\n\nKotlin ist eine moderne Programmiersprache, die aktiv für die Entwicklung von Android-Apps, Serverlösungen (Ktor, Spring Boot) und sogar Frontend (Kotlin/JS) eingesetzt wird. Wie jede andere Sprache ist jedoch auch Kotlin anfällig für Schwachstellen, insbesondere wenn der Entwickler noch am Anfang seiner Reise steht. In diesem Artikel analysieren wir die Top-10-Schwachstellen von Kotlin-Anwendungen, die jeder angehende Entwickler kennen sollte. Wir betrachten Codebeispiele und geben praktische Tipps zu deren Behebung.
\n\n1. Ignorieren der Null Safety
\nKotlin ist bekannt für seine sichere Handhabung von Null-Werten (Null Safety). Anfänger verwenden jedoch oft den Operator !! (Not-Null-Assertion), was zu NullPointerException führt.
// Schlecht: Risiko einer NPE\nval name: String? = null\nprintln(name!!.length)\n\n// Gut: sicherer Aufruf\nprintln(name?.length ?: "Name fehlt")\nEmpfehlung: Vermeiden Sie !!. Verwenden Sie den Elvis-Operator (?:) oder let/also.
2. Unsichere Speicherung von Geheimnissen (Hardcoded Secrets)
\nDas Speichern von API-Schlüsseln, Tokens und Passwörtern direkt im Code ist ein grober Fehler. Ein Angreifer kann diese leicht aus der APK-Datei extrahieren.
\n// Schlecht: Token im Code\nval apiToken = "sk-1234567890abcdef"\n\n// Gut: Verwendung von BuildConfig oder NDK\n// In build.gradle: buildConfigField "String", "API_TOKEN", "\\"${apiToken}\\""\nEmpfehlung: Verwenden Sie Umgebungsvariablen, BuildConfig oder einen sicheren Speicher (Android Keystore).
3. SQL-Injection in Android (Room/Exposed)
\nSelbst mit ORM (Object-Relational Mapping) kann eine Injection auftreten, wenn rohe SQL-Abfragen mit String-Konkatenation verwendet werden.
\n// Schlecht: anfällig für Injection\nval query = "SELECT * FROM users WHERE name = '$userInput'"\n\n// Gut: parametrisierte Abfrage\nval query = "SELECT * FROM users WHERE name = ?"\nval cursor = db.rawQuery(query, arrayOf(userInput))\nEmpfehlung: Verwenden Sie immer parametrisierte Abfragen oder sichere APIs (Room @Query mit Parametern).
4. Unsicheres Logging
\nDas Protokollieren sensibler Daten (Passwörter, Kartennummern) in der Produktion kann zu Datenlecks führen.
\n// Schlecht: Protokollierung des Passworts\nLog.d("Auth", "Benutzerpasswort: $password")\n\n// Gut: Nur den Fakt protokollieren\nLog.d("Auth", "Benutzerauthentifizierungsversuch")\nEmpfehlung: Verwenden Sie Log-Level und Filter. Deaktivieren Sie in der Produktion Log.v und Log.d.
5. Falsche Verwendung von SharedPreferences
\nSharedPreferences speichern Daten standardmäßig in einer XML-Datei ohne Verschlüsselung. Bei gerooteten Geräten sind die Daten für Angreifer zugänglich.
// Schlecht: normale SharedPreferences\nval prefs = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE)\n\n// Gut: EncryptedSharedPreferences (AndroidX Security)\nval masterKey = MasterKey.Builder(context)\n .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)\n .build()\nval encryptedPrefs = EncryptedSharedPreferences.create(\n context, "secure_prefs", masterKey,\n EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,\n EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM\n)\nEmpfehlung: Verwenden Sie für vertrauliche Daten EncryptedSharedPreferences oder DataStore mit Verschlüsselung.
6. Schwachstellen bei der Deserialisierung (JSON/Gson/Moshi)
\nBei der Deserialisierung nicht vertrauenswürdiger Daten kann beliebiger Code ausgeführt werden oder Speicherverlust auftreten.
\n// Schlecht: Verwendung von Gson ohne Validierung\nval user = Gson().fromJson(jsonString, User::class.java)\n\n// Gut: Vali