Logjam Mitigation

Problem this snippet solves:

The logjam vulnerabilities described here do not impact ssl traffic offloaded by BIG-IP unless select COMPAT ciphers are enabled by an administrator. However, for ssl traffic that is not offloaded at the BIG-IP, but simply load balanced to back end servers, the clients are at risk for a man-in-the-middle attack if both client and server are vulnerable.

This iRule will check for any Diffie-Hellman EXPORT ciphers (as listed in RFC 2246) being offered by the client and will reject the connection if it finds one.

How to use this snippet:

Apply this iRule (with associated data-group) to any ssl virtual that is NOT offloading ssl but DOES load balance ssl traffic for vulnerable servers. Tested in 11.2.1 and 11.6, but should work in all versions.

OpenSSL command to test:

openssl s_client -connect 192.168.22.102:443 -tls1 -cipher EXPORT

Log output:

May 23 09:26:52 tmm info tmm[7296]: Rule /Common/cipherlist_test <CLIENT_DATA>: TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA matched DH Export Cipher, rejecting

Code :

### DataGroup ###
ltm data-group internal DH_EXPORT_CIPHERLIST {
    records {
        000b {
            data TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
        }
        000e {
            data TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
        }
        0011 {
            data TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
        }
        0014 {
            data TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
        }
        0017 {
            data TLS_DH_anon_EXPORT_WITH_RC4_40_MD5
        }
        0019 {
            data TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA
        }
    }
    type string
}
### iRule ###
when CLIENT_ACCEPTED {
  TCP::collect
}
when CLIENT_DATA {
  if { ! [info exists rlen] } {
    binary scan [TCP::payload] cSS rtype sslver rlen
    #log local0. "SSL Record Type $rtype, Version: $sslver, Record Length: $rlen"
    if { $sslver > 767 } {
      if { $rtype != 22 } {
        #log local0. "Client-Hello expected, rejecting. \
        Src: [IP::client_addr]:[TCP::remote_port] -> \
        Dst: [IP::local_addr]:[TCP::local_port]"
        reject
        return
  }
  #collect the rest of the record if necessary
  if { [TCP::payload length] < $rlen } {
    TCP::collect $rlen
  }
  
  #skip record header and random data
  set field_offset 43
  
  #set the offset
  binary scan [TCP::payload] @${field_offset}c sessid_len
  set field_offset [expr {$field_offset + 1 + $sessid_len}]
  
  #get the cipherlist length
  binary scan [TCP::payload] @${field_offset}S cipherlist_len
  
  #get ciphers, separate into a list of elements
  set field_offset [expr {$field_offset + 2}]
  set cipherlist_len [expr {$cipherlist_len * 2}]
  binary scan [TCP::payload] @${field_offset}H${cipherlist_len} cipherlist
  #log local0. "Cipher list: $cipherlist"
}
for { set x 0 } { $x < $cipherlist_len } { incr x 4 } {
  set cipher [string range $cipherlist $x [expr {$x + 3}]]
  if { [class match $cipher equals DH_EXPORT_CIPHERLIST] } {
    log local0. "[class match -value $cipher equals DH_EXPORT_CIPHERLIST] matched DH Export Cipher, rejecting"
    reject
    return
  } else { #log local0. "$cipher ok, not on DH Export list" }
}

event CLIENT_DATA disable
TCP::release
  }
}

Tested this on version:

11.6
Updated Jun 06, 2023
Version 2.0

Was this article helpful?

No CommentsBe the first to comment