Segurança de aplicações Kotlin: top 10 vulnerabilidades para iniciantes
\n\nKotlin é uma linguagem de programação moderna, amplamente utilizada para o desenvolvimento de aplicações Android, soluções de servidor (Ktor, Spring Boot) e até mesmo frontend (Kotlin/JS). No entanto, como qualquer outra linguagem, Kotlin está sujeita a vulnerabilidades, especialmente se o desenvolvedor está apenas começando sua jornada. Neste artigo, vamos abordar as top 10 vulnerabilidades de aplicações Kotlin que todo desenvolvedor iniciante deve conhecer. Veremos exemplos de código e daremos dicas práticas para corrigi-las.
\n\n1. Ignorar o Null Safety
\nKotlin é conhecido por seu trabalho seguro com valores nulos (Null Safety). No entanto, iniciantes frequentemente usam o operador !! (not-null assertion), o que leva a NullPointerException.
// Ruim: risco de NPE\nval name: String? = null\nprintln(name!!.length)\n\n// Bom: chamada segura\nprintln(name?.length ?: "Nome ausente")\nRecomendação: Evite !!. Use o operador elvis (?:) ou let/also.
2. Armazenamento inseguro de segredos (Hardcoded Secrets)
\nArmazenar chaves de API, tokens e senhas diretamente no código é um erro grave. Um invasor pode facilmente extraí-los do arquivo APK.
\n// Ruim: token no código\nval apiToken = "sk-1234567890abcdef"\n\n// Bom: uso de BuildConfig ou NDK\n// Em build.gradle: buildConfigField "String", "API_TOKEN", "\\"${apiToken}\\""\nRecomendação: Use variáveis de ambiente, BuildConfig ou armazenamento seguro (Android Keystore).
3. Injeções SQL no Android (Room/Exposed)
\nMesmo com ORM (Object-Relational Mapping), é possível permitir injeção se forem usadas consultas SQL brutas com concatenação de strings.
\n// Ruim: vulnerável a injeção\nval query = "SELECT * FROM users WHERE name = '$userInput'"\n\n// Bom: consulta parametrizada\nval query = "SELECT * FROM users WHERE name = ?"\nval cursor = db.rawQuery(query, arrayOf(userInput))\nRecomendação: Sempre use consultas parametrizadas ou APIs seguras (Room @Query com parâmetros).
4. Logging inseguro
\nRegistrar dados sensíveis (senhas, números de cartão) em produção pode levar ao vazamento de informações.
\n// Ruim: registrar senha\nLog.d("Auth", "User password: $password")\n\n// Bom: registrar apenas o fato\nLog.d("Auth", "User authentication attempt")\nRecomendação: Use níveis de logging e filtros. Em produção, desative Log.v e Log.d.
5. Uso incorreto de SharedPreferences
\nSharedPreferences por padrão armazenam dados em um arquivo XML sem criptografia. Se o dispositivo estiver rooteado, os dados ficam acessíveis ao invasor.
// Ruim: SharedPreferences comuns\nval prefs = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE)\n\n// Bom: 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)\nRecomendação: Para dados confidenciais, use EncryptedSharedPreferences ou DataStore com criptografia.
6. Vulnerabilidades na desserialização (JSON/Gson/Moshi)
\nAo desserializar dados não confiáveis, é possível obter execução de código arbitrário ou vazamento de memória.
\n// Ruim: uso de Gson sem validação\nval user = Gson().fromJson(jsonString, User::class.java)\n\n// Bom: val