确保Android上的通信安全

在最近发生的所有数据泄露事件中,隐私已成为重要的话题。 几乎每个应用程序都通过网络进行通信,因此考虑用户信息的安全性很重要。 在这篇文章中,您将学习确保Android应用程序通信安全的最新最佳做法。

使用HTTPS

在开发应用程序时,最佳做法是将网络请求限制为必不可少的请求。 对于必不可少的内容,请确保它们是通过HTTPS而不是HTTP制作的。 HTTPS是一种对流量进行加密的协议,这样它就不会轻易被窃听者拦截。 Android的优点在于,迁移就像将URL从http更改为https一样简单。

URL url = new URL("https://example.com");
HttpsURLConnection httpsURLConnection = (HttpsURLConnection)url.openConnection();
httpsURLConnection.connect();

实际上,Android N和更高版本可以使用Android的网络安全配置强制实施HTTPS。

在Android Studio中,为您的项目选择app / res / xml目录。 如果xml目录尚不存在,请创建它。 选择它,然后单击文件>新建文件 。 将其称为network_security_config.xml 。 该文件的格式如下:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <domain-config cleartextTrafficPermitted="false">
    <domain includeSubdomains="true">example.com</domain>
  </domain-config>
</network-security-config>

要告诉Android使用此文件,请将文件名添加到AndroidManifest.xml文件的application标签中:

<application android:networkSecurityConfig="@xml/network_security_config"

更新加密提供者

多年来,HTTPS协议已被利用多次。 当安全研究人员报告漏洞时,通常会修补缺陷。 应用补丁程序可确保您的应用程序的网络连接使用最新的行业标准协议。 该协议的最新版本所包含的弱点少于以前的弱点。

要更新加密货币提供者 ,您将需要包含Google Play服务。 在build.gradle的模块文件中,将以下行添加到dependencies部分:

implementation 'com.google.android.gms:play-services-safetynet:15.0.1'

SafetyNet服务API具有更多功能,包括用于检查URL以查看其是否被标记为已知威胁的Safe Browsing API和用于保护您的应用免受垃圾邮件发送者和其他恶意流量攻击的reCAPTCHA API。

同步Gradle之后,可以调用ProviderInstallerinstallIfNeededAsync方法:

public class MainActivity extends Activity implements ProviderInstaller.ProviderInstallListener
{
  @Override
  protected void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    ProviderInstaller.installIfNeededAsync(this, this);
  }
}

当提供程序成功更新或已经更新时,将调用onProviderInstalled()方法。 否则,将onProviderInstallFailed(int errorCode, Intent recoveryIntent)

证书和公钥固定

与服务器建立HTTPS连接时,服务器会提供数字证书,并由Android进行验证,以确保连接安全。 可以使用来自中间证书颁发机构的证书对证书进行签名。 中间机构使用的该证书可以依次由另一个中间机构签名,依此类推,只要最后一个证书由Android OS已经信任的根证书颁发机构签名,就可以信任。

如果信任链中的任何证书无效,则连接不安全。 虽然这是一个很好的系统,但并非万无一失。 攻击者可能会指示Android OS接受自定义证书。 拦截代理可以拥有受信任的证书,并且如果设备由公司控制,则该公司可能已将设备配置为接受其自己的证书。 这些方案允许“中间人”攻击,从而可以解密和读取HTTPS通信。

通过对照提供的预期证书副本检查提供的服务器证书,可以轻松锁定证书。 这样可以防止在证书与预期证书不同时进行连接。

为了在Android N及更高版本上实现固定,您需要将证书的哈希(称为“固定”)添加到network_security_config.xml文件中。 这是一个示例实现:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <domain-config cleartextTrafficPermitted="false">
    <domain includeSubdomains="true">duckduckgo.com</domain>
    <pin-set>
      <pin digest="SHA-256">lFL47+i9MZkLqDTjnbPTx2GZbGmRfvF3GkEh+J+1F3g=</pin>
      <pin digest="SHA-256">w9MWhhnFZDSPWTFBjaoeGuClsrCs7Z70lG7YNlo8t+s=</pin>
    </pin-set>
  </domain-config>
</network-security-config>

要查找特定站点的图钉,您可以转到SSL Labs ,输入站点,然后单击Submit 。 或者,如果您正在为公司开发应用程序,则可以要求公司提供。

注意:如果需要支持运行Android N之前的OS版本的设备,则可以使用TrustKit库。 它以完全相同的方式利用网络安全配置文件。

消毒与验证

到目前为止,所有保护措施都已确保安全。 即使这样,也不要忘记进行常规编程验证。 盲目信任从网络接收到的数据是不安全的。 良好的编程习惯是“按合同设计”,其中方法的输入和输出满足定义特定接口期望的合同。

例如,如果服务器期望的字符串长度不超过48个字符,请确保该接口最多返回不超过48个字符。

if (editText.getText().toString().length() <= 48)
{
    ; //return something...
}
else
{
    ; //return default or error
}

如果只希望服务器提供数字,则应检查输入内容。 虽然这有助于防止发生无辜的错误,但同时也减少了注入和内存损坏攻击的可能性。 当数据传递到NDKJNI(本地C和C ++代码)时,尤其如此。

将数据发送到服务器也是如此。 不要盲目发送数据,尤其是由用户生成的数据。 例如,优良作法是限制用户输入的长度,尤其是当该输入将由SQL Server或将运行代码的任何技术执行时。

尽管保护服务器免受攻击不属于本文的范围,但是作为移动开发人员,您可以通过删除服务器使用的语言字符来尽自己的一份力量。 这样,输入就不会受到注入攻击的影响。 一些示例在用户输入不是必需的情况下会删除引号,分号和斜杠:

string = string.replace("\\", "").replace(";", "").replace("\"", "").replace("\'", "");

如果您确切知道所需的格式,则应进行检查。 一个很好的例子是电子邮件验证:

private final String emailRegexString = "^[A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z]{2,4}$";
private boolean isValidEmailString(String emailString)
{
     return emailString != null &&   Pattern.compile(emailRegexString).matcher(emailString).matches();
}

也可以检查文件。 如果您要将照片发送到服务器,则可以检查它是有效的照片。 对于JPEG格式,前两个字节和后两个字节始终为FF D8FF D9

private static boolean isValidJPEGAtPath(String pathString) throws IOException
{
    RandomAccessFile randomAccessFile = null;
    try
    {
        randomAccessFile = new RandomAccessFile(pathString, "r");
        long length = randomAccessFile.length();
        if (length < 10L)
        {
            return false;
        }
        byte[] start = new byte[2];
        randomAccessFile.readFully(start);
        randomAccessFile.seek(length - 2);
        byte[] end = new byte[2];
        randomAccessFile.readFully(end);
        return start[0] == -1 && start[1] == -40 && end[0] == -1 && end[1] == -39;
    }
    finally
    {
        if (randomAccessFile != null)
        {
            randomAccessFile.close();
        }
    }
}

在显示直接显示来自服务器的消息的错误警报时,请当心。 错误消息可能会泄露专用调试信息或与安全性有关的信息。 解决方案是让服务器发送一个错误代码,让客户端查找该错误代码以显示预定义的消息。

与其他应用程序的通信

在保护与设备之间的通信时,保护IPC也很重要。 在某些情况下,开发人员会留下共享文件或已实现套接字以交换敏感信息。 这是不安全的。 最好使用Intent 。 您可以通过提供以下包名称来使用Intent发送数据:

Intent intent = new Intent();
intent.setComponent(new ComponentName("com.example.app","com.example.app.TheActivity"));
intent.putExtra("UserInfo", "Example string");
startActivity(intent);

要向多个应用程序广播数据,您应强制只有使用您的签名密钥进行签名的应用程序才能获取数据。 否则,您注册的任何应用都可以读取您发送的信息,以接收广播。 同样,如果您已注册接收广播,则恶意应用可以向您的应用发送广播。 您可以在使用签名作为protectionLevel的广播发送和接收广播时使用权限。 您可以在清单文件中定义自定义权限,如下所示:

<permission android:name="com.example.mypermission" android:protectionLevel="signature"/>

然后,您可以像这样授予权限:

<uses-permission android:name="com.example.mypermission"/>

这两个应用都需要在清单文件中具有权限才能运行。 发送广播:

Intent intent = new Intent();
intent.putExtra("UserInfo", "Example string");
intent.setAction("com.example.SOME_NOTIFICATION");
sendBroadcast(intent, "com.example.mypermission");

另外,您可以在发送广播时使用setPackage(String)将广播限制为与指定包匹配的一组应用程序。 在清单文件中将android:exported设置为false将排除从您的应用程序外部接收到的广播。

端到端加密

了解HTTPS的局限性对于保护网络通信非常重要。 在大多数HTTPS实现中,加密在服务器处终止。 例如,您与公司服务器的连接可能是通过HTTPS进行的,但是一旦该流量到达服务器,它便不会被加密。 然后,可以通过建立另一个HTTPS会话或通过不加密发送它来将其转发到其他服务器。 公司能够查看已发送的信息,并且在大多数情况下,这是业务运营所必需的。 但是,这也意味着公司可以将信息未经加密地传递给第三方。

最近有一种趋势称为“端到端加密”,其中只有两个端部通信设备才能读取流量。 一个很好的例子是一个加密的聊天应用程序,其中两个移动设备通过服务器相互通信。 只有发送者和接收者可以阅读彼此的消息。

一个可以帮助您理解端到端加密的类比是,假设您希望某人向您发送一条只有您才能阅读的消息。 为此,请为他们提供一个带有打开的挂锁的盒子(公用密钥),同时保留挂锁的密钥(专用密钥)。 用户编写一条消息,将其放入框中,锁定挂锁,然后将其发送回给您。 只有您可以阅读该消息,因为您是唯一拥有解锁挂锁钥匙的人。

通过端到端加密,两个用户可以互相发送密钥。 服务器仅提供通信服务,但无法读取通信内容。 尽管实现细节不在本文讨论范围之内,但这是一项强大的技术。 如果您想了解更多有关此方法的信息,那么一个很好的起点是开源Signal项目GitHub存储库

结论

有了GDPR之类的所有新隐私法,安全性变得越来越重要。 这通常是移动应用程序开发中被忽略的方面。

翻译自: https://code.tutsplus.com/tutorials/securing-communications-on-android--cms-31596

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值