MASTG-TEST-0022:测试自定义证书存储和证书锁定
已弃用测试
此测试已**弃用**,不应再使用。**原因**:MASTG V2 中提供新版本
请查看以下涵盖此 v1 测试的 MASTG v2 测试
概述¶
静态分析¶
网络安全配置¶
检查网络安全配置,查找任何 <pin-set>
元素。检查它们的 expiration
日期(如果有)。如果过期,证书锁定将对受影响的域禁用。
测试提示:如果证书锁定验证检查失败,则应在系统日志中记录以下事件(请参阅 监控系统日志)
I/X509Util: Failed to validate the certificate chain, error: Pin verification failed
TrustManager¶
实施证书锁定涉及三个主要步骤
- 获取所需主机的证书。
- 确保证书为 .bks 格式。
- 将证书锁定到默认 Apache Httpclient 的实例。
为了分析证书锁定的正确实施,HTTP 客户端应加载 KeyStore
InputStream in = resources.openRawResource(certificateRawResource);
keyStore = KeyStore.getInstance("BKS");
keyStore.load(resourceStream, password);
加载 KeyStore 后,我们可以使用 TrustManager,它信任我们的 KeyStore 中的 CA
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses the TrustManager
// SSLContext context = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
应用的实施方式可能不同,仅针对证书的公钥、整个证书或整个证书链进行锁定。
网络库和 WebViews¶
使用第三方网络库的应用程序可能会利用这些库的证书锁定功能。例如,可以使用 CertificatePinner
设置 okhttp
OkHttpClient client = new OkHttpClient.Builder()
.certificatePinner(new CertificatePinner.Builder()
.add("example.com", "sha256/UwQAapahrjCOjYI3oLUx5AQxPBR02Jz6/E2pt0IeLXA=")
.build())
.build();
使用 WebView 组件的应用程序可能会使用 WebViewClient 的事件处理程序,对每个请求进行某种“证书锁定”,然后再加载目标资源。以下代码显示了一个验证示例
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient(new WebViewClient(){
private String expectedIssuerDN = "CN=Let's Encrypt Authority X3,O=Let's Encrypt,C=US;";
@Override
public void onLoadResource(WebView view, String url) {
//From Android API documentation about "WebView.getCertificate()":
//Gets the SSL certificate for the main top-level page
//or null if there is no certificate (the site is not secure).
//
//Available information on SslCertificate class are "Issuer DN", "Subject DN" and validity date helpers
SslCertificate serverCert = view.getCertificate();
if(serverCert != null){
//apply either certificate or public key pinning comparison here
//Throw exception to cancel resource loading...
}
}
}
});
或者,最好使用配置了锁定的 OkHttpClient,并让它作为代理覆盖 WebViewClient
的 shouldInterceptRequest
。
Xamarin 应用程序¶
使用 Xamarin 开发的应用程序通常会使用 ServicePointManager
来实施锁定。
通常会创建一个函数来检查证书,并将布尔值返回给 ServerCertificateValidationCallback
方法
[Activity(Label = "XamarinPinning", MainLauncher = true)]
public class MainActivity : Activity
{
// SupportedPublicKey - Hexadecimal value of the public key.
// Use GetPublicKeyString() method to determine the public key of the certificate we want to pin. Uncomment the debug code in the ValidateServerCertificate function a first time to determine the value to pin.
private const string SupportedPublicKey = "3082010A02820101009CD30CF05AE52E47B7725D3783B..."; // Shortened for readability
private static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors
)
{
//Log.Debug("Xamarin Pinning",chain.ChainElements[X].Certificate.GetPublicKeyString());
//return true;
return SupportedPublicKey == chain.ChainElements[1].Certificate.GetPublicKeyString();
}
protected override void OnCreate(Bundle savedInstanceState)
{
System.Net.ServicePointManager.ServerCertificateValidationCallback += ValidateServerCertificate;
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Main);
TesteAsync("https://security.claudio.pt");
}
在这个特定示例中,我们锁定了证书链的中间 CA。HTTP 响应的输出将在系统日志中可用。
可以在 MASTG 存储库中获取包含前面示例的示例 Xamarin 应用
解压缩 APK 文件后,使用像 dotPeak、ILSpy 或 dnSpy 这样的 .NET 反编译器来反编译存储在“Assemblies”文件夹中的应用 dll,并确认 ServicePointManager 的使用情况。
了解更多
- Xamarin 的证书和公钥锁定 - https://thomasbandt.com/certificate-and-public-key-pinning-with-xamarin
- ServicePointManager - https://msdn.microsoft.com/en-us/library/system.net.servicepointmanager(v=vs.110).aspx
Cordova 应用程序¶
基于 Cordova 的混合应用程序本身不支持证书锁定,因此使用插件来实现此目的。最常见的是 PhoneGap SSL 证书检查器。check
方法用于确认指纹,回调将确定后续步骤。
// Endpoint to verify against certificate pinning.
var server = "https://www.owasp.org";
// SHA256 Fingerprint (Can be obtained via "openssl s_client -connect hostname:443 | openssl x509 -noout -fingerprint -sha256"
var fingerprint = "D8 EF 3C DF 7E F6 44 BA 04 EC D5 97 14 BB 00 4A 7A F5 26 63 53 87 4E 76 67 77 F0 F4 CC ED 67 B9";
window.plugins.sslCertificateChecker.check(
successCallback,
errorCallback,
server,
fingerprint);
function successCallback(message) {
alert(message);
// Message is always: CONNECTION_SECURE.
// Now do something with the trusted server.
}
function errorCallback(message) {
alert(message);
if (message === "CONNECTION_NOT_SECURE") {
// There is likely a MITM attack going on, be careful!
} else if (message.indexOf("CONNECTION_FAILED") >- 1) {
// There was no connection (yet). Internet may be down. Try again (a few times) after a little timeout.
}
}
解压缩 APK 文件后,Cordova/Phonegap 文件将位于 /assets/www 文件夹中。“plugins”文件夹将使您可以看到使用的插件。我们需要在应用程序的 JavaScript 代码中搜索此方法以确认其使用情况。
动态分析¶
按照 测试端点身份验证 中的说明进行操作。如果这样做不会导致流量被代理,则可能意味着实际上实施了证书锁定,并且所有安全措施都已到位。对于所有域是否都发生同样的情况?
作为快速冒烟测试,您可以尝试使用 objection 中描述的 绕过证书锁定 来绕过证书锁定。objection 挂钩的锁定相关 API 应该出现在 objection 的输出中。
但是,请记住
- API 可能不完整。
- 如果没有挂钩任何内容,并不一定意味着应用程序未实施锁定。
在这两种情况下,应用程序或其某些组件可能以一种 objection 支持的方式实施自定义锁定。请查看静态分析部分以获取特定的锁定指示器和更深入的测试。