Forum Discussion

kazeem_yusuf1's avatar
kazeem_yusuf1
Icon for Nimbostratus rankNimbostratus
Aug 01, 2018

An Irule for Client Ssl Profile that Allows Unassigned TLS Extension Values (17516)

Hello Community,

 

I have a requirement to allow enriched https header enrichment. The SSL negotiation (I'm doing ssl termination on F5) fails because the enriched header from client contains reserved tls extension values. (https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtmltls-extensiontype-values-1).

 

The Client Hello request in the SSL Handshake was captured and contained an Extensions list, which included a reserved TLS Extension value (17156), which the F5 isn't presenting in Server Hello.

 

I need an irule that can allow that Extension to be added on the client ssl profile so the ssl handshake doesn't fail.

 

  • I added this irule, it created an extension actually, but there was no data under it.

     

    when CLIENTSSL_CLIENTHELLO { set my_ext "Hello world!" set my_ext_type 17516 SSL::extensions insert [binary format S1S1a* $my_ext_type [string length $my_ext] $my_ext] }

     

  • Is this extension inserted by a public tool or are you writing your SSL client?

     

    your code try to insert the extension in CLIENTHELLO packet

     

    Do you want to insert it in SERVERHELLO packet?

     

  • If you're trying to reflect the client's MSISDN extension to the server, you definitely want to use the SERVERSSL_CLIENTHELLO_SEND event. It does not require forward proxy to use this event.

     

    when SERVERSSL_CLIENTHELLO_SEND {
        set msisdn "foobar"
        set bin [binary format S1S1S1S1ca* 17516 [expr [string length ${msisdn}] + 5] [expr [string length ${msisdn}] + 3] 0 [string length ${msisdn}] ${msisdn}]   
        SSL::extensions insert $bin
    }
    

     

      • Stan_PIRON_F5's avatar
        Stan_PIRON_F5
        Icon for Employee rankEmployee

        You can try this to catch and remove this extension from CLIENT_HELLO packet (not tested)

        it will then insert it in server side TLS handshake

         

        when CLIENT_ACCEPTED {
            set tls_extension_17516 ""
            SSL::disable   
            TCP::collect
        }
         
        when CLIENT_DATA {
            # Store TCP Payload up to 2^14 + 5 bytes (Handshake length is up to 2^14)
            set payload [TCP::payload 16389]
            set payloadlen [TCP::payload length]
            
            # If valid TLS 1.X CLIENT_HELLO handshake packet
            if { [binary scan $payload cH4ScH6H4x32c tls_record_content_type tls_version tls_recordlen tls_handshake_action tls_handshakelen_hex tls_handshake_version tls_handshake_sessidlen] == 7 && \
                ($tls_record_content_type == 22) && \
                ([string match {030[1-3]} $tls_version]) && \
                ($tls_handshake_action == 1) && \
                ($payloadlen == ($tls_recordlen & 0xffff )+5)} {
                
                # store in a variable the handshake length
                #set tls_handshakelen [expr 0x$tls_handshakelen_hex]
                scan $tls_handshakelen_hex %x tls_handshakelen
                # store in a variable the handshake version
                set tls_handshake_prefered_version $tls_handshake_version
         
                # skip past the session id
                set record_offset [expr {44 + ($tls_handshake_sessidlen & 0xff)}]
         
                # skip past the cipher list
                binary scan $payload @${record_offset}S tls_ciphlen
                set record_offset [expr {$record_offset + 2 + ($tls_ciphlen & 0xffff)}]
         
                # skip past the compression list
                binary scan $payload @${record_offset}c tls_complen
                set record_offset [expr {$record_offset + 1 + ($tls_complen & 0xffff)}]
         
                # check for the existence of ssl extensions
                if { ($payloadlen > $record_offset) } {
                    # skip to the start of the first extension
                    set tls_extension_length_start $record_offset
                    binary scan $payload @${record_offset}S tls_extension_length
                    set record_offset [expr {$record_offset + 2}]
                    # Check if extension length + offset equals payload length
                    if {$record_offset + ($tls_extension_length & 0xffff) == $payloadlen} {
                        # for each extension
                        while { $record_offset < $payloadlen } {
                            binary scan $payload @${record_offset}SS tls_extension_type tls_extension_record_length
                            set tls_extension_record_length [expr {$tls_extension_record_length & 0xffff}]
                            if { $tls_extension_type == 17516 } {
                                # if it's extension type 17516
                                binary scan $payload @${record_offset}A[expr {$tls_extension_record_length +4}] tls_extension_17516
                                set ext_start $record_offset
                                set ext_len [expr {$tls_extension_record_length + 4}]
                                set record_offset [expr {$record_offset + $tls_extension_record_length + 4}]
                            } else {
                                # skip over other extensions
                                set record_offset [expr {$record_offset + $tls_extension_record_length + 4}]
                            }
                        }
                    }
                }
            }
            unset -nocomplain payload payloadlen tls_record_content_type tls_handshake_action tls_handshake_sessidlen record_offset tls_ciphlen tls_complen tls_extension_type tls_extension_record_length tls_supported_versions_length tls_supported_versions
            if {$tls_extension_17516 ne ""} {
                # remove extension from Payload
                TCP::payload replace $ext_start $ext_len ""
                # Change extension Length
                TCP::payload replace $tls_extension_length_start 2 [binary format S [expr {($tls_extension_length & 0xffff) - $ext_len}]]
                # Change Handshake Length
                TCP::payload replace 6 3 [binary format H6 [format %06X [expr {$tls_handshakelen - $ext_len}]]]
                # Change Message Length
                TCP::payload replace 3 2 [binary format S [expr {($tls_recordlen & 0xffff) - $ext_len}]]
            }
            SSL::enable
            TCP::release
        }
         
        when SERVERSSL_CLIENTHELLO_SEND {
            if { $tls_extension_17516 ne "" } {
                SSL::extensions insert $tls_extension_17516
            }
        }

         

         

  • Hum ok....DO you have a summary of what you have propose and the purpose please in order to understand

     

    • Stan_PIRON_F5's avatar
      Stan_PIRON_F5
      Icon for Employee rankEmployee

      The goal of this code is:

      • disable SSL profile on client side to disable TLS inspection before the code ends
      • binary search the expected extension
      • save in variable tls_extension_17516 the content of extension type 17516
      • save in variable ext_start the index of beginning of extension 17516
      • save in variable ext_len the extension 17516 length
      • replace in payload the extension with no value (from ext_start with length ext_len)

       

      missing in the code :

      • change extension length to new value
      • change handshake length to new value

       

      I will update the code with missing commands later.

      • Stan_PIRON_F5's avatar
        Stan_PIRON_F5
        Icon for Employee rankEmployee

        I just updated the code above.

         

        Can you try it and update this thread?