Безопасность Kotlin приложений: топ-10 уязвимостей для начинающих

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Безопасность Kotlin приложений: топ-10 уязвимостей для начинающих

Kotlin — современный язык программирования, который активно используется для создания Android-приложений, серверных решений и мультиплатформенных проектов. Однако даже с его строгой типизацией и безопасностью по умолчанию, разработчики-новички часто допускают ошибки, которые могут привести к серьёзным уязвимостям. В этой статье мы разберём топ-10 самых распространённых проблем безопасности в Kotlin-приложениях, покажем примеры опасного кода и дадим рекомендации по их устранению.

1. SQL-инъекции (SQL Injection)

Одна из самых старых и опасных уязвимостей. Если вы напрямую конкатенируете пользовательский ввод в SQL-запрос, злоумышленник может выполнить произвольные команды.

// ОПАСНО: конкатенация строк
val query = "SELECT * FROM users WHERE name = '$userInput'"
statement.executeQuery(query)

// БЕЗОПАСНО: использование параметризованных запросов
val query = "SELECT * FROM users WHERE name = ?"
val preparedStatement = connection.prepareStatement(query)
preparedStatement.setString(1, userInput)
preparedStatement.executeQuery()

2. Небезопасное хранение паролей

Никогда не храните пароли в открытом виде. Используйте bcrypt, Argon2 или PBKDF2. В Kotlin для этого можно использовать библиотеку spring-security-crypto или kotlinx-serialization с хешированием.

// ОПАСНО: хранение в plain text
data class User(val password: String)

// БЕЗОПАСНО: хеширование с солью
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder

val encoder = BCryptPasswordEncoder()
val hashedPassword = encoder.encode(plainPassword)

3. Отсутствие проверки ввода (Input Validation)

Любые данные от пользователя должны проходить валидацию. Игнорирование этого правила ведёт к XSS, инъекциям и DoS-атакам.

// ОПАСНО: прямой вывод без экранирования
fun renderHtml(userInput: String): String {
    return "<div>$userInput</div>"
}

// БЕЗОПАСНО: экранирование HTML
import org.owasp.encoder.Encode

fun renderSafeHtml(userInput: String): String {
    return "<div>${Encode.forHtml(userInput)}</div>"
}

4. Уязвимости в сериализации данных

Kotlin использует kotlinx.serialization или Gson/Moshi. Неправильная настройка может привести к раскрытию чувствительных данных или удалённому выполнению кода.

// ОПАСНО: сериализация всех полей
@Serializable
data class User(
    val name: String,
    val passwordHash: String // утечка хеша!
)

// БЕЗОПАСНО: исключение чувствительных полей
@Serializable
data class SafeUser(
    val name: String,
    @Transient val passwordHash: String = ""
)

5. Небезопасное использование WebView (Android)

При разработке Android-приложений на Kotlin часто используют WebView. Если не отключить JavaScript или не настроить фильтрацию, возможна XSS-атака.

// ОПАСНО: включен JavaScript без фильтрации
webView.settings.javaScriptEnabled = true
webView.loadUrl("file:///android_asset/index.html")

// БЕЗОПАСНО: отключаем JavaScript для статического контента
webView.settings.javaScriptEnabled = false
// Или используем Content Security Policy
webView.loadDataWithBaseURL(null, content, "text/html", "UTF-8", null)

6. Неправильное управление сессиями

Хранение токенов аутентификации в SharedPreferences без шифрования — частая ошибка. Используйте EncryptedSharedPreferences или Android Keystore.

// ОПАСНО: открытое хранение токена
val prefs = context.getSharedPreferences("auth", Context.MODE_PRIVATE)
prefs.edit().putString("token", token).apply()

// БЕЗОПАСНО: шифрованное хранение
val encryptedPrefs = EncryptedSharedPreferences.create(
    "secure_prefs",
    MasterKey.DEFAULT_MASTER_KEY_ALIAS,
    context,
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
encryptedPrefs.edit().putString("token", token).apply()

7. Утечка информации через логирование

Разработчики часто логируют лишние данные: пароли, токены, номера карт. Это опасно в production.

// ОПАСНО: логирование чувствительных данных
log.info("User login: $username, password: $password")

// БЕЗОПАСНО: маскирование
log.info("User login: $username, password: [REDACTED]")

8. Небезопасное использование Coroutines

При работе с корутинами можно случайно запустить утечку ресурсов или выполнить неотменяемые операции, что приведёт к DoS.

// ОПАСНО: глобальный scope без отмены
GlobalScope.launch {
    // бесконечная операция
}

// БЕЗОПАСНО: использование viewModelScope или lifecycleScope
viewModelScope.launch {
    // операция автоматически отменяется при уничтожении ViewModel
}

9. Отсутствие проверки прав доступа (Android)

Не проверяйте разрешения только в одном месте. Злоумышленник может обойти проверку через Intent-фильтры.

// ОПАСНО: проверка только в Activity
if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
    // доступ к камере
}

// БЕЗОПАСНО: проверка в каждом критическом методе
fun takePhoto() {
    if (context.checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
        requestPermission()
        return
    }
    // безопасный доступ
}

10. Использование устаревших или небезопасных библиотек

Даже в Kotlin можно подключить библиотеку с известными уязвимостями. Регулярно обновляйте зависимости и используйте инструменты анализа (например, OWASP Dependency-Check).

// build.gradle.kts
dependencies {
    // ОПАСНО: старая версия с CVE
    implementation("com.squareup.okhttp3:okhttp:3.12.0")
    
    // БЕЗОПАСНО                

Блоги

Рекомендаций по книгам