Technical Articles
F5 SMEs share good practice.
cancel
Showing results for 
Search instead for 
Did you mean: 
Custom Alert Banner
Nir_Zigler_7297
Historic F5 Account

Recently we’ve witnessed yet another earth shattering vulnerability in a popular and very fundamental service.
Dubbed Winshock, it follows and joins the Heartbleed, Shellshock and Poodle in the pantheon of critical vulnerabilities discovered in 2014.
Winshock (CVE-2014-6321) earns a 10.0 CVSS score due to being related to a common service such as TLS, and pot...

SChannel

From MSDN:
Secure Channel, also known as Schannel, is a security support provider (SSP) that contains a set of security protocols that provide identity authentication and secure, private communication through encryption.

Basically, SChannel is Microsoft’s implementation of TLS, and it is used in various MS-related services that support encryption and authentication – such as: Internet Information Services (IIS), Remote Desktop Protocol, Exchange and Outlook Web Access, SharePoint, Active Directory and more.

Naturally, SChannel also contains implementation for the TLS handshake protocol, which is performed before every secure session is established between the client and the server.

The TLS Handshake

The following image demonstrates how a typical TLS handshake looks like:

Image source: http://www-01.ibm.com/support/knowledgecenter/SSFKSJ_7.1.0/com.ibm.mq.doc/sy10660_.htm?lang=en

The handshake is used for the client and the server to agree on the terms of the connection.
The handshake is conducted using messages, for the purpose of authenticating between the server and the client, agreeing on cipher suites, and exchanging public keys using certificates.
Each type of message is passed on the wire as a unique “TLS Record”.
Several messages (TLS records) may be sent over one packet.

Some of the known TLS records are the following:

  • Client Hello – The client announces it would like to initiate a connection with the server. It also presents all the various cipher suites it can support. This record may also have numerous extensions used to provide even more data.

  • Server Hello – The server acknowledges the Client Hello and presents its own information.

  • Certificate Request – In some scenarios, the client is required to present its certificate in order to authenticate itself. This is known as two-way authentication (or a mutual authentication). The Certificate Request message is sent by the server and forces the client to present a valid certificate before the handshake is successful.

  • Certificate – A message used to transfer the contents of a certificate, including subject name, issuer, public key and more.

  • Certificate Verify – Contains signed value using the client’s private key. It is presented by the client along with their certificate during a 2-way handshake, and serves as a proof of the client actually holding the certificate they claim to.

    SChannel Vulnerabilities

    Two vulnerabilities were found in the way SChannel handles those TLS records.

    One vulnerability occurs when parsing the “server_name” extension of the Client Hello message. This extension is typically used to specify the host name which the client is trying to connect to on the target server. In some way this is similar to the HTTP “Host” header.
    It was found that SChannel will not properly manage memory allocation when this record contains more than one server name.
    This vulnerability leads to denial of service by memory exhaustion.

    The other vulnerability occurs when an invalid signed value is presented inside a Certificate Verify message. It was found that values larger than what the server expects will be written to the memory beyond the allocated buffer scope.
    This behavior may result in a potential remote code execution.

    Mitigation with BIG-IP iRules

    SSL offloading using BIG-IP is inherently not vulnerable as it does not relay vulnerable messages to the backend server. However, in a “pass-through” scenario, where all the TLS handshake messages are being forwarded without inspection, backend servers may be vulnerable to these attacks.

    The following iRule will detect and mitigate attempts to exploit above SChannel vulnerabilities:

    when CLIENT_ACCEPTED {
     TCP::collect
     set MAX_TLS_RECORDS 16
     set iPacketCounter 0
     set iRecordPointer 0
     set sPrimeCurve ""
     set iMessageLength 0
    }
    when CLIENT_DATA {
     #log local0. "New TCP packet. Length [TCP::payload length]. Packet Counter $iPacketCounter"
     set bScanTLSRecords 0
     if { $iPacketCounter == 0 } {
      binary scan [TCP::payload] cSS tls_xacttype tls_version tls_recordlen
      if { [info exists tls_xacttype] && [info exists tls_version] && [info exists tls_recordlen] } {
       if { ($tls_version == "769" || $tls_version == "770" || $tls_version == "771") && $tls_xacttype == 22 } {
        set bScanTLSRecords 1
       }
      }
     }
    
     if { $iPacketCounter > 0 } {
      # Got here mid record, collect more fragments
      #log local0. "Gather. tls rec $tls_recordlen, ptr $iRecordPointer"
      if { [expr {$iRecordPointer + $tls_recordlen + 5}] <= [TCP::payload length] } {
       #log local0. "Full record received"
       set bScanTLSRecords 1
      } else {
       #log local0. "Record STILL fragmented"
       set iPacketCounter [expr {$iPacketCounter + 1}]
       TCP::collect
      }
     }
    
     if { $bScanTLSRecords } {
       # Start scanning records
       set bNextRecord 1
       set bKill 0
       while { $bNextRecord >= 1 } {
        #log local0. "Reading next record. ptr $iRecordPointer"
        binary scan [TCP::payload] @${iRecordPointer}cSS tls_xacttype tls_version tls_recordlen
        #log local0. "SSL Record Type $tls_xacttype , Version: $tls_version , Record Length: $tls_recordlen"
        if { [expr {$iRecordPointer + $tls_recordlen + 5}] <= [TCP::payload length] } {
         binary scan [TCP::payload] @[expr {$iRecordPointer + 5}]c tls_action
         if { $tls_xacttype == 22 && $tls_action == 1 } {
          #log local0. "Client Hello"
          set iRecordOffset [expr {$iRecordPointer + 43}]
          binary scan [TCP::payload] @${iRecordOffset}c tls_sessidlen
          set iRecordOffset [expr {$iRecordOffset + 1 + $tls_sessidlen}]
          binary scan [TCP::payload] @${iRecordOffset}S tls_ciphlen
          set iRecordOffset [expr {$iRecordOffset + 2 + $tls_ciphlen}]
          binary scan [TCP::payload] @${iRecordOffset}c tls_complen
          set iRecordOffset [expr {$iRecordOffset + 1 + $tls_complen}]
          binary scan [TCP::payload] @${iRecordOffset}S tls_extenlen
          set iRecordOffset [expr {$iRecordOffset + 2}]
          binary scan [TCP::payload] @${iRecordOffset}a* tls_extensions
    
          for { set i 0 } { $i < $tls_extenlen } { incr i 4 } {
           set iExtensionOffset [expr {$i}]
           binary scan $tls_extensions @${iExtensionOffset}SS etype elen
           if { ($etype == "00") } {
            set iScanStart [expr {$iExtensionOffset + 9}]
            set iScanLength [expr {$elen - 5}]
            binary scan $tls_extensions @${iScanStart}A${iScanLength} tls_servername
            if { [regexp \x00 $tls_servername] } {
             log local0. "Winshock detected - NULL character in host name. Server Name: $tls_servername"
             set bKill 1
            } else {
             #log local0. "Server Name found valid: $tls_servername"
            }
            set iExtensionOffset [expr {$iExtensionOffset + $elen}]
           } else {
            #log local0. "Uninteresting extension $etype"
            set iExtensionOffset [expr {$iExtensionOffset + $elen}]
           }
           set i $iExtensionOffset
          }
         } elseif { $tls_xacttype == 22 && $tls_action == 11 } {
          #log local0. "Certificate"
          set iScanStart [expr {$iRecordPointer + 17}]
          set iScanLength [expr {$tls_recordlen - 12}]
          binary scan [TCP::payload] @${iScanStart}A${iScanLength} client_certificate
          if { [regexp {\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01(\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07|\x06\x05\x2b\x81\x04\x00(?:\x22|\x23))} $client_certificate reMatchAll reMatch01] } {
           #log local0. $match01
           switch $reMatch01 {
            "\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07" {
             set sPrimeCurve "P-256"
            }
            "\x06\x05\x2b\x81\x04\x00\x22" {
             set sPrimeCurve "P-384"
            }
            "\x06\x05\x2b\x81\x04\x00\x23" {
             set sPrimeCurve "P-521"
            }
            default {
             #log local0. "Invalid curve"
            }
           }
          }
         } elseif { $tls_xacttype == 22 && $tls_action == 15 } {
          #log local0. "Certificate Verify"
          set iScanStart [expr {$iRecordPointer + 11}]
          set iScanLength [expr {$tls_recordlen - 6}]
          binary scan [TCP::payload] @${iScanStart}A${iScanLength} client_signature
          binary scan $client_signature c cSignatureHeader
          if { $cSignatureHeader == 48 } {
           binary scan $client_signature @3c r_len
           set s_len_offset [expr {$r_len + 5}]
           binary scan $client_signature @${s_len_offset}c s_len
           set iMessageLength $r_len
           if { $iMessageLength < $s_len } {
            set iMessageLength $s_len
           }
          } else {
           #log local0. "Sig header invalid"
          }
         } else {
          #log local0. "Uninteresting TLS action"
         }
    
         # Curve and length found - check Winshock
         if { $sPrimeCurve ne "" && $iMessageLength > 0 } {
          set iMaxLength 0
          switch $sPrimeCurve {
           "P-256" {
            set $iMaxLength 33
           }
           "P-384" {
            set $iMaxLength 49
           }
           "P-521" {
            set $iMaxLength 66
           }
          }
    
          if { $iMessageLength > $iMaxLength } {
           log local0. "Winshock detected - Invalid message length (found: $iMessageLength, max:$iMaxLength)"
           set bKill 1
          }
         }
    
         # Exploit found, close connection
         if { $bKill } {
          TCP::close
          set bNextRecord 0
         } else {
          # Next record
          set iRecordPointer [expr {$iRecordPointer + $tls_recordlen + 5}]
          if { $iRecordPointer == [TCP::payload length]} {
           # End of records => Assume it is the end of the packet.
           #log local0. "End of records"
           set bNextRecord 0
           set iPacketCounter 0
           set iRecordPointer 0
           set sPrimeCurve ""
           set iMessageLength 0
           TCP::release
           TCP::collect
          } else {
           if { $bNextRecord < $MAX_TLS_RECORDS } {
            set bNextRecord [expr {$bNextRecord + 1}]
           } else {
            set bNextRecord 0
            #log local0. "Too many loops over TLS records, exit now"
            TCP::release
            TCP::collect
           }
          }
         }
        } else {
         #log local0. "Record fragmented"
         set bNextRecord 0
         set iPacketCounter [expr {$iPacketCounter + 1}]
         TCP::collect
        }
       }
     } else {
      # Exit here if packet is not TLS handshake
      if { $iPacketCounter == 0 } {
       TCP::release
       TCP::collect
      }
     }
    }

    Create a new iRule and attach it to your virtual server.

  •  

  •  

  •  

  •  

0EM1T000001EpaS.jpg

Comments
Ilya_Chernyakov
Historic F5 Account
Cool article. Not bad for one hand !
paul786walk_283
Nimbostratus
Nimbostratus
nancy44sinha_28
Nimbostratus
Nimbostratus
majlink608_2892
Nimbostratus
Nimbostratus
specialcon113_2
Nimbostratus
Nimbostratus
ocdusstret3_289
Nimbostratus
Nimbostratus
kunal721mane_28
Nimbostratus
Nimbostratus
fairf80_294651
Nimbostratus
Nimbostratus
razah0148_29999
Nimbostratus
Nimbostratus
anask9598_30014
Nimbostratus
Nimbostratus
jose282hamon_30
Nimbostratus
Nimbostratus
audrey45bm_3032
Nimbostratus
Nimbostratus
cindy55marc_303
Nimbostratus
Nimbostratus
Version history
Last update:
‎23-Jun-2022 09:34
Updated by: