Skip to content

Commit ceb253e

Browse files
Add qhelp
1 parent 749ecab commit ceb253e

File tree

4 files changed

+95
-0
lines changed

4 files changed

+95
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
Certificate pinning is the practice of only trusting a specific set of SSL certificates, rather than those that the device trusts by default.
7+
In Android applications, it is reccomended to use certificate pinning when communicating over the network,
8+
in order to minimize the risk of machine-in-the-middle attacks from a comprimised CA.
9+
</overview>
10+
11+
<recommendation>
12+
<p>
13+
The easiest way to implement certificate pinning is to declare your pins in a <code>network-security-config</code> XML file.
14+
This will automatically provide certificate pinning for any network connection made by the app.
15+
</p>
16+
<p>
17+
Another way to implement certificate pinning is to use the `CertificatePinner` from the `okhttp` library.
18+
</p>
19+
<p>
20+
A final way to implement certificate pinning is to use a <code>TrustManager</code>, initialized from a <code>KeyStore</code> loaded with only the neccesary certificates.
21+
</p>
22+
23+
</recommendation>
24+
25+
<example>
26+
<p>
27+
In the first (bad) case below, a network call is performed with no certificate pinning implemented.
28+
The other (good) cases demonstrate the different ways to implement certificate pinning.
29+
</p>
30+
<sample src="AndroidMissingCertificatePinning1.java" />
31+
<sample src="AndroidMissingCertificatePinning2.xml" />
32+
<sample src="AndroidMissingCertificatePinning3.java" />
33+
</example>
34+
35+
<references>
36+
<li>
37+
OWASP Mobile Security: <a href="https://mobile-security.gitbook.io/mobile-security-testing-guide/android-testing-guide/0x05g-testing-network-communication#testing-custom-certificate-stores-and-certificate-pinning-mstg-network-4">Testing Custom Certificate Stores and Certificate Pinning (MSTG-NETWORK-4)</a>
38+
</li>
39+
<li>
40+
Android Developers: <a href="https://developer.android.com/training/articles/security-config">Network security configuration</a>
41+
</li>
42+
<li>
43+
OkHttp: <a href="https://square.github.io/okhttp/4.x/okhttp/okhttp3/-certificate-pinner/">CertificatePinner</a>
44+
</li>
45+
</references>
46+
</qhelp>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// BAD - By default, this network cal does not use certificate pinning
2+
URLConnection conn = new URL("https://example.com").openonnection();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!-- GOOD: Certificate pinning implemented via a Network Security Config file -->
2+
3+
<!-- In AndroidManifest.xml -->
4+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
5+
package="com.example.app">
6+
7+
<application android:networkSecurityConfig="@xml/NetworkSecurityConfig">
8+
...
9+
</application>
10+
11+
</manifest>
12+
13+
<!-- In res/xml/NetworkSecurityConfig.xml -->
14+
<network-security-config>
15+
<domain-config>
16+
<domain>good.example.com</domain>
17+
<pin-set expiration="2038/1/19">
18+
<pin digest="SHA-256">...</pin>
19+
</pin-set>
20+
</domain-config>
21+
</network-security-config>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// GOOD: Certificate pinning implemented via okhttp3.CertificatePinner
2+
CertificatePinner certificatePinner = new CertificatePinner.Builder()
3+
.add("example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
4+
.build();
5+
OkHttpClient client = new OkHttpClient.Builder()
6+
.certificatePinner(certificatePinner)
7+
.build();
8+
9+
client.newCall(new Request.Builder().url("https://example.com").build()).execute();
10+
11+
12+
13+
// GOOD: Certificate pinning implemented vis a TrustManager
14+
KeyStore keyStore = KeyStore.getInstance("BKS");
15+
keyStore.load(resources.openRawResource(R.raw.cert), null);
16+
17+
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
18+
tmf.init(keyStore);
19+
20+
SSLContext sslContext = SSLContext.getInstance("TLS");
21+
sslContext.init(null, tmf.getTrustManagers(), null);
22+
23+
URL url = new URL("http://www.example.com/");
24+
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
25+
26+
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());

0 commit comments

Comments
 (0)