Forum Discussion

Philip_Jonsson_'s avatar
Philip_Jonsson_
Icon for Altostratus rankAltostratus
Oct 23, 2018

Extracting SSL Certificate Issuer from Server Side Connection

Hello!

 

I'm currently trying to build an iRule to extract the SSL Certificate Issuer from the Server Side Connection. All of the examples I have seen is based on the Client Side.

 

To give you some background, there is currently a bug in BIG-IP SWG where it actually intercepts the SSL session when its specifically configured not to. We have mitigate the problem using an iRule but the problem still occurs, yet more uncommon. Capturing evidence of this is difficult but I figure we can at least create a log entry whenever the certificate is signed by the SWG, thus, we are intercepting the SSL session.

 

When capturing the error using tcpdump, in Wireshark, I want specifically this information:

 

 

You can clearly see here that *.fz.se is signed by my SWG. Having a log entry created for this would give us an indication of how often the problem occurs.

 

Using iCall to trigger a tcpdump would be even better but I think at this point it will be too late to run a tcpdump.

 

5 Replies

  • So this is a forward proxy use case, yes? Where SSLFWD is re-signing the remote server cert. And you want to log the issuer of the forged server certificate (which should be the F5 itself)?

     

  • Exactly Kevin. We have set up a Transparent SSL Forwarding Solution with the default action of SSL Bypass. However, due to the bug documented in the bug: id 673357 "SWG puts flow in intercept when session is not found", the SWG is still intercepting the SSL Session.

     

    It happens when the APM Session is being created. This is solved by an iRule that manually creates the APM session in the CLIENT_ACCEPTED event.

     

    So the signer of the certificate should by default, always be the original certificate authority.

     

    Even with this iRule, we intermittently hit this problem. I have the exact same environment setup in my home and due to the low traffic amount, it happens very seldom. What I want is to have the BIG-IP log whenever the issuer is the SWG, meaning, we are hitting the bug. I can use that myself and also in the customer environment.

     

    I have tried creating an iRule using the SSL::cert issuer command but the wiki says it's only applicable on the Client side which won't work in my case.

     

    The data should be extractable from the SERVER_DATA event but with my limited iRule knowledge, it will be quite difficult to setup. Been Googling like crazy but only found examples from a Client Side perspective with standard commands.

     

  • Well no. SERVER_DATA is a server-side event and typically triggers with a TCP::collect in the SERVER_CONNECTED event, which itself is triggered on a server side (node to BIG-IP) TCP handshake. The issue here is that you're looking for traffic coming from the BIG-IP, and aside for a few exceptions, there aren't iRule events for traffic leaving the BIG-IP. In other words, anything you do in SERVER_DATA is relative to traffic coming from the server, which in this case is the remote Internet host.

    The only option you really have for capturing client-side traffic coming from the BIG-IP to the client is to layer a VIP in front of this VIP. This external layered VIP wouldn't do any SSL, just simple TCP pass-through.

    when CLIENT_ACCEPTED {
        virtual internal_vip
    }
    

    But it would see all of the TLS traffic coming from the SSLFWD configuration and could extract that information, albeit with TCP binary iRules processing.

  • Ahh I forgot about that, it's the same with CLIENT_DATA right? You need a tcp::collect in the CLIENT_ACCEPTED event?

     

    Hmm.. I might be in luck then. In my own setup, I actually have a "core F5" configured with a Port-Specific Wildcard VS capturing HTTP/HTTPS traffic and sending off to the SWG. In that case, the SWG will be the SERVER and I should be able to extract it from the SERVER_DATA event. Correct?

     

    Do you know if there are any example iRule for this? My iRule skills are limited but when checking examples, I can usually put something together, script-kiddie style. :)

     

    But when I searched I couldn't find any.

     

  • The more I thought about this, the more I realized the layered iRule to extract the forged issuer name would be insanely complex and not so great for performance. So I came up with a less painful option that should still do the job. Originally you were asking to extract the value and compare it. In this simpler option, however, you can just look for the forged issuer value in the server's response.

    This gets applied to a layered VIP in front of the SSLFWD VIP, and does not do any TLS processing.

    when CLIENT_ACCEPTED {
        virtual [sslfwd vip name]
    }
    when SERVER_CONNECTED {
        TCP::collect
    }
    when SERVER_DATA {
        binary scan [TCP::payload] H* hex
        if { ( $hex starts_with "1603" ) and ( [regexp {1603[0-9]{2}[0-9a-z]{4}0b} $hex] ) } {
            log local0. "TEST: found server cert message"
            regexp {1603[0-9]{2}[0-9a-z]{4}0b.*} $hex dump
            if { [binary format H* $dump] contains "f5demolabs.com" } {
                log local0. "TEST: found re-signed cert"
            } else {
                log local0. "TEST: didn't find re-signed cert"
            }
        }
        TCP::release
        TCP::collect
    }
    

    I've left the log statements in for testing. So basically, the server's Certificate message can come in the same packet as the ServerHello message, or can come afterwards. And since you don't know which will happen, you have to do a release and collect to keep digging into the payload. This isn't optimal, so you may also want to define a variable that gets set once you find what you're looking for so that you can skip any further collects.

    binary scan [TCP::payload] H* hex
    

    Grab the server's payload and convert to hex.

    if { ( $hex starts_with "1603" ) and ( [regexp {1603[0-9]{2}[0-9a-z]{4}0b} $hex] ) } {
    

    All SSL handshake messages will start with "1603" (hex), and "[regexp {1603[0-9]{2}[0-9a-z]{4}0b} $hex]" looks for a specific pattern in the dumped hex: 1603 + a 2-digit value corresponding to the TLS minor version + a 4-character hex value corresponding to the message length + "0b" indicating that this is a Certificate message.

    regexp {1603[0-9]{2}[0-9a-z]{4}0b.*} $hex dump
    

    Now that you've found this, use a version of the same regexp to pull all of the hex data in the payload to the end.

    if { [binary format H* $dump] contains "f5demolabs.com" } {
    

    Internally convert this hex to ascii and look for your local issuer CA string. If the cert wasn't forged, this won't be there.

    Admittedly this isn't a particularly optimal iRule, but it's much better than trying to extract the issuer name from the TLS handshake.