android - 使用 Google Cloud Endpoints 时如何避免中间人攻击?

标签 android ssl endpoints man-in-the-middle pinning

我目前正在编写我的第一个 Android 应用程序,并决定使用谷歌云端点。 我已按照以下文档保护我的后端端点方法:https://cloud.google.com/appengine/docs/java/endpoints/auth , https://cloud.google.com/appengine/docs/java/endpoints/gen_clients , https://cloud.google.com/appengine/docs/java/endpoints/consume_android

基本上,您必须为端点生成 WEB_CLIENT_ID 和 ANDROID_CLIENT_ID, 在您要保护的每个方法上添加一个参数 User,最后检查方法内部 用户不为空,否则抛出 OAuthRequestException。

我已经构建了客户端 android 库并在我的 android 应用程序中像这样配置它:

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
String accountName = preferences.getString(MainActivity.PREF_ACCOUNT_NAME, null);

GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(context,
                        "server:client_id:xxxxxxxxx-xxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com");

credential.setSelectedAccountName(accountName);

DataLoaderApi.Builder builder = new DataLoaderApi.Builder(AndroidHttp.newCompatibleTransport(),
                        new AndroidJsonFactory(), credential);

起初它似乎工作得很好,你不能在没有凭证的情况下使用后端方法。 (您将遇到 401 错误)

不幸的是,我注意到如果您使用像“Charles Proxy”这样的工具,仍然可以解密 https 请求/响应到后端端点 (https://www.charlesproxy.com/)。您只需在智能手机上安装 charles 代理证书并配置代理即可。

这是对同一问题的另一种描述: http://nickfishman.com/post/50557873036/reverse-engineering-native-apps-by-intercepting-network

现在你有了 android 应用程序使用的端点 url,你已经得到了每个请求中发送的所有参数和所有 header 属性,甚至是自动化属性 使用 token ,所以基本上您需要在应用程序中使用我的后端端点的所有信息。 :( 我知道 token 会在一段时间后过期,但与此同时您可以提取我的数据。

谷歌在谷歌云存储文档中谈到了这一点: https://cloud.google.com/storage/docs/concepts-techniques#bestpractices

“确保您使用验证服务器证书的 HTTPS 库。缺乏服务器证书验证会使您的应用程序容易受到中间人攻击或其他攻击。”

很好,但是当您使用由他们的工具生成的端点客户端库时,您也很容易受到攻击。

我知道有解决方案可以避免这个问题: https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning

但是我如何使用生成的端点客户端 android 库并避免中间人攻击?

最佳答案

创建您的自定义 KeyStore 并仅将系统证书放入其中。 Android系统证书可以从here获得.

创建 TrustManager 和 SSLSocketFactory,它们将只信任您刚刚创建的这个 KeyStore,引用自 this :

// Load CAs from an InputStream
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.crt"));
Certificate ca;
try {
    ca = cf.generateCertificate(caInput);
    System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
    caInput.close();
}

// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);

// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);

SSLSocketFactory ssf = context.getSocketFactory();

使用NetHttpTransport.Builder创建NetHttpTransport,并设置上面创建的SSLSocketFactory。然后您可以像往常一样使用端点方法构建器:

Api.Builder builder = new Api.Builder(objNetHttpTransport,
                    new AndroidJsonFactory(), credential);

这应该可行,唯一的问题是管理根证书。您需要定期发送更新。

关于android - 使用 Google Cloud Endpoints 时如何避免中间人攻击?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34104592/

相关文章:

redirect - Nginx:将 http://example.com 和 http://*.example.com 重定向到 https://example.com

c++ - SSL_CTX_set_tlsext_servername_callback 回调函数未被调用

ssl - Xamarin - Android - 手动验证服务器的 SSL 证书 ModernHttpClient

.net - .NET 3.5 中的 REST 友好 WCF 端点

android - 如何从内网加载PNG文件到Android中?

android - “如何在android中的textview上显示div html内容

java - 如何从方法更改静态类变量的值,然后从其他方法获取它?

wcf - 使用 NLB 在 IIS 中托管自定义 WCF

java - 是否可以使用一个端点运行两个 ws 实现?

javascript - Google Maps API NativeScript 自定义标记图标