Network Security Configuration
Problem: SSL Certificate Errors
-
SSLHandshakeException
and kin
- Unrecognized certificate
- Self-signed certificate
-
Non-Solution: Accept-all
TrustManager
- Readily enables interception attacks
- Gets you banned from the Play Store
Enter Network Security Configuration
- Create XML resource with "use this certificate" rule
- Add
android:networkSecurityConfig
on <application>
to manifest
- It Just Works™
OK, There's One Problem
- Network security configuration debuted with Android 7.0
- Rules will be ignored on older versions of Android
I Can Haz Backport?
TrustKit-Android
https://github.com/datatheorem/TrustKit-Android
- Limited subset of rules
-
Requires manual integration with HTTP client API
HttpURLConnection
- OkHttp3
- Cleanroom implementation from spec
- Works to API Level 17
I Can Haz Backport?
CWAC-NetSecurity
https://github.com/commonsguy/cwac-netsecurity
- Supports most of the rules
-
Requires manual integration with HTTP client API
HttpURLConnection
- OkHttp3
- True backport, based on official AOSP code
- Works to API Level 17
Using CWAC-NetSecurity
- Set up standard network security configuration
- Add a
<meta-data>
element your manifest
- Add library to
build.gradle
new TrustManagerBuilder().withManifestConfig(ctxt)
- Tie the
TrustManagerBuilder
into your HTTP client
Configuration XML
<domain-config>
: rules for a particular domain/set of sub-domains
<base-config>
: baseline rules, if any
<debug-overrides>
: rules only for debuggable builds
Debug-Only Behavior
- Put rules in
<debug-overrides>
- Example: self-signed certificate only for debug builds
Self-Signed Certificate
- Create a
raw
resource with CRT or PEM file
- Add
<certificates src="@raw/...">
without anything else to configuration
- Skipping
<certificates src="system">
blocks all default CAs
Limiting Possible Authorities
- Create a
raw
resource with the root certificate of that authority
- Add
<certificates src="@raw/...">
without anything else to configuration
- Skipping
<certificates src="system">
blocks all default CAs
- IOW, same as self-signed, just with CA's root certificate
Banning Cleartext Traffic
- Native 7.0:
cleartextTrafficPermitted="false"
on a configuration element to ban for that scope
- Native 6.0:
android:usesCleartextTraffic="false"
on <application>
- CWAC-NetSecurity: native 7.0 approach works for OkHttp3 integration
Pinning Certificates
- Create a
<pin-set>
element in configuration
- Add 1+ child
<pin>
with certificate hash via openssl x509 -in server.crt -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
- Decide on expiration date, if any (fails open after that date)
CWAC-NetSecurity: Flexible Configurations
Or, Testing Manifest-Declared Stuff is Painful
- Use
withConfig()
, supplying a Context
and the XML resource ID
-
Benefits
- Can choose different resources at runtime based on situation
- Always uses the backport, for consistency across OS versions
CWAC-NetSecurity: Certificate Memorization
Basically, On-The-Fly Soft Pinning
- If enabled, default is "trust on first use" (TOFU)
- If certificate received does not match certificate we have seen before, custom exception
-
You prompt user for what to do
- Yes, it's OK — IT warned me about this
- Um, let's use it for now, but bug me again later
- Abandon ship! Abandon ship!
Questions?