如何在Android Volley中检测TLS版本

10

我的项目长期以来一直在使用Android Volley网络框架,但最近我在网上发现了一个SSL 3.0协议漏洞。

我想知道如何查找我的项目使用的TLS版本,以及如何确认库是否已更新。

这是我的源代码片段:

HttpStack stack = new HurlStack();
Network network = new BasicNetwork(stack);
mHttpRequestQueue = new RequestQueue(new NoCache(), network);
mHttpRequestQueue.start();

我认为关键点在于HurlStack类,它依赖于org.apache.http包,但我无法确定TLS/SSL配置位于何处。


没有 TLS 3.0,我猜你是指 SSL 3.0。 - Robert
@Robert 是的,SSL3和TLS1。 - Alex Wang
我追踪了源代码,只发现了这个:context = SSLContext.getInstance("TLS"); - Alex Wang
3个回答

20

您可以通过创建自定义的HTTPStack并在Volley.javaVolley.newRequestQueue(context, httpStack)方法中设置堆栈来修改Volley中使用的TLS版本。但是,这只需要针对Android 16-19版本进行。在v16之前,不支持TLS 1.2,在v19之后,默认启用TLS 1.2。因此,您应重点关注手动将TLS设置为1.2,以适用于Android 16-19版本。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
    && Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
    try {
      ProviderInstaller.installIfNeeded(getContext());
    } catch (GooglePlayServicesRepairableException e) {
      // Indicates that Google Play services is out of date, disabled, etc.
      // Prompt the user to install/update/enable Google Play services.
      GooglePlayServicesUtil.showErrorNotification(e.getConnectionStatusCode(), getContext());
      // Notify the SyncManager that a soft error occurred.
      syncResult.stats.numIOExceptions++;
      return;
    } catch (GooglePlayServicesNotAvailableException e) {
      // Indicates a non-recoverable error; the ProviderInstaller is not able
      // to install an up-to-date Provider.
      // Notify the SyncManager that a hard error occurred.
      syncResult.stats.numAuthExceptions++;
      return;
    }

    HttpStack stack = null;
    try {
      stack = new HurlStack(null, new TLSSocketFactory());
    } catch (KeyManagementException e) {
      e.printStackTrace();
      Log.d("Your Wrapper Class", "Could not create new stack for TLS v1.2");
      stack = new HurlStack();
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
      Log.d("Your Wrapper Class", "Could not create new stack for TLS v1.2");
      stack = new HurlStack();
    }
    requestQueue = Volley.newRequestQueue(context, stack);
} else {
  requestQueue = Volley.newRequestQueue(context);
}

接下来使用一个TLSSocketFactory类,它扩展了SSLSocketFactory类,就像Florian Krauthan在这里创建的那样,其中启用了v1.2 TLS协议:https://gist.github.com/fkrauthan/ac8624466a4dee4fd02f#file-tlssocketfactory-java


3
在我的4.4设备上运行之前,我还需要按照https://blog.dev-area.net/2015/08/17/protect-your-android-app-against-ssl-exploits/升级安全提供程序。 - Diederik
2
@Diederik的观点非常重要。代码必须处理安全代码提供者的更新。在我的情况下,即使安全提供者已经被另一个应用程序更新了,我仍然需要在自己的应用程序中包含代码才能使TLS正常工作。 - Ajji
4
@Ajji,我已更新答案,包括检查安全提供程序是否具有最新的更新。对于其他人,您可以在此处阅读官方文档以了解更多信息:https://developer.android.com/training/articles/security-gms-provider.html 这可以同步完成(如我的答案所示),也可以异步完成。但是,必须完成。 - w3bshark
Android 抱怨 HttpStack 已经过时。我实现了您链接中的异步版本,并且在 API 19 的模拟器上可以正常工作,而不需要 HttpStack 和 TLSSocketFactory。直接跳过这部分是否可行? - user10981072

1
在 Android 上使用的 TLS 版本主要取决于所使用的 Android 版本。Apache Volley 基于 Apache Http Client,后者基于 HttpsUrlConnection,因此使用标准的 SSL/TLS SSLSocketFactory。
在 Android 4.3 以下版本通常只支持 SSLv3 和 TLS 1.0。在更高版本中,TLS 1.1 和 1.2 通常被支持但被禁用。
从 Android 5 开始,TLS 1.1 和 TLS 1.2 默认被支持和启用

那么我在源代码中该在哪里找到TLS版本呢?你能指出具体位置吗? 我需要完全确认。 - Alex Wang
只要您不设置自定义SSLSocketFactory,您的代码就不会指定TLS版本。这一切都在Android API运行时代码中完成。 - Robert
应该有一种方法可以在Android版本16-20中启用Volley的TLS v1.2,因为它受支持但默认情况下未启用。您能否指向Volley文档,以便可能实现此操作?不幸的是,“所有这些都在Android API运行时代码中完成”并没有什么帮助。OkHttp库提供了设置TLS版本的功能:https://dev59.com/_l4b5IYBdhLWcg3wYAb6 - w3bshark

0
@w3bshark的回答对我很有帮助。但使用该代码之前,请确保您包含了更新安全提供程序的代码。在我的情况下,直到我更新了安全提供程序,TLS才能正常工作。以下是更新它的代码。
private void updateAndroidSecurityProvider() {
    try {
        ProviderInstaller.installIfNeeded(this);
    } catch (GooglePlayServicesRepairableException e) {
        Log.e("Test321", "PlayServices not installed");
    } catch (GooglePlayServicesNotAvailableException e) {
        Log.e("Test321", "Google Play Services not available.");
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接