Pages

Subscribe:

Story of a PoC - F5 BIG-IP Cookie Information Disclosure

Curiosity is the biggest virtue of a hacker’s mindset. Only because curiosity people like me loose focus of the actual target and run behind the OTHER things. (Anyways, they are more interesting)

Similar thing happened while I was Pen testing some Web servers which were running behind a load balancer. Nessus was showing some vulnerability associated with load balancer through which it was able to figure out the internal IP of the target server. I read about the vulnerability but was not able to manually test it. Now instead of completing the project in given time, I kept going deeper into the finding and had to stay in office up-to 2 AM just to complete the work. I want to share what ever I learnt, hope you find it useful and interesting.

Little Bit of LOAD BALANCING

Load balancing is a technique to distribute workload across number of servers, network links and other hardware resources in order to achieve optimal resource utilization and maximum throughput. It also serves the cause to avoid any overload and service outage.

Server farms achieve high scalability and high availability through server load balancing, a technique that makes the server farm appear to clients as a single server. In general, server load balancing architectures are of two main types:

1. Transport-level load balancing such as the DNS-based approach or TCP/IP-level load balancing which acts independently of the application payload.

2. Application-level load balancing which uses the application payload to make load balancing decisions.

Load balancing can further be classified into two types namely software-based and hardware based load balancers. Hardware based load balancers are used in transport level load balancing as they are faster than software based ones. On the other hands software based load balancers run on standard operating systems and hardware components (PCs).

In this case we will look into a vulnerability associated with an application level load balancer named F5 Big IP. For balancing the load between the servers this load balancer uses a technique called "Load Balancing using Cookie injection". The load balancer checks if the request contains a specific load balancing cookie. If the cookie is not found, a server is selected using a distribution algorithm such as round-robin. A load balancing session cookie is added to the response before the response is sent. When the browser receives the session cookie, the cookie is stored in temporary memory and is not retained after the browser is closed. The browser adds the cookie to all subsequent requests in that session, which are sent to the load balancer. By storing the server slot as cookie value, the load balancer can determine the server that is responsible for this request (in this browser session).

Now to talk about F5 Big IP Load balancer, to maintain the session between the client and allotted server it encodes the internal IP and the port being used for the session, stores it into the cookie and injects that into the client browser.

When scanned, Nessus reports the vulnerability with name "F5 BIG-IP Cookie Information Disclosure" and also gives the Internal IP and port that was used while Nessus ran its script. When I read bout the vulnerability, I was eager to verify it manually. So I connected to the target server and in response I received the cookie from the Big IP load balancer. Cookies contents were something like

Name: BIGipServerpool_reservations_80
Content : 940968458.20480.0000
Host : x.x.x.62
Path : /

When I read it, first thought that came to my mind was Nessus gave away a false positive. But then I observed that Nessus was not only detecting the vulnerability but also was able to find out the Internal IP which it was displaying in the result section.

So, to go into little deeper I thought capturing the traffic at wire level while scanning might help somehow. So I started Wireshark and realized that running scan on an IP and analyzing the capture file for the needed result is like moving a mountain. Only option left for me was to run the .nasl script for this plugin and capture the traffic of it. So finally I meet the requirement to run a nasl script individually. I did searched on Google and found out how to do it on BT.

For this we need to move to the directory where Nessus plugins are located which in case of Linux is

opt/nessus/lib/nessus/plugins/

From here we need to run the particular script which in this case is bigip_cookie.nasl

I used the following command to run the script while being in the above mentioned directory

/opt/nessus/bin/nasl -t x.x.x.62

In result the script only displayed “successful”, nothing else. So I changed my focus to the data captured by wireshark. Through all the streams I was able to see nothing but similar data that I saw in the cookie. No Internal IP, no port and nothing. This was the time when I started getting annoyed, anxious and curious at the same time. (And also when my boss realised that the project will be delayed :P)

So with all my frustration and curiosity I now opened the nasl script in editor and read the script. I observed that the script was trying to initiate a connection with the target and was capturing the cookie recieved in the response. Then the script parsed the cookie to find the string “BIGipServerpool” in order to confirm that cookie belongs to Big IP. From the contents of the cookie it was reading the encoded number format (940968458.20480.0000) which was supposed to be the IP. With some weird mathematics the script was able to decode the number and find out the Internal IP.

I tried several techniques to decode the IP manually. I even tried using code part from the .nasl script but zero was all that I got in return.

Now to understand what that script was doing exactly I read little bit about .nasl scripting. (Vijay Mukhi has written a small but very useful guide to start with nasl scripting). I kept putting a printing statement for every variable the script was using after every calculation. Then after I figured out (It took me nearly 3 hours) that from three partitions of the encoded string only first was containing entire IP and second was showing the encoded port number. For Example

940968458 20480 0000
(Encoded IP) (Port)

It was very relaxing when I saw the output and understood how exactly it all was happening. But all that relaxation vanished when I realized that its nearly five o clock and I will now have to stay in office till midnight or even more to finish the remaining work of mine.

After all of this I realised one more thing that till now I don’t have anything in hand which I can give as PoC of manual testing to the client. Here was when my boss also got actively intrested in this stuff. I explained him what all I have done so far and then he came up with an idea. He just took the code from nasl script which was doing the decoding stuff. Then he made a ruby script to do same stuff. Take the IP and port as input, connect, capture and parse the cookie and decode the IP and port from it. Only difference being that the script was giving output which shows us the Internal IP and the port being used.

I ran that script in konsole and took the screenshot of output and made a PoC of that. That’s it. I am giving below the small script

-----------------------------------------------------------------------------------------------------------------------------
require 'net/http'
require 'net/https'

#~ puts "\n############################################### #\n" 
#~ puts "F5 Big-IP Cookie information Disclosure\n"
#~ puts "################################################\ n\n"
#~ puts "\n"
#~ puts "Usage: bigip_cookie <IP Address> <port>\n"

rrr = ARGV[0]
ppp = ARGV[1]
#~ puts rrr
#~ puts ppp
http = Net::HTTP.new("#{ARGV[0]}", ARGV[1])
http.use_ssl = true
path = '/'
resp, data = http.get(path, nil)
cookie = resp.response['set-cookie']
IP_port = /BIGipServer([^=]+)=([0-9]+)\.([0-9]+)\.[0-9]+/
m = IP_port.match(cookie)
puts m[2]

oct1 = (m[2].to_i & 0x000000ff)

oct2 = (m[2].to_i & 0x0000ffff) >> 8

oct3 = (m[2].to_i & 0x00ffffff) >> 16
oct4 = m[2].to_i >> 24
port = (m[3].to_i & 0x00ff) * 256 + (m[3].to_i >> 8)
puts "Cookie: #{cookie}"
puts "Internal IP is: #{oct1}.#{oct2}.#{oct3}.#{oct4}"
puts "Port is: #{port}"

-----------------------------------------------------------------------------------------------------------------------------

As soon as I got the PoC one more thought caught my mind. As the load balancer depends upon the cookie for maintaining the session, what will happen if we change the value of port in the cookie? Will the load balancer try to connect to the new port that we have given? Is it possible to do an internal port scan on the target IP with this idea? 

As I had to finish the project in given time, I kept this thought aside and finished the project nearly at midnight.

Now to try all those things I will first have to find the Big IP load balancer running in this blue nowhere. Till then this question will keep haunting my mind.