26 February, 2013

Decoding F5 Cookie

Decoding F5 Cookie
Secure Ideas
Author: Secure Ideas
Share:

As a Penetration Tester, there are many different things you come across while performing a test.   The one in which I will discuss in this post is the cookies returned by the F5 BigIp Server.  These cookies are purposed for load balancing and if not properly protected, will reveal IP addresses and ports of internal servers.  From a security mindset, it is far from ideal to be handing out internal network information like this. 

The first step in decoding an F5 cookie is to identify it.  The following response header is an example of an F5 cookie being set:

Set-Cookie: BIGipServerApp_Pool_SSL=839518730.47873.0000; path=/

The name of the cookie will probably be slightly different, but is should be similar and the value will be 3 values separated by periods. The next step is to decode the cookie to identify the internal IP address and Port.
The above cookie translates to:
IP Address: 10.10.10.50 Port: 443
The following method was used to decode the IP Address (this information is available from F5’s website http://support.f5.com/kb/en-us/solutions/public/6000/900/sol6917.html):

  1. Take the first segment of the cookie value (839518730) and convert it to its 4-byte hexadecimal equivalent (320A0A0A)
  2. Reverse the byte order (0A0A0A32)
  3. Convert each byte back to its decimal value
  4. 0A = 10, 0A = 10, 0A = 10, 32 = 50
  5. The resulting address is 10.10.10.50

The following method was used to decode the port number:

  1. Take the second segment of the cookie value (47873) and convert it to the equivalent 2-byte hexadecimal value (BB01)
  2. Reverse the byte order (01BB)
  3. Convert the value back to its decimal value (443)

Although this manual method works, it is rather tedious. I found a reference to a python script that will decode the IP address for you. It can be found here: http://penturalabs.wordpress.com/2011/03/29/how-to-decode-big-ip-f5-persistence-cookie-values/

This code didn’t decode the port so I have extended the python script to add some additional functionality (the script is included at the end of this post).  The first piece of functionality I added was to decode the port.  Then after thinking about it, I decided to add the ability to pass in multiple cookie values from a text file and have them decoded in bulk.

The following image shows the script being executed using just a single cookie value:

bash

The following image shows the script being executed using an input file containing multiple cookie values (it just so happens the vales are all the same):

bash 2

If you do not want to reveal these internal IP addresses, F5 does provide instructions on how to encrypt the cookie value.  This information can be found on the F5 support site here: http://support.f5.com/kb/en-us/solutions/public/7000/700/sol7784.html?sr=14607726.

The following is the modified script:

#!/usr/bin/env python

# This script decodes the IP and Port of an F5 cookie.
# example string: 839518730.47873.0000
# This script is extended off of the concept from http://penturalabs.wordpress.com/2011/03/29/how-to-decode-big-ip-f5-persistence-cookie-values/ where I have added in the ability to decode the Port in addition to supporting input files containing multiple cookie values.

import struct
import sys

def decode(cookie_value):

     (host, port, end) = cookie_value.split(‘.’)

     (a, b, c, d) = [ord(i) for i in struct.pack(“<I”, int(host))]

     p = [ord(i) for i in struct.pack(“<I”, int(port))]
     portOut = p[0]*256 + p[1]

     print “%s.%s.%s.%s:%s” % (a,b,c,d,portOut)

if len(sys.argv) != 3:
        print “Usage: %s input_type encoded_string” % sys.argv[0]
     print “-c Individual cookie value”
     print “-f File Name containing cookie values on each linen”
     print “ex. %s -c 839518730.47873.0000” % sys.argv[0]
     print “ex. %s -f inputfile.txt” % sys.argv[0]
        exit(1)

if sys.argv[1] == “-c”:
     cookie_text = sys.argv[2]
     decode(cookie_text)
if sys.argv[1] == “-f”:
     file_name = sys.argv[2]
     with open(file_name,’r’) as f:
          for x in f:
               x = x.rstrip()
               if not x: continue
               decode(x)

If you are performing a test and come across this value, don’t overlook it.  It may contain some internal IP addresses that can be useful to an attacker.  This should be brought to the attention of the client to determine the risk level of the information being revealed.

James Jardine is a Principal Security Consultant with Secure Ideas.  If you are in need of a penetration test or other security consulting services you can contact him at james@secureideas.com or visit the Secure Ideas – Professionally Evil site for services provided.

Join the professionally evil newsletter

Related Resources