Android SSL Certificate Pinning

Eniz Bilgin
4 min readOct 25, 2018

--

Mobil uygulama geliştirmede en önemli şeylerden biri de uzak sunucu ile güvenli iletişimdir. Çoğu zaman, uygulamanızla sunucu arasında hassas veriler göndermeniz gerekir. Örneğin mobil bankacılık uygulamalarını ele alın. İstediğiniz son şey, birilerinin banka hesap bilgilerini ele geçirmiş olmasıdır.

Günümüzde yaygın olarak HTTP temelli REST API mimarisi kullanılmaktadır. Bu iletişim modeli için en iyi koruma yöntemi TLS / SSL standardıdır. HTTP protokolü ve şifrelemenin birleşiminden HTTPS protokolü ortaya çıkmaktadır. HTTPS hizmeti istemci ile uzak sunucu arasında güvenli, şifreli iletişim kanalları sağlar.

Gizlilik, iletim katmanı (TCP) şifrelenerek sağlandığı için protokol seviyesinde (GET, PUT, POST, vb.) HTTP ve HTTPS arasında herhangi bir farklılık yoktur.

Geliştiriciler çoğu zaman uygulamalarını geliştirirken HTTPS protokolü ile iletişim sağlarlar. Böyle bir kullanım uzak sunucuda desteklediği takdirde TLS / SSL şifrelemesini sağlayacaktır. Ancak yeterince iyi bir güvenlik seviyesi sağlamayacaktır.

TLS standardı X509 sertifikalarına ve asimetrik şifrelemeye dayanmaktadır. Yani, sadece protokol adını değiştirmek, HTTPS yapmak şifrelemeyi etkinleştirir, ancak uygulama sunucu tarafından verilen her sertifikaya güvenir. Yani istemci ve sunucu arasındaki iletişimde araya giren birinin kendine ait sahte sertifikasını oluşturabileceği anlamına geliyor. Bu sertifika ile şifreli iletişimde araya girerek güvenlik zafiyeti oluşturur. Bu tür güvenlik saldırılarına Man-In-The-Middle adı verilir. Peki bu tarz saldırıları önlemek için ne yapmalıyız ?

Man in the middle (https://riis.com/wp-content/uploads/2017/09/FTCMITM-1.png)

Certificate Pinning

Bu tür saldırılardan korunmak için geliştiriciler Certificate Pinning yöntemini uygulamalıdır. İstemci tarafında sunucu sertifikası doğrulamasına bağlı bir yöntemdir. Bu doğrulama, mobil uygulama tarafında sunucu sertifikasının kullanılmasını gerektirir. Sunucu ile uygulama arasında bağlantı kurulurken, uygulama içindeki sertifika uzak sunucuda ki sertifika ile karşılaştırmalıdır. Bu doğrulama gerçekleştiği zaman uzak sunucu ve uygulama arasında bağlantı kurulur ve veri aktarımı başlar, aksi durumda güvenlik ihlali oluştuğu için uygulama tarafında bağlantı kesilmelidir.

Certificate Pinning ile yüksek düzeyde güvenlik sağlanmış olur. Android uygulamalar için güvenlik zafiyetinin tekrar oluşması oldukça zor bir durumdur. Ancak imkansız değildir. Uygulamanın decompile edilip içerisindeki sertifikanın devredışı bırakılması ve yeniden build edilip paketin oluşturulması oldukça kompleks bir durumdur.

Certificate Pinning yöntemi, uygulama içinde gömülü bir sertifika veya sertifikaya ait parmak izi ile çalıştığı için uzak sunucu tarafında sertifika değiştiği zaman uygulamanında güncellenmesi gerekmektedir.

Android uygulama geliştirirken SSL Certificate Pinning uygulamanının birçok yöntemi vardır.

OkHttpClient ve Retrofit

OkHttpClient kullandığınız uygulamalarda CertificatePinner sınıfını ile SSL Pinning’i uygulayabilirsiniz. CertificatePinner ile sertifikaya ait parmak izi değerini (sha256) aşağıdaki şekilde ekleyebilirsiniz.

@ApplicationScope
@Provides
fun provideClient(sslPinning: SSLPinning): OkHttpClient {

val pinner = CertificatePinner.Builder()
.add("*.example.net", "sha256/xblablablablaaaaaaa?=")
.build()

return OkHttpClient.Builder()
.certificatePinner(pinner)
.build()
}
@ApplicationScope
@Provides
fun provideRetrofit(client: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl("https://aa.example.net/")
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(MoshiConverterFactory.create())
.build()
}

Kullandığımız REST api içindeki sertifikaya ait parmak izi (sha256) değerini SSL-Labs sitesinde hostname ile öğrenebilirsiniz.

Bir diğer yöntem ise openssl kullanarak sertifikaya ait bu değeri aşağıdaki şekilde öğrenebilirsiniz.

openssl x509 -pubkey -inform der -in ~/Desktop/cert.cer | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64

Bu değerler (sha256) sertifikanının publicKey değerine aittir.

Sertifikaya ait parmak izi değerini (sha256) bu şekilde bulmak yerine, uygulama içinde de bulup aşağıdaki şekilde kullanabilirsiniz.

  1. Sertifikayı proje içindeki resource altına eklemelisiniz.
/res/raw

2. Sertifikayı kullanmanızı sağlayacak yazdığımız SSLPinning sınıfını kullanabilirsiniz.

@ApplicationScope
@Provides
fun provideSSLPining(application: SampleApplication): SSLPinning {

val sslPinning: SSLPinning = SSLPinningImpl()
// init certificate
sslPinning.initSSLWithCertificate(application.applicationContext, R.raw.blabla)
return sslPinning
}


@ApplicationScope
@Provides
fun provideClient(sslPinning: SSLPinning): OkHttpClient {

val pin = CertificatePinner.pin(sslPinning.getCertificate())

val certificatePinner = CertificatePinner.Builder()
.add("*.example.net", pin)
.build()

return OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()
}

SSLPinning sınıfı, BKS ve PKCS12 türündeki sertifikalarlada bu işlemin uygulanmasını sağlamaktadır.

@ApplicationScope
@Provides
fun provideSSLPining(application: SampleApplication): SSLPinning {

val sslPinning: SSLPinning = SSLPinningImpl()
// init certificate

sslPinning.initSSLWithertificateType(application.applicationContext, R.raw.bksbks,"password","BKS")

return sslPinning
}

Ayrıca OkHttpClient ‘e sslSocketFactory ekleyerek de bu işlemi aşağıdaki şekilde yapabiliriz.

@ApplicationScope
@Provides
fun provideClient(sslPinning: SSLPinning): OkHttpClient {

return OkHttpClient.Builder()
.sslSocketFactory(sslPinning.getSSLSocketFactory(),sslPinning.getTrustManager())
.build()
}

Volley

SSLPinning sınıfını, sertifikayı projeye ekledikten sonra Volley kütüphanesi ile aşağıdaki şekilde kullanabilirsiniz.

Herhangi bir network kütüphanesi kullanmadığınız zaman ise SSL Certificate Pinning’i uygulamasınu aşağıda görebilirsiniz.

val urlConnection = url.openConnection() as HttpsURLConnectionurlConnection.sslSocketFactory = sslPinning.getSSLSocketFactory()

Özet

Hangi yöntemi kullanacağınız aslında çok önemli değildir, ancak her zaman SSL Certificate Pinning’in zorunlu olduğunu unutmayın. Gerçekten güvenli bir ağ oluşturmanın tek yolu budur. Bu sebeple OWASP Mobile ekibi de MiTM saldırısı için koruma yöntemi olarak SSL Certificate Pinning’i önerir.

--

--