所有文章 > 技术杂货铺 > Kotlin 损坏 认证指南: 示例和预防
Kotlin 损坏 认证指南: 示例和预防

Kotlin 损坏 认证指南: 示例和预防

现在,您已经创建了一个可以工作的表单。您是否考虑过它是否会让您的用户面临攻击风险?

作为开发人员,我们通常更关心确保代码有效、可维护且易于阅读,而不是修复错误。但是,如果我们不优先考虑安全性,我们的应用程序就会受到恶意攻击。因此,将安全性作为我们开发过程的一部分至关重要。但要做到这一点,我们首先必须了解我们的应用程序可能面临的威胁类型。

在这篇文章中,我将解释如何保护您的 Kotlin 应用程序免受身份验证漏洞的影响。首先,我将解释一些常见的身份验证漏洞。然后,我们将研究使 Kotlin 应用程序更安全的解决方案。最重要的是,您将看到保护您的用户免受恶意攻击者的攻击并不一定意味着额外的工作!

Kotlin 身份验证失败指南:示例和预防措施图片

什么是失效身份验证?

身份验证失效是一个宽泛的术语,它涵盖了多种漏洞。我们将重点关注两个主要漏洞:

  • 会话管理:劫持用户会话 ID
  • 凭证管理:劫持真实用户的凭证

攻击可以非常具体,针对个人。攻击者发动大规模攻击也很常见。

会话管理

首先,每当用户与应用程序交互时,都会为他们分配一个会话 ID 来帮助识别他们。这是应用程序用于与用户通信的唯一 ID。会话 ID 通常以共享首选项的形式出现。由于共享首选项是让用户保持登录状态的好方法,攻击者会尝试使用各种方法来获取这些 ID,从而获取受保护的信息。

让我们看一些不同类型的会话管理攻击以及如何预防它们。

攻击:会话 ID URL 重写

在会话 ID URL 重写中,用户的会话 ID 会出现在 URL 中。在这种情况下,您已将用户的私人数据暴露给大范围攻击。这可能导致攻击者嗅探并获取会话 ID 的访问权限。

解决方案

Kotlin 仍然主要用于开发移动应用程序,但是也可以使用 Kotlin 构建 Web 应用程序。在该网站上使用 HTTPS 非常重要。简而言之,HTTPS 可以验证网站并保护用户提交的信息。黑客无法解密用户信息,从而降低了攻击的可能性。

大多数网站 URL 旁边的挂锁符号代表 HTTPS,可让用户知道该网站是安全的。Adobe 业务平台后端已从 Java 迁移到 Kotlin。锁图标可让用户确信该网站可以安全使用。

Kotlin 身份验证失败指南:示例和预防措施图片

URL 旁边的锁定图标可确保用户网站的安全

幸运的是,Kotlin 有许多框架可用于提供、使用和测试 HTTPS。例如,Ktor和http4k是用于连接 Kotlin 应用程序的流行框架。相比之下,Ktor 是完全异步的,而 http4k 则不是。选择最适合您需求的框架很重要。

攻击:会话固定

移动应用程序连接到外部服务以验证用户身份。这些服务包括其主机服务器、其他移动资源和第三方服务。黑客将利用此通信中的漏洞发起攻击。

在会话固定攻击中,攻击者试图诱骗用户验证预定的会话 ID。攻击者将尝试预先确定一个会话 ID。然后,他们向用户发送一个带有预定会话 ID 的链接。这将提示用户登录。攻击者误以为该链接指向合法应用程序,然后输入其凭据。攻击者能够访问受保护的资源,因为他们现在可以访问经过身份验证的会话 ID。

解决方案

移动客户端证书

阻止非人类攻击访问您的应用程序的最简单方法是通过移动客户端证书。本质上,应用程序使用移动客户端证书向后端验证自身身份。客户端证书只是验证连接来自受信任的来源,并应允许访问后端。因此,这允许防火墙阻止未经授权的应用程序或恶意机器人。最重要的是,这只允许受信任的应用程序访问您的后端。可以将其视为应用程序与外部服务之间的数字握手。

幸运的是,Kotlin 支持在您的应用中整合移动客户端证书。使用 Kotlin 添加证书有三种方法:网络安全配置、信任管理器和证书固定。每种方法都有自己的优点和缺点,因此请确保选择最适合您的 Kotlin 应用的方法。以下代码是证书固定与okHttpClient一起使用的示例。

val certificatePinner = CertificatePinner.Builder()
       .add(
              "www.secureserver.com",
              "sha256/7HIpactkIAq2Y49orFEOQKurWxkmSFZhBCoQYcRyJ3Y="
       ).build()



val okHttpClient = OkHttpClient.Builder()
       .certificatePinner(certificatePinner)
       .build()
结束会话

此外,在长时间不活动后结束会话长度并在一定时间后注销可以减少违规的可能性。您可以使用共享首选项删除或添加会话 ID。同样重要的是,Kotlin 会将共享首选项存储在设备本身内。因此,请记住对它们进行加密,以便任何获得访问权限的人都无法读取它们。此外,一旦用户长时间不活动,请确保销毁 ID。

为了说明这一点,请考虑像 Amazon Prime 这样的电影流媒体应用。流媒体应用希望让用户能够轻松浏览应用,而无需每次都登录。相反,银行应用应该在几分钟后注销用户,因为攻击的可能性要高得多。考虑到这一点,请确保在用户不再活跃或离开应用时清除已保存的数据。您可以使用活动生命周期 onDestroy 和 onResume 来执行此操作。

onDestroy(){
    val sharedPref = context.getSharedPreferences(STRING_VALUE, Context.MODE_PRIVATE)
    sharedPref.edit().clear().apply()
}
onResume(){
    context.getSharedPreferences(STRING_VALUE, 0).edit().clear().commit();
}

凭证管理

攻击者获取受保护信息的最简单方法是使用用户的凭据。

攻击者会尝试获取用户的凭证对(即用户名和密码)。获取这些凭证后,攻击者便可控制用户的帐户。这让攻击者可以访问受保护的资源。

攻击:凭证填充

凭证填充攻击正在兴起,不再以大型企业为目标。基本上,这种类型的攻击发生在攻击者已经可以访问用户凭证的情况下。

黑客通常会将凭证出售或泄露给其他攻击者。他们已经获得了未加密数据库的访问权限。这些攻击者会自动尝试不同的用户名和密码对。事实上,黑客会使用模拟器等虚拟环境来做到这一点。

最重要的是,这是一场数字游戏。其目的是劫持用户账户。攻击者之所以这样做,是因为人们经常在不同的应用程序上使用相同的密码和用户名。实际上,目前攻击者已经能够访问数十亿个凭证。

解决方案

因此,有效防止移动应用成为凭证填充攻击的受害者的最佳方法之一是防止其在虚拟设备上运行。这些虚拟设备包括模拟器、仿真器、虚拟环境、调试工具和其他虚拟环境。下面的代码只是检查应用是否在仿真器中打开。

首先,我们收集市场上所有的模拟器。其次,Kotlin 允许我们评估它们的属性,主要是它们的 build 值。最后,我们使用返回值来确定是否可以授予应用程序访问权限。

private fun checkBuildConfig(): Boolean {
var isEmulator = (Build.MANUFACTURER.contains("Genymotion")
|| Build.MODEL.contains("google_sdk")
|| Build.MODEL.toLowerCase().contains("droid4x")
|| Build.MODEL.contains("Emulator")
|| Build.MODEL.contains("Android SDK built for x86")
|| Build.HARDWARE == "goldfish"
|| Build.HARDWARE == "vbox86"
|| Build.HARDWARE.toLowerCase().contains("nox")
|| Build.FINGERPRINT.startsWith("generic")
|| Build.PRODUCT == "sdk"
|| Build.PRODUCT == "google_sdk"
|| Build.PRODUCT == "sdk_x86"
|| Build.PRODUCT == "vbox86p"
|| Build.PRODUCT.toLowerCase().contains("nox")
|| Build.BOARD.toLowerCase().contains("nox")
|| (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")))
return isEmulator
}

黑客希望使用服务器和后端来访问应用程序。在这种情况下,请记住加密所有 API 端点,因为攻击者将使用此信息进行凭证填充。例如,建议加密用户名和密码,因为攻击者需要这些信息进行攻击。为了增加保护,请考虑使用密钥库,这会使从设备中提取加密数据变得更加困难。

fun main():{
val plaintext: ByteArray = ...
al keygen = KeyGenerator.getInstance("AES")
keygen.init(256)
val key: SecretKey = keygen.generateKey()
val cypher = Cypher.getInstance("AES/CBC/PKCS5PADDING")
cypher.init(CYPHER.ENCRYPT_MODE, key)
val cyphertext: ByteArray = cypher.doFinal(plaintext)
val iv: ByteArray = cypher.iv
}

攻击:密码喷洒

密码喷洒是一种暴力攻击,类似于凭证填充。喷洒不涉及已经存在的密码和用户名对。攻击者将尝试使用常用短语、术语、生日等来猜测用户凭证。假设许多人会选择弱密码。平均而言,用户必须记住 100 个密码。这导致人们使用弱密码或重复使用密码来让自己的生活更轻松。最重要的是,这可能导致您的应用容易受到恶意攻击和入侵。

解决方案

总体而言,使用无密码身份验证可以消除不安全的密码行为。用户通常会选择非常容易被破解的常用密码。这让黑客很容易利用此漏洞。考虑向用户发送验证链接、要求发送验证所有权的短信或使用生物识别技术。生物识别技术是一项特别好的安全功能,因为它需要用户采取独特的身体动作。而 Kotlin 支持在您的应用程序中使用生物识别技术。

val biometricManager = BiometricManager.from(this)
when (biometricManager.canAuthenticate(BIOMETRIC_STRONG or DEVICE_CREDENTIAL)) {
    BiometricManager.BIOMETRIC_SUCCESS ->
        Log.d("MY_APP_TAG", "App can authenticate using biometrics.")
    BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE ->
        Log.e("MY_APP_TAG", "No biometric features available on this device.")
    BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE ->
        Log.e("MY_APP_TAG", "Biometric features are currently unavailable.")
    BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> {
        // Prompts the user to create credentials that your app accepts.
        val enrollIntent = Intent(Settings.ACTION_BIOMETRIC_ENROLL).apply {
            putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
                BIOMETRIC_STRONG or DEVICE_CREDENTIAL)
        }
        startActivityForResult(enrollIntent, REQUEST_CODE)
    }
}

结论

身份验证失败可能会对您的 Kotlin 应用程序造成严重影响。因此,将安全性纳入开发流程非常重要。

文章来源:Kotlin Broken Authentication Guide: Examples and Prevention

#你可能也喜欢这些API文章!