介绍
Android操作系统具有许多内置的安全功能,例如应用程序沙箱,针对缓冲区和整数溢出攻击的保护以及用于程序指令和数据的独立存储区。 因此,默认情况下,通常不将不执行任何文件系统或网络操作的简单Android应用程序视为安全的。
但是,如果您要开发更复杂的应用程序,则有责任确保其安全并保护用户的隐私。 在本文中,我将列出一些最佳实践,您可以遵循这些最佳实践来构建安全的Android应用程序,该应用程序不会泄漏数据或权限,并且通常不易受到可能安装在其上的恶意应用程序的攻击。用户的设备。
1.使用内部存储来存储敏感数据
每个Android应用程序都有一个与其关联的内部存储目录,该目录的路径基于该应用程序的程序包名称。 此目录中的文件非常安全,因为默认情况下它们使用MODE_PRIVATE
文件创建模式。 这意味着文件不能被设备上的任何其他应用访问。 因此,这是将应用程序的所有敏感数据存储在内部存储目录中的最佳位置。
要确定应用程序内部存储目录的绝对路径,建议您使用getFilesDir()
方法。 知道其路径后,在其中引用文件就像在任何其他目录中引用文件一样简单。 例如,以下是在应用程序的内部存储目录中引用名为myfile.dat的文件的方式:
File myFile = new File(getFilesDir(), "myfile.dat");
2.加密外部存储上的数据
Android设备的内部存储容量通常受到限制。 因此,有时您别无选择,只能将敏感数据存储在外部存储介质(例如可移动SD卡)上。
由于用户和设备上的其他应用程序都可以直接访问外部存储介质上的数据,因此以加密格式存储数据非常重要。 当今,开发人员使用的最流行的加密算法之一是AES,它是Advanced Encryption Standard的缩写,密钥大小为256位。
使用包含在Android SDK中的javax.crypto
包编写代码来加密和解密应用程序的数据可能会造成混淆。 因此,大多数开发人员更喜欢使用第三方库,例如Facebook的Conceal库,它们通常更易于使用。
3. IPC使用意图
刚接触Android应用程序开发的经验丰富的程序员经常尝试使用套接字,命名管道或共享文件来与Android设备上安装的其他应用程序异步通信。 这些方法不仅艰巨,笨拙,而且容易受到威胁。 在Android操作系统上进行进程间通信的一种更简单,更安全的方法是使用意图。
要将数据发送到应用程序的特定组件,您必须创建Intent
类的新实例,并使用其setComponent()
方法来指定应用程序的包名和组件的名称。 然后,您可以使用putExtra()
方法向其中添加数据。
例如,这是将字符串Hello World发送到名为MyActivity的Activity
方法 ,该Activity
属于一个程序包名称为my.other.app的应用程序:
// Create an intent
Intent intent = new Intent();
// Specify the component name
intent.setComponent(
new ComponentName("my.other.app","my.other.app.MyActivity")
);
// Add data
intent.putExtra("DATA", "Hello World!");
// Send the intent to the activity
startActivity(intent);
要将数据一次发送到多个应用程序,可以使用sendBroadcast()
方法以广播形式发送意图。 但是,默认情况下,具有适当配置的BroadcastReceiver
任何应用都可以读取BroadcastReceiver
。
因此,如果要将敏感信息作为广播发送,则必须使用一个自定义权限,其protectionLevel
设置为signature
。 这样,Android操作系统可确保只有使用您的签名密钥签名的应用程序才能接收广播。
这是一个代码段,向您展示如何将字符串Hello World发送为安全广播:
// Create an intent
Intent intent = new Intent();
// Add data
intent.putExtra("DATA", "Hello World");
// Specify an action name for
// the receiver's intent-filter
intent.setAction("my.app.receive");
// Send as a broadcast using a custom permission
sendBroadcast(intent, "my.custom.permission");
请注意,只有在发送方和接收方应用程序的清单文件中声明并使用了自定义权限后,上述代码才能按预期工作。
<permission android:name="my.custom.permission"
android:protectionLevel="signature"/>
<uses-permission android:name="my.custom.permission"/>
4.使用HTTPS
应用程序和服务器之间的所有通信都必须通过HTTPS连接,最好使用HttpsURLConnection
类。 如果您认为对非机密数据使用HTTP可以,请再三考虑。
许多Android用户每天都在公共区域连接到几个开放的Wi-Fi热点。 其中一些热点可能是恶意的。 恶意热点可以轻易地更改HTTP流量的内容,以使您的应用程序以意外的方式运行,或者更糟的是,向其中注入广告或漏洞利用。
通过使用HTTPS,只要服务器配置有由可信证书颁发机构(例如DigiCert或GlobalSign)颁发的证书,就可以确保网络流量安全,以防窃听和中间人攻击。
如果您的应用程序具有大量的网络代码,并且您担心自己不知不觉地以明文形式发送了一些数据,则应考虑使用nogotofail ,它是Google构建的开源工具,可以发现此类错误。
5.使用GCM代替SMS
早在GCM( Google Cloud Messaging的缩写)不存在时,许多开发人员就在使用SMS将数据从其服务器推送到其应用程序。 今天,这种做法已基本消失。
如果您是还没有从SMS切换到GCM的那些开发人员之一,则必须知道SMS协议既不是加密的,也不是可以防止欺骗攻击的。 此外,具有READ_SMS
权限的用户设备上的任何应用都可以读取SMS。
GCM更加安全,并且是将消息推送到应用程序的首选方式,因为所有GCM通信都是经过加密的。 使用客户端上定期刷新的注册令牌和服务器端上的唯一API密钥对它们进行身份验证。 要了解有关GCM的更多信息,您可以参考有关推送通知的本教程 。
6.避免索要个人资料
如今,用户隐私已变得非常重要。 实际上,有一些法律,例如欧盟的《 数据保护指令》和加拿大的《 个人信息保护和电子文档法》 ,其中规定了对用户隐私的保护。 因此,除非您有充分的理由和非常安全的基础结构来收集,存储和传输个人用户信息,否则必须避免直接在应用程序中提出要求。
在Android上查找用户身份验证和用户个人资料信息的更好方法是通过Google身份平台 。 Google Identity Platform允许用户使用其Google帐户快速登录到您的应用程序。 通过平台成功登录后,只要有必要,您的应用程序就可以轻松查找有关用户的各种详细信息,例如用户名,电子邮件地址,个人资料照片,联系人等。 另外,您可以使用Firebase等免费服务来为您管理用户身份验证。
如果必须自己处理用户凭据,建议您以安全哈希的形式存储和传输它们。 使用Android SDK生成不同类型哈希的最直接方法是使用MessageDigest
类。
这是一个小代码段,向您展示如何使用SHA-256哈希函数创建字符串Hello World的哈希:
// Initialize MessageDigest to use SHA-256
MessageDigest md = MessageDigest.getInstance("SHA-256");
// Convert the string to a hash
byte[] sha256Hash = md.digest("Hello World".getBytes());
7.验证用户输入
在Android上,无效的用户输入通常不会导致诸如缓冲区溢出之类的安全问题。 但是,如果允许用户与SQLite数据库或内部使用SQLite数据库的内容提供程序进行交互,则必须严格清理用户输入或使用参数化查询。 否则,您的数据容易受到SQL注入攻击的攻击。
与此类似,如果要使用用户输入动态生成要在嵌入式脚本引擎(例如Mozilla Rhino)上运行的代码,则用户输入验证和清理也非常重要。 。
8.发布前使用ProGuard
如果攻击者能够使用源代码,则可能严重损害内置在Android应用程序中的安全措施。 在发布应用程序之前,建议使用Android SDK中包含的ProGuard工具来混淆和最小化源代码。
如果将buildType
设置为release
则Android Studio会在构建过程中自动包含ProGuard。 Android SDK的proguard-android.txt文件中可用的默认ProGuard配置足以满足大多数应用的需求。 如果要向配置中添加自定义规则,则可以在名为proguard-rules.pro的文件中进行操作,该文件是每个Android Studio项目的一部分。
结论
希望您现在对如何确保Android应用程序的安全性有更好的了解。 我在本文中提到的大多数最佳做法仅在使用Android SDK开发应用程序时适用。 如果使用的是Android NDK,则必须更加小心,因为在使用C语言编程时,您应该自己管理低级细节,例如指针和内存分配。
要了解有关Android上安全性的更多信息,可以参考AOSP安全性文档 。
翻译自: https://code.tutsplus.com/articles/how-to-secure-an-android-app--cms-26385