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
|