移动安全是一系列保护应用程序、用户数据和服务器基础设施免受攻击和泄露的措施。根据OWASP Mobile Top 10(2024),不安全的数据存储仍然是移动应用程序中最常见的漏洞。本文将讨论主要威胁、加密方法、安全存储、身份验证和代码保护 — 初级开发人员需要了解的一切。
关键要点
OWASP(开放Web应用程序安全项目)是一个发布最危险移动安全漏洞排名的非营利组织。OWASP Mobile Top 10是一个帮助开发人员理解首先关注什么的列表。在2024版本中,与不安全存储、弱身份验证和不安全网络通信相关的问题位居榜首。
M1:不安全的数据存储 — 最常见的问题:密码、令牌和个人数据未经加密就留在SharedPreferences、NSUserDefaults或本地文件中。M2:弱身份验证 — 缺乏服务器端验证,弱密码。M3:不安全的网络通信 — 缺乏HTTPS或SSL证书验证不正确。M4和M5与密码学和错误的API使用有关。
M6:不安全的授权 — 用户可以通过在请求中替换ID来访问另一个用户的数据。M7:代码注入(SQL注入、XSS)。M8:应用程序操纵 — 重打包、代码替换。M9和M10 — 通过第三方库泄露数据和逆向工程。针对这些威胁,都有经过验证的对策,IT Sectr自2017年以来在所有项目中都应用了这些对策。
MITM攻击发生在攻击者拦截应用程序与服务器之间的流量时。这可以通过DNS欺骗、ARP欺骗或连接到不安全的Wi-Fi网络来实现。使用SSL/TLS证书和Certificate Pinning进行保护。
Certificate Pinning是一种机制,应用程序通过它验证服务器证书是否与应用程序代码中预先存储的证书匹配。即使攻击者通过代理(例如Burp Suite)替换了证书,应用程序也会拒绝连接。Pinning有两种类型:公钥固定(Public Key Pinning)和证书哈希固定(Certificate Hash Pinning)。
AES(高级加密标准)是一种对称加密算法,是设备上数据安全的基础。AES使用相同的密钥进行加密和解密。AES支持128、192或256位密钥。在移动开发中,AES-256用于加密设备上的数据:文件、缓存、本地数据库中的记录。
AES模式:GCM(推荐)— 提供数据认证,CBC — 带块链接的基本模式,ECB — 不安全,请勿使用。对于iOS,AES可通过CommonCrypto(CCOptions)使用;对于Android,可通过Java密码体系结构(JCA)中的Cipher使用。重要提示:加密密钥绝不应存储在应用程序代码中 — 请使用Keychain/Keystore。
非对称加密:RSA — 使用一对密钥(公钥和私钥)。RSA用于加密少量数据 — 通常用于在客户端和服务器之间交换对称密钥。最小RSA密钥长度为2048位(推荐4096)。在iOS上,RSA可通过Security Framework(SecKeyCreateRandomKey)使用;在Android上,可通过Android Keystore中的KeyPairGenerator使用。
哈希(SHA-256、SHA-3)是将数据不可逆地转换为固定长度字符串的过程。哈希用于数据完整性验证和密码存储。对于密码,务必使用bcrypt、scrypt或Argon2 — 普通的SHA-256容易受到彩虹表攻击。SSL/TLS是用于加密客户端和服务器之间网络流量的协议。现代标准是TLS 1.3,它提供前向保密(PFS)。
TLS 1.3比其前身更快:握手只需一次往返而不是两次。在Android上,最小TLS版本通过SSLSocket配置;在iOS上,通过ATS(应用程序传输安全)配置,默认要求TLS 1.2或更高版本。ATS只能在有正当理由的情况下为特定域禁用。
Keychain(钥匙串)是iOS / macOS中用于密码、加密密钥、证书和令牌的安全存储。Keychain中的数据使用每个设备唯一的硬件密钥进行加密。对Keychain的访问通过Security Framework(SecItemAdd、SecItemCopyMatching)控制。Keychain在设备锁定时自动锁定,并使用安全隔区(Secure Enclave)进行加密。
Android Keystore是用于加密密钥的系统存储,与应用程序隔离。从Android 6.0(API 23)开始,Keystore在具有安全芯片的设备上使用硬件支持(TEE — 可信执行环境)。Keystore中的密钥永远不会离开安全区域 — 应用程序只接收用于加密和签名操作的句柄。
| 参数 | iOS Keychain | Android Keystore |
|---|---|---|
| 存储的数据类型 | 密码、令牌、密钥、证书 | 加密密钥 |
| 硬件支持 | 安全隔区(所有配备A7+的iPhone) | TEE(Android 6+,取决于芯片) |
| 加密 | AES-256硬件加密 | 使用硬件密钥的AES/GCM |
| 生物识别 | Face ID / Touch ID用于访问 | BiometricPrompt用于访问 |
| iCloud / 备份 | 通过iCloud Keychain同步 | 不与云同步 |
| 性能 | 较慢(硬件加密) | 较快(TEE) |
SharedPreferences和NSUserDefaults不是为存储敏感数据而设计的 — 它们以明文形式存储信息。为保护数据,请使用EncryptedSharedPreferences(Android)或在保存到UserDefaults(iOS)之前加密数据。在IT Sectr,我们始终使用Keychain和Keystore来存储访问令牌和密码。
OAuth 2.0是一种委托授权协议,无需传输密码即可安全访问用户资源。在移动应用程序中,最常用的是带有PKCE(代码交换证明密钥)的授权码流程。PKCE防止授权码被截获 — 这是移动应用程序的强制性要求。
OpenID Connect(OIDC)是在OAuth 2.0之上的用户身份验证扩展。OIDC添加了JWT格式的ID令牌,其中包含用户信息(姓名、电子邮件、ID)。OAuth 2.0 + OIDC流程包括:将用户重定向到登录页面,获取授权码,将代码交换为令牌(access + refresh + id),使用访问令牌进行API请求。
JWT(JSON Web令牌)是一种紧凑的、URL安全的令牌格式,包含JSON格式的声明(claims)。JWT由三部分组成:头部(类型和签名算法)、负载(数据)和签名。访问令牌是用于API访问的短命令牌(15-60分钟)。刷新令牌是用于获取新访问令牌而无需重新登录的长命令牌(天/周)。
会话令牌是一种传统方法,服务器将会话存储在数据库或Redis中,客户端接收一个随机标识符。在移动开发中,JWT更受青睐:它不需要服务器端会话存储,在自身内部包含所有信息,并且易于验证。然而,JWT不能立即撤销 — 这是一个权衡,通过短访问令牌生命周期和使用刷新令牌来解决。
iOS上的Face ID和Touch ID,Android上的指纹认证 — 使用用户独特物理特征的生物识别认证方法。在iOS上,生物识别通过LocalAuthentication(LAContext)工作;在Android上,通过BiometricPrompt(Android 9+)或FingerprintManager(已弃用)工作。生物识别用于解锁应用程序、确认支付和访问受保护的数据。
重要注意事项:生物识别是便利的UX,但不能替代服务器端认证。生物识别验证成功后,应用程序应从服务器获取访问令牌。在Android上,务必确认设备使用的是Class 3(强)生物识别,而不仅仅是基于摄像头的面部识别(Class 1)。
ProGuard是用于Android的Java字节码混淆、压缩和优化工具,提高了代码对抗逆向工程的安全性。R8是其继任者,自Android Studio 3.4起内置在Gradle中。R8执行四项任务:压缩(删除未使用的类和方法)、优化(内联方法、简化代码)、混淆(将类和方法重命名为短名称)和预验证(字节码检查)。
DexGuard是ProGuard的商业版本,具有增强的保护功能:字符串加密、资源混淆、防重打包、APK完整性控制。对于大多数项目,R8就足够了,但对于金融和银行应用,DexGuard提供了额外的安全层。R8通过build.gradle启用:minifyEnabled = true和proguardFiles。
Root检测(Android)和越狱检测(iOS)是检查设备上是否已获得超级用户权限的机制。在被入侵的设备上,可以读取进程内存、拦截流量和替换代码。在Android上进行检查时,使用SU二进制文件的存在、测试签名密钥和非标准构建标志。
RASP(运行时应用程序自我保护)是一种在执行期间保护应用程序的技术。RASP检测调试、重打包、代码注入的尝试,并在检测到威胁时终止应用程序。RASP解决方案的示例:Dexter、Guardsquare、Promon。RASP在运行时工作并对异常做出反应 — 与在执行前保护代码的静态混淆不同。
逆向工程是从编译后的应用程序恢复源代码的过程。工具:JADX(APK反编译器)、Ghidra、IDA Pro、Hopper。对抗逆向工程的保护是混淆、字符串加密、完整性检查和Root检测的组合。完全的保护不存在 — 目标是为攻击者制造足够昂贵的逆向工程成本。
常见问题
从OWASP Mobile Top 10开始 — 这是最常见漏洞的路线图。然后学习HTTPS和SSL证书,配置Certificate Pinning,然后转向通过Keychain / Keystore的安全存储。
AES(对称)— 一个密钥用于加密和解密,快速,适用于大量数据。RSA(非对称)— 一对密钥(公钥和私钥),较慢,用于交换对称密钥。
只需加密机密数据:密码、令牌、个人用户数据、支付信息。图像、文本和界面设置不需要加密 — 这会增加大小并减慢应用程序速度。
刷新令牌是一种长命令牌,允许在不重新输入密码的情况下获取新的访问令牌。这提高了安全性 — 访问令牌的有效期为15-60分钟,即使泄露,攻击者也无法长时间使用。
是的,Android的发布构建必须启用R8。这不仅是对抗逆向工程的保护,也是APK大小减小和性能优化。没有R8,您的代码可以通过单个JADX命令反编译为可读形式。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。