0

I got the following exception on Fabric:

Non-fatal Exception: javax.net.ssl.SSLPeerUnverifiedException: Hostname assets.domain.com not verified:
    certificate: sha256/6NEXAaHJ2CAMKUOkWhMCwH9biv2QtAFsYMl0WqkocgM=
    DN: CN=apc.aptilo.com,OU=Domain Control Validated - RapidSSL(R),OU=See www.rapidssl.com/resources/cps (c)13,OU=GT19785026,2.5.4.5=#13204456444273427335456d62337a6151706e6e6d356744615556354b6a63696c44
    subjectAltNames: [apc.aptilo.com]
       at okhttp3.internal.connection.RealConnection.connectTls(SourceFile:250)
       at okhttp3.internal.connection.RealConnection.establishProtocol(SourceFile:198)
       at okhttp3.internal.connection.RealConnection.buildConnection(SourceFile:174)
       at okhttp3.internal.connection.RealConnection.connect(SourceFile:114)
       at okhttp3.internal.connection.StreamAllocation.findConnection(SourceFile:193)
       at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(SourceFile:129)
       at okhttp3.internal.connection.StreamAllocation.newStream(SourceFile:98)
       at okhttp3.internal.connection.ConnectInterceptor.intercept(SourceFile:42)
       at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:92)
       at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:67)
       at okhttp3.internal.cache.CacheInterceptor.intercept(SourceFile:109)
       at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:92)
       at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:67)
       at okhttp3.internal.http.BridgeInterceptor.intercept(SourceFile:93)
       at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:92)
       at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(SourceFile:124)
       at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:92)
       at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:67)
       at okhttp3.RealCall.getResponseWithInterceptorChain(SourceFile:170)
       at okhttp3.RealCall.access$100(SourceFile:33)
       at okhttp3.RealCall$AsyncCall.execute(SourceFile:120)
       at okhttp3.internal.NamedRunnable.run(SourceFile:32)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
       at java.lang.Thread.run(Thread.java:818)

And together with the security team we've realized that this is probably a case where the user opened our app connected to some hotel Wi-Fi and was branded with those pesky login pages. Only 2 users seem to be affected so far and we have many more users so it's not like this is a real man-in-the-middle attack.

As such, I want to validate the common name on the exception. If it matches our host, assets.domain.com, than it's a potential attack and I want to log the occurrence. If the CN is different, than I just want to suppress the error.

What are my options? I can only think of parsing the exception cause string and with a regex extract the CN=value part. But is there a better less error-prone solution?

tl;dr;

I want to extract the CN value from the SSLPeerUnverifiedException and compare it our valid hostname. What's the best way to achieve this?

rfgamaral
  • 16,546
  • 57
  • 163
  • 275

1 Answers1

1

With the limited sample you provide, it's something like this

"(?s)SSLPeerUnverifiedException:.*?(?<!\\S)CN=([^\\s,]+)(?=,)"

where capture group 1 contains the CN value.

Output:

 **  Grp 0 -  ( pos 35 , len 165 ) 
SSLPeerUnverifiedException: Hostname assets.domain.com not verified:
    certificate: sha256/6NEXAaHJ2CAMKUOkWhMCwH9biv2QtAFsYMl0WqkocgM=
    DN: CN=apc.aptilo.com  
 **  Grp 1 -  ( pos 186 , len 14 ) 
apc.aptilo.com  
  • Not sure what you mean with "limited sample", but that's all Fabric gives me, sorry. Thanks for the regex. I was hoping that there was some utility functions that could parse a `SSLPeerUnverifiedException` and convert into a `Certificate` and then I could safely check for the CN. But I guess nothing like that exists. This will have to do. – rfgamaral Sep 02 '16 at 18:44
  • Sorry couldn't narrow this down more. The only way to pull out parts of this (or any) exception is to look at the source code to see how it is generated. But, obviously if they don not publish it, they reserve the right to modify the generation without the hassle of keeping to some format. Good luck~ –  Sep 02 '16 at 19:00