Certificate pinning 101

Lightning talk

Xavier Rubio Jansana

 @teknik_tdr
 https://xrubio.com
 https://github.com/xrubioj/

Summary

  • What?
  • Why?
  • How SSL/TLS works
  • MiTM Attacks
  • Certificate pinning 101
  • Security considerations

What?

Network security technique

Why?

Avoid MiTM attacks 😱

Implications

  • Stealing app secrets
  • Stealing user secrets
  • Subverting communication
    (e.g. change delivery address)

How SSL/TLS works

HTTPS Connection

Certificate

Certificate

Certificate vs Signature

Subject Public Key Info

Certificate name validation

Certificate chain validation

Root CAs

  • Settings → Security → Trusted certificates
  • System vs User

MiTM Attacks

  • Root CA injection 😈
  • CA insuficient validation → rogue certificate 😐
  • Self-signed certificates → validation disabled 🚨😅

Certificate pinning 101

OkHttp


					val hostname = "*.google.com"
					val certificatePinner = CertificatePinner.Builder()
					      .add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
					      .build()
					val client = OkHttpClient.Builder()
					      .certificatePinner(certificatePinner)
					      .build()
					
Exception:
javax.net.ssl.SSLPeerUnverifiedException: Certificate pinning failure!
   Peer certificate chain:
     sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=: CN=publicobject.com, OU=PositiveSSL
     sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=: CN=COMODO RSA Secure Server CA
     sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=: CN=COMODO RSA Certification Authority
     sha256/lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=: CN=AddTrust External CA Root
   Pinned certificates for publicobject.com:
     sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
   at okhttp3.CertificatePinner.check(CertificatePinner.java)
   at okhttp3.Connection.upgradeToTls(Connection.java)
   at okhttp3.Connection.connect(Connection.java)
   at okhttp3.Connection.connectAndSetOwner(Connection.java)

Android N


						<?xml version="1.0" encoding="utf-8"?>
						<network-security-config>
						    <domain-config>
						        <domain includeSubdomains="true">appmattus.com</domain>
						        <pin-set>
						            <pin digest="SHA-256">4hw5tz+scE+TW+mlai5YipDfFWn1dqvfLG+nU7tq1V8=</pin>
						            <pin digest="SHA-256">YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=</pin>
						        </pin-set>
						    </domain-config>
						</network-security-config>
					
AndroidManifest.xml:

							<?xml version="1.0" encoding="utf-8"?>
							<manifest>
							    <application
							        android:networkSecurityConfig="@xml/network_security_config"android:networkSecurityConfig="@xml/network_security_config">
							        <!-- ... -->
							    </application>
							</manifest>
						

Backport

CWAC-NetSecurity https://github.com/commonsguy/cwac-netsecurity

"Allows the same XML configuration to be used, going back to API Level 17 (Android 4.2)"

With some manual work... 🤷‍♂️

How to react

  • Hard failure
  • Soft failure

Strategies

  • Hardcoded pins
  • Accept on first access
  • Get pins from server → inception! 🙃

Security considerations

⚠️ Hide your secrets!

See "Android security basics" talk by Krzysztof Kocel https://www.meetup.com/Barcelona-Android-Developer-Group/events/244107028/

References

Questions? 🤔

Thanks! 🎉

Xavier Rubio Jansana

 @teknik_tdr
 https://xrubio.com
 https://github.com/xrubioj/

This talk is available at:
https://xrubio.com/talks/talk-lightning-certificate-pinning/