Forum Discussion

Siva_107534's avatar
Siva_107534
Icon for Nimbostratus rankNimbostratus
Dec 28, 2009

How to encrypt the cookies generated by LTM?

Hi All,

 

How to encrypt the cookie information generated by LTM in the browser, becoz

 

by default cookies in the browser displays the Internal Pool IP of web servers

 

accessed through LTM . This is highly insecure..

 

I understand i can be encrypted thru irule, any one can guide exact iRule to make the browser cookies in the encrypted format

 

Any pls help....

10 Replies

  • Hi Siva,

     

    Have you looked at the following:

     

     

    http://devcentral.f5.com/wiki/default.aspx/iRules/EncryptingCookies.html

     

     

    and

     

     

    http://devcentral.f5.com/wiki/default.aspx/iRules/Cookie_Encryption_across_pools_and_services.html

     

     

     

    Bhattman
  • In 9.4 and higher, you could also use the HTTP profile option for encrypting the cookie:

     

     

    SOL7784: Overview of cookie encryption

     

    https://support.f5.com/kb/en-us/solutions/public/7000/700/sol7784.html

     

     

    Aaron
  • Help. We are using 9.3.1 and got hit on a vulnerability scan for unencrypted cookies. I used the link http://devcentral.f5.com/wiki/defau...okies.html

     

    to create the irules needed for this. Our QA tested and advised us all was well. We attempted to roll out to production and got many failures and had to roll back. I thought it had to do with existing sessions and once the user logged back in he/she would be OK. My own testing showed that the irule would force you back to the login page every time you clicked on a different feature of the application. After logging off and on to the site 3 times, everything appeared to be working. In addition to the irule, we created a custom cookie and named it app_cookie to match the irule.

     

    The error message and irule are shown below. I can turn debugging on if needed but would like some insight please.

     

    Thank you,

     

    Chris

     

     

    Code is here: http://pastebin.com/QwsVjzfs

     

     

    I don't know how to post it here properly.
  • Hi Chris,

     

     

    Can you edit your post and put the iRule between [ code ] [/ code ] tags to preserve the spacing and text between angle brackets?

     

     

    Can you also enable debug (maybe just for your client IP in RULE_INIT) and post the /var/log/ltm entries for a failure?

     

     

    Thanks, Aaron
  • Here is the debug info. As before, I had to log in and out of the app multiple times before all aspects of the webapp responded properly without kicking me back to the login page.

     

     

    Dec 10 12:28:35 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : Response from app contained our cookie: 2493884608.20480.0000

     

    Dec 10 12:28:35 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : Encrypted error cookie to: %a4%b1%22%df%aceqZ%d9Il%a2%a5%03%03%5b%e6%9f%88%13.%c3%e8%b2Ef%d4%dbP%1d%c6G%fc%9a%98%06v%bdc%1b%db%b8%0e%d5%0c%c7%fc%e7

     

    Dec 10 12:28:35 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : Original error cookie value: %a4%b1%22%df%aceqZ%d9Il%a2%a5%03%03%5b%e6%9f%88%13.%c3%e8%b2Ef%d4%dbP%1d%c6G%fc%9a%98%06v%bdc%1b%db%b8%0e%d5%0c%c7%fc%e7

     

    Dec 10 12:28:35 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : $cookie_uri_decoded was set successfully

     

    Dec 10 12:28:35 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : $cookie_decrypted: 2493884608.20480.0000

     

    Dec 10 12:28:35 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : Response from app contained our cookie: 2493884608.20480.0000

     

    Dec 10 12:28:35 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : Encrypted error cookie to: %a4%b1%22%df%aceqZ%d9Il%a2%a5%03%03%5b%e6%9f%88%13.%c3%e8%b2Ef%d4%dbP%1d%c6G%fc%9a%98%06v%bdc%1b%db%b8%0e%d5%0c%c7%fc%e7

     

    Dec 10 12:28:36 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : Original error cookie value: %a4%b1%22%df%aceqZ%d9Il%a2%a5%03%03%5b%e6%9f%88%13.%c3%e8%b2Ef%d4%dbP%1d%c6G%fc%9a%98%06v%bdc%1b%db%b8%0e%d5%0c%c7%fc%e7

     

    Dec 10 12:28:36 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : $cookie_uri_decoded was set successfully

     

    Dec 10 12:28:36 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : $cookie_decrypted: 2493884608.20480.0000

     

    Dec 10 12:28:37 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : Original error cookie value: %a4%b1%22%df%aceqZ%d9Il%a2%a5%03%03%5b%e6%9f%88%13.%c3%e8%b2Ef%d4%dbP%1d%c6G%fc%9a%98%06v%bdc%1b%db%b8%0e%d5%0c%c7%fc%e7

     

    Dec 10 12:28:37 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : $cookie_uri_decoded was set successfully

     

    Dec 10 12:28:37 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : $cookie_decrypted: 2493884608.20480.0000

     

    Dec 10 12:28:37 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : Original error cookie value: %a4%b1%22%df%aceqZ%d9Il%a2%a5%03%03%5b%e6%9f%88%13.%c3%e8%b2Ef%d4%dbP%1d%c6G%fc%9a%98%06v%bdc%1b%db%b8%0e%d5%0c%c7%fc%e7

     

    Dec 10 12:28:37 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : $cookie_uri_decoded was set successfully

     

    Dec 10 12:28:37 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : $cookie_decrypted: 2493884608.20480.0000

     

    Dec 10 12:28:37 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : Response from app contained our cookie: 2493884608.20480.0000

     

    Dec 10 12:28:37 tmm tmm[1096]: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt : Encrypted error cookie to: %a4%b1%22%df%aceqZ%d9Il%a2%a5%03%03%5b%e6%9f%88%13.%c3%e8%b2Ef%d4%dbP%1d%c6G%fc%9a%98%06v%bdc%1b%db%b8%0e%d5%0c%c7%fc%e7

     

  • That's a cool site. Here's the iRule code:

     

     

    
    TCL error: Rule Enterprise_F5_Fix_with_E35-THD_cookie_encrypt HTTP_REQUEST - cant read cookie: no such variable while executing HTTP::cookie value $cookie 
    
    
    
    when CLIENT_ACCEPTED {
        Define an AES encryption key. A 128 bit (or larger) key is recommended. 
        You can use a key generator, or create your own using only HEX characters.
       set aes_key "63544a5e7178677b45366b4140"
    
        Name of the cookie to encrypt/decrypt
       set cookie "app_cookie"
    
        Log debug messages to /var/log/ltm?  1=yes, 0=no.
       set cookie_encryption_debug 0
    }
    when HTTP_REQUEST {
        If the error cookie exists with any value, for any requested object, try to decrypt it
       if {[string length [HTTP::cookie value $cookie]]}{
    
          if {$cookie_encryption_debug}{log local0. \
             "Original error cookie value: [HTTP::cookie value $cookie]"}
    
           URI decode the value (catching any errors that occur when trying to 
           decode the cookie value and save the output to cookie_uri_decoded)
          if {not ([catch {URI::decode [HTTP::cookie value $cookie]} cookie_uri_decoded])}{
    
              Log that the cookie was URI decoded
             if {$cookie_encryption_debug}{log local0. "\$cookie_uri_decoded was set successfully"}
    
              Decrypt the value
             if {not ([catch {AES::decrypt $aes_key $cookie_uri_decoded} cookie_decrypted])}{
    
                 Log the decrypted cookie value
                if {$cookie_encryption_debug}{log local0. "\$cookie_decrypted: $cookie_decrypted"}
             } else {
    
                 URI decoded value couldn't be decrypted.
             }
          } else {
              Cookie value couldn't be URI decoded
          }
       } else {
           Cookie wasn't present in the request
       }
    if {[HTTP::uri] ends_with ".asmx?WSDL"}{
    set rewrite 1
    if { [HTTP::version] eq "1.1" } {
    HTTP::version "1.0"
    }
    } else {
    set rewrite 0
    }
    switch [getfield [string tolower [HTTP::uri]] "/" 2] {
             appe21test {pool test.app_EE_20 }
                      appe21 { pool www.company.com_e20 }
                      appe30 { pool www.company.com_e30 }
                      appe30test { pool www.company.com_e30test }                
                      se08q4 { pool www.company.com_08q4 }  
                      
                  }
    }
    when HTTP_RESPONSE {
        Check if response contains an error cookie with a value
       if {[string length [HTTP::cookie value $cookie]] > 0}{
    
           Log the original error cookie value from the app
          if {$cookie_encryption_debug}{log local0. \
             "Response from app contained our cookie: [HTTP::cookie value $cookie]"}
    
           Encrypt the cookie value so the client can't change the value
          HTTP::cookie value $cookie [URI::encode [AES::encrypt $aes_key [HTTP::cookie value $cookie]]]
    
           Log the encoded and encrypted error cookie value
          if {$cookie_encryption_debug}{log local0. \
            "Encrypted error cookie to: [URI::encode [AES::encrypt $aes_key [HTTP::cookie value $cookie]]]"}
       }
    if {$rewrite == 1}{
     collect payload for URI replacement
    if {[HTTP::header exists Content-Length]}{
    set clength [HTTP::header Content-Length]
    } else {
    set clength 4294967295
    }
    if { !($clength == 0) } {
    HTTP::collect $clength
    }
    }
    }
    when HTTP_RESPONSE_DATA {
    set payload [HTTP::payload]
    regsub -all {(
     
      
     Aaron
  • So the encryption/decryption looks to be working in your logs. Did you get the runtime TCL error "cant read cookie: no such variable while executing HTTP::cookie value $cookie" on every request which wasn't persisted correctly? Or did that just occur when you first added the iRule?

     

     

    If the encryption is working, but you're still seeing persistence failures (client request going to a server which doesn't have a session for the client), I'd guess it's due to multiple clients making requests over the same TCP connection. This can happen when users connect to the same site through a proxy. You can fix this issue by adding a OneConnect profile to the virtual server. If you're using SNAT you can use a source mask of 0.0.0.0 on the OneConnect profile. If you're not using SNAT, create a custom OneConnect profile with a source mask of 255.255.255.255. You can check this page for details on OneConnect:

     

     

    http://devcentral.f5.com/wiki/default.aspx/AdvDesignConfig/oneconnect.html

     

     

    Aaron
  • A couple of other points I forgot:

     

     

    If you use HTTP::collect you should limit the collection to the first 1Mb of payload, else you risk triggering a TMM core. See SOL6578 for details:

     

     

    SOL6578: TMM will crash if an iRule collects more than 4MB of data

     

    http://support.f5.com/kb/en-us/solutions/public/6000/500/sol6578.html

     

     

    And you could probably break out the payload rewriting functionality to a separate iRule as it wouldn't conflict with the cookie encryption.

     

     

    Lastly, you could replace the payload collection with a stream profile and STREAM::expression iRule. The stream option should be more efficient than the payload collection. For examples of the stream option, you can check the STREAM::expression wiki page:

     

     

    http://devcentral.f5.com/wiki/default.aspx/iRules/stream__expression

     

     

    Aaron
  • Aaron,

     

    Thank you very much for your help and suggestions. I will take back to my dev group and do some testing.

     

    Chris