For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Forum Discussion

Amit_Grover_171's avatar
Amit_Grover_171
Icon for Nimbostratus rankNimbostratus
Oct 12, 2015

Need to write Irule to decode auth string to Base64 and fetch domain name from it and compare that domain name with certificate to deny/permit traffic

Hi,

 

Need to write Irule to decode auth string to Base64 and fetch domain name from it and compare that domain name with certificate to deny/permit traffic.

 

Please help ASAP.

 

/Regards Amit Grover

 

9 Replies

  • Try this:

    when HTTP_REQUEST {
        if { [HTTP::header exists Authorization] } {
            catch { 
                set creds [b64decode [findstr [HTTP::header Authorization] "Basic " 6]]
    
                 credentials will ether be in domain\user:password or user@domain:password format
                if { $creds contains "\\" } {
                    set domain [findstr $creds "" 0 "\\"]
                } elseif { $creds contains "@" } {
                    set domain [findstr $creds "@" 1 ":"]
                }
    
                log local0. $domain
            }
        }
    }
    

    Once you have the domain value you can simply apply logic to compare it to the certificate:

    if { $domain ne "" } {
        if { $domain eq $cert_valu } {
             ...do something
        }
    }
    
  • you can use [HTTP::username] variable to get username part of Basic authentication instead of Base64.

     

  • Right, so minor modification required:

    when HTTP_REQUEST {
        if { [HTTP::header exists Authorization] } {
            set creds [HTTP::username]
    
            if { $creds ne "" } {
             credentials will ether be in domain\user:password or user@domain:password format
                if { $creds contains "\\" } {
                    set domain [findstr $creds "" 0 "\\"]
                } elseif { $creds contains "@" } {
                    set domain [findstr $creds "@" 1]
                }
    
                log local0. $domain
            }
        }
    }
    
  • Hi,

    Its not a HTTP request instead its a auth string in XMPP like :-

    "Y3NqYWJiZXIuY29t"

    Wherein "Y3NqYWJiZXIuY29t" is domain name.

    Another catch is we have multi SAN certificate so I want to compare this domain name with SAN's and then only permit traffic.

    Please assist further.

    /Regards Amit Grover

  • Something like this to get the domain value. I need to assume for the following code that the request that's sending this payload data is a POST:

     

    when HTTP_REQUEST {
        if { [HTTP::method] eq "POST" } {
             buffer the HTTP payload and trigger the HTTP_REQUEST_DATA event
            HTTP::collect [HTTP::header Content-Length]
        }
    }
    when HTTP_REQUEST_DATA {
         HTTP payload data is available here
        if { [HTTP::payload] contains "" 21 "<"]
            catch { set domain [b64decode $domain] } 
    
            log local0. "domain = $domain"
        }
    }

    Another catch is we have multi SAN certificate so I want to compare this domain name with SAN's and then only permit traffic.

     

    So do you mean you're applying this iRule to multiple HTTPS VIPs that have separate SAN certs, and you need to check the domain against each of the SAN names? Would it not be the same as the HTTP::host value?

     

  • Hi Kevin,

     

    Thanks again for prompt response but. This is not http/https request we have XMPP stream in which we got auth string as described above. XMPP use SASL to authenticate but in our scenario we have to use Irule to authenticate it and certificate against which it will be authenticate is a Multi-SAN certificate.

     

    Yes true we have multiple XMPP VIPS in which multisan certs are being used and I need to compare domain with those SAN's and permit it.

     

    /Regards Amit Grover

     

  • Hi Amit,

    did you try to replace HTTP event and commands from Kevin irule by TCP one.

    You can also get the requested TLS server name instead of cert used.

    when CLIENT_ACCEPTED {
        TCP::collect
    }
    when CLIENTSSL_CLIENTHELLO {
    
        if { [SSL::extensions exists -type 0] } {
             if the servername exists - store it in tls_servername variable
            set tls_servername [string range [SSL::extensions -type 0] 9 [string length [SSL::extensions -type 0]]]
        }
    }
    when CLIENT_DATA {
         HTTP payload data is available here
        set authStr [findstr [TCP::payload] ""]
        if { $authStr ne "" } {
            set domain [findstr $authStr "mechanism='EXTERNAL'>" 21 end]
            catch { set domain [b64decode $domain] } 
            log local0. "domain = $domain"
        }
        TCP::release
    }
    
  • Hi Stanisals,

     

    Thanks for response below is the situation.

     

    TLS negotiation has been successful between F5 acting as server and any UC system acting as client. Stream initiated from UC system. During TLS negotiation, first F5 sent/shared the “server hello” and “server certificate” on response to “client hello” from UC System and also requested for “client certificate” now Client will share its own certificate and server will authorize it via Client cert Root, now this client certificate( negotiated during TLS) will be used by F5 to Send the SUCCESS or FAILURE ( after comparing the Client domain name from the client certificate)

     

    As when Server will send the SUCCESS on the response of AUTH from client, Server will check the encoded Client Domain Name received in the AUTH with the clients certificates shared at time of TLS negotiation. PFB link. http://xmpp.org/extensions/xep-0178.html So the client domain name ( decoded one that received in AUTH), will be checked in the certificates shared by client while doing TLS negotiation for the session only.

     

    Please share is it possible to compare domain from certificate with Auth stream.

     

    /Regards Amit Grover