3

A recommendation has been made by the team penetration testing our Android app that we should pin the IP address of the server along with the already pinned certificate to add a layer defense against man in the middle attacks. My question is how could I pin the server IP address on an android app in addition to the already pinned certificate.

Currently I am using okhttp. I already have certificate pinning implemented, this is done when creating a singleton okhttpClient using okhttpClientBuilder. Code shown below. I would like to add backend server IP address pinning to this builder somehow.

val client = OkHttpClient.Builder()
            .addInterceptor { chain ->
                    val request = chain.request().newBuilder()
                        .addHeader(apiKeyHeader, apiKey)
                        .header("Content-Type", "application/json")
                        .build()
                chain.proceed(request)
            }.addInterceptor(loggingInterceptor)
            .certificatePinner(CertificatePinUtil.createOkHttpCertPinner())
            .build()

Any recommendations around how to implement IP pinning would be helpful. Ideally we would do this using OkhttpClientBuilder or the android security configs. I do not want to implement any manual checking of the responses.

D. Maul
  • 341
  • 2
  • 11

2 Answers2

1

You can implement your own Dns, that has a hardcoded result for Dns.

https://github.com/yschimke/okurl/blob/master/src/main/kotlin/com/baulsupp/okurl/network/DnsOverride.kt#L15-24

  override fun lookup(hostname: String): List<InetAddress> {
    val override = overrides[hostname]

    if (override != null) {
      logger.fine("Using Dns Override ($hostname): $override")
      return listOf(InetAddress.getByName(override))
    }

    return dns.lookup(hostname)
  }
Yuri Schimke
  • 12,435
  • 3
  • 35
  • 69
0

There are quite a few different considerations that go into the process of setting up SSL Pinning. It's a bit beyond the scope of a Stack Overflow post, but there are a few good reads:

And let's not forget, here is a link to the official Android guide

OKHTTP example

String hostname = “publicobject.com”;

CertificatePinner certificatePinner = new CertificatePinner.Builder()
 .add(“publicobject.com”, “sha1/DmxUShsZuNiqPQsX2Oi9uv2sCnw=”)
 .add(“publicobject.com”, “sha1/SXxoaOSEzPC6BgGmxAt/EAcsajw=”)
 .add(“publicobject.com”, “sha1/blhOM3W9V/bVQhsWAcLYwPU6n24=”)
 .add(“publicobject.com”, “sha1/T5x9IXmcrQ7YuQxXnxoCmeeQ84c=”)
 .build();

OkHttpClient client = new OkHttpClient();
client.setCertificatePinner(certificatePinner);

Request request = new Request.Builder()
      .url(“https://” + hostname)
      .build();
    client.newCall(request).execute();

OkHttpSSLPinning.java hosted with ❤ by GitHub - ref: http://square.github.io/okhttp/

Update: You have to use the domain itself because the SSL certificates are generally given to domain names and don’t include specific IP. It is possible to issue the cert for the IP but it’s not common practice. (Accessing https sites with IP address)

The point of using the pinning is to ensure there is no MitM attack when resolving the SSL handshake.

Sinandro
  • 2,426
  • 3
  • 21
  • 36
Hermes
  • 2,828
  • 2
  • 14
  • 34
  • SSL pinning is already implemented. Post has been edited to more clearly convey this. What I am trying to achieve is pin the actual IP address of the backend server on top of the already implemented cert pinning. – D. Maul Jun 25 '19 at 22:21
  • Updated answer to reflect your comment. – Hermes Jun 26 '19 at 00:11