mirror of
https://github.com/nmap/nmap.git
synced 2025-12-12 02:39:03 +00:00
o [NSE] Added the Internet Storage Name Service (iSNS) library and the
isns-info script that lists information about portals and iSCSI devices. [Patrik Karlsson]
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
# Nmap Changelog ($Id$); -*-text-*-
|
# Nmap Changelog ($Id$); -*-text-*-
|
||||||
|
|
||||||
|
o [NSE] Added the Internet Storage Name Service (iSNS) library and the
|
||||||
|
isns-info script that lists information about portals and iSCSI devices.
|
||||||
|
[Patrik Karlsson]
|
||||||
|
|
||||||
o [NSE] Added rmi-vuln-classloader which scans for machines vulnerable to
|
o [NSE] Added rmi-vuln-classloader which scans for machines vulnerable to
|
||||||
remote class loading. [Aleksandar Nikolic]
|
remote class loading. [Aleksandar Nikolic]
|
||||||
|
|
||||||
|
|||||||
563
nselib/isns.lua
Normal file
563
nselib/isns.lua
Normal file
@@ -0,0 +1,563 @@
|
|||||||
|
---
|
||||||
|
-- A minimal Internet Storage Name Service (iSNS) implementation
|
||||||
|
--
|
||||||
|
-- @author "Patrik Karlsson <patrik@cqure.net>"
|
||||||
|
--
|
||||||
|
|
||||||
|
local bin = require('bin')
|
||||||
|
local bit = require('bit')
|
||||||
|
local ipops = require('ipOps')
|
||||||
|
local match = require('match')
|
||||||
|
local stdnse = require('stdnse')
|
||||||
|
local tab = require('tab')
|
||||||
|
_ENV = stdnse.module("isns", stdnse.seeall);
|
||||||
|
|
||||||
|
iSCSI = {
|
||||||
|
|
||||||
|
NodeType = {
|
||||||
|
TARGET = 1,
|
||||||
|
INITIATOR = 2,
|
||||||
|
CONTROL = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Header = {
|
||||||
|
|
||||||
|
VERSION = 1,
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Creates a header instance
|
||||||
|
--
|
||||||
|
-- @param func_id number containing the function ID of the message
|
||||||
|
-- @param pdu_len number containing the length of the PDU
|
||||||
|
-- @param flags number containing the message flags
|
||||||
|
-- @param trans_id number containing the transaction id
|
||||||
|
-- @param seq_id number containing the sequence id
|
||||||
|
-- @return o new class instance
|
||||||
|
new = function(self, func_id, pdu_len, flags, trans_id, seq_id)
|
||||||
|
local o = {
|
||||||
|
ver = Header.VERSION,
|
||||||
|
func_id = func_id,
|
||||||
|
flags = flags,
|
||||||
|
trans_id = trans_id,
|
||||||
|
seq_id = seq_id,
|
||||||
|
pdu_len = pdu_len,
|
||||||
|
}
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Parses a opaque string and creates a new Header instance
|
||||||
|
--
|
||||||
|
-- @param data opaques string containing the raw data
|
||||||
|
-- @return hdr new instance of Header
|
||||||
|
parse = function(data)
|
||||||
|
local hdr = Header:new()
|
||||||
|
local pos
|
||||||
|
|
||||||
|
pos, hdr.ver, hdr.func_id, hdr.pdu_len, hdr.flags, hdr.trans_id,
|
||||||
|
hdr.seq_id = bin.unpack(">SSSSSS", data)
|
||||||
|
|
||||||
|
return hdr
|
||||||
|
end,
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Converts the instance to an opaque string
|
||||||
|
-- @return str containing an opaque string
|
||||||
|
__tostring = function(self)
|
||||||
|
return bin.pack(">SSSSSS", self.ver, self.func_id,
|
||||||
|
self.pdu_len, self.flags, self.trans_id, self.seq_id )
|
||||||
|
end
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Attribute = {
|
||||||
|
|
||||||
|
Tag = {
|
||||||
|
ISNS_TAG_DELIMITER = 0,
|
||||||
|
ISNS_TAG_ENTITY_IDENTIFIER = 1,
|
||||||
|
ISNS_TAG_ENTITY_PROTOCOL = 2,
|
||||||
|
ISNS_TAG_MGMT_IP_ADDRESS = 3,
|
||||||
|
ISNS_TAG_TIMESTAMP = 4,
|
||||||
|
ISNS_TAG_PROTOCOL_VERSION_RANGE = 5,
|
||||||
|
ISNS_TAG_REGISTRATION_PERIOD = 6,
|
||||||
|
ISNS_TAG_ENTITY_INDEX = 7,
|
||||||
|
ISNS_TAG_ENTITY_NEXT_INDEX = 8,
|
||||||
|
ISNS_TAG_ENTITY_ISAKMP_PHASE_1 = 11,
|
||||||
|
ISNS_TAG_ENTITY_CERTIFICATE = 12,
|
||||||
|
ISNS_TAG_PORTAL_IP_ADDRESS = 16,
|
||||||
|
ISNS_TAG_PORTAL_TCP_UDP_PORT = 17,
|
||||||
|
ISNS_TAG_PORTAL_SYMBOLIC_NAME = 18,
|
||||||
|
ISNS_TAG_ESI_INTERVAL = 19,
|
||||||
|
ISNS_TAG_ESI_PORT = 20,
|
||||||
|
ISNS_TAG_PORTAL_INDEX = 22,
|
||||||
|
ISNS_TAG_SCN_PORT = 23,
|
||||||
|
ISNS_TAG_PORTAL_NEXT_INDEX = 24,
|
||||||
|
ISNS_TAG_PORTAL_SECURITY_BITMAP = 27,
|
||||||
|
ISNS_TAG_PORTAL_ISAKMP_PHASE_1 = 28,
|
||||||
|
ISNS_TAG_PORTAL_ISAKMP_PHASE_2 = 29,
|
||||||
|
ISNS_TAG_PORTAL_CERTIFICATE = 31,
|
||||||
|
ISNS_TAG_ISCSI_NAME = 32,
|
||||||
|
ISNS_TAG_ISCSI_NODE_TYPE = 33,
|
||||||
|
ISNS_TAG_ISCSI_ALIAS = 34,
|
||||||
|
ISNS_TAG_ISCSI_SCN_BITMAP = 35,
|
||||||
|
ISNS_TAG_ISCSI_NODE_INDEX = 36,
|
||||||
|
ISNS_TAG_WWNN_TOKEN = 37,
|
||||||
|
ISNS_TAG_ISCSI_NODE_NEXT_INDEX = 38,
|
||||||
|
ISNS_TAG_ISCSI_AUTHMETHOD = 42,
|
||||||
|
ISNS_TAG_PG_ISCSI_NAME = 48,
|
||||||
|
ISNS_TAG_PG_PORTAL_IP_ADDR = 49,
|
||||||
|
ISNS_TAG_PG_PORTAL_TCP_UDP_PORT = 50,
|
||||||
|
ISNS_TAG_PG_TAG = 51,
|
||||||
|
ISNS_TAG_PG_INDEX = 52,
|
||||||
|
ISNS_TAG_PG_NEXT_INDEX = 53,
|
||||||
|
ISNS_TAG_FC_PORT_NAME_WWPN = 64,
|
||||||
|
ISNS_TAG_PORT_ID = 65,
|
||||||
|
ISNS_TAG_FC_PORT_TYPE = 66,
|
||||||
|
ISNS_TAG_SYMBOLIC_PORT_NAME = 67,
|
||||||
|
ISNS_TAG_FABRIC_PORT_NAME = 68,
|
||||||
|
ISNS_TAG_HARD_ADDRESS = 69,
|
||||||
|
ISNS_TAG_PORT_IP_ADDRESS = 70,
|
||||||
|
ISNS_TAG_CLASS_OF_SERVICE = 71,
|
||||||
|
ISNS_TAG_FC4_TYPES = 72,
|
||||||
|
ISNS_TAG_FC4_DESCRIPTOR = 73,
|
||||||
|
ISNS_TAG_FC4_FEATURES = 74,
|
||||||
|
ISNS_TAG_IFCP_SCN_BITMAP = 75,
|
||||||
|
ISNS_TAG_PORT_ROLE = 76,
|
||||||
|
ISNS_TAG_PERMANENT_PORT_NAME = 77,
|
||||||
|
ISNS_TAG_FC4_TYPE_CODE = 95,
|
||||||
|
ISNS_TAG_FC_NODE_NAME_WWNN = 96,
|
||||||
|
ISNS_TAG_SYMBOLIC_NODE_NAME = 97,
|
||||||
|
ISNS_TAG_NODE_IP_ADDRESS = 98,
|
||||||
|
ISNS_TAG_NODE_IPA = 99,
|
||||||
|
ISNS_TAG_PROXY_ISCSI_NAME = 101,
|
||||||
|
ISNS_TAG_SWITCH_NAME = 128,
|
||||||
|
ISNS_TAG_PREFERRED_ID = 129,
|
||||||
|
ISNS_TAG_ASSIGNED_ID = 130,
|
||||||
|
ISNS_TAG_VIRTUAL_FABRIC_ID = 131,
|
||||||
|
ISNS_TAG_SERVER_VENDOR_OUI = 256,
|
||||||
|
ISNS_TAG_DD_SET_ID = 2049,
|
||||||
|
ISNS_TAG_DD_SET_SYMBOLIC_NAME = 2050,
|
||||||
|
ISNS_TAG_DD_SET_STATUS = 2051,
|
||||||
|
ISNS_TAG_DD_SET_NEXT_ID = 2052,
|
||||||
|
ISNS_TAG_DD_ID = 2065,
|
||||||
|
ISNS_TAG_DD_SYMBOLIC_NAME = 2066,
|
||||||
|
ISNS_TAG_DD_MEMBER_ISCSI_INDEX = 2067,
|
||||||
|
ISNS_TAG_DD_MEMBER_ISCSI_NAME = 2068,
|
||||||
|
ISNS_TAG_DD_MEMBER_FC_PORT_NAME = 2069,
|
||||||
|
ISNS_TAG_DD_MEMBER_PORTAL_INDEX = 2070,
|
||||||
|
ISNS_TAG_DD_MEMBER_PORTAL_IP_ADDR = 2071,
|
||||||
|
ISNS_TAG_DD_MEMBER_PORTAL_TCP_UDP_PORT = 2072,
|
||||||
|
ISNS_TAG_DD_FEATURES = 2078,
|
||||||
|
ISNS_TAG_DD_NEXT_ID = 2079,
|
||||||
|
ISNS_VENDOR_SPECIFIC_SERVER_BASE = 257,
|
||||||
|
ISNS_VENDOR_SPECIFIC_ENTITY_BASE = 385,
|
||||||
|
ISNS_VENDOR_SPECIFIC_PORTAL_BASE = 513,
|
||||||
|
ISNS_VENDOR_SPECIFIC_NODE_BASE = 641,
|
||||||
|
ISNS_VENDOR_SPECIFIC_DD_BASE = 1024,
|
||||||
|
ISNS_VENDOR_SPECIFIC_DDSET_BASE = 1281,
|
||||||
|
ISNS_VENDOR_SPECIFIC_OTHER_BASE = 1537,
|
||||||
|
},
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Creates a new Attribute instance
|
||||||
|
--
|
||||||
|
-- @param tag number containing the tag number
|
||||||
|
-- @param val string containing the tag value
|
||||||
|
-- @param len number containing the tag length
|
||||||
|
-- @return o new Attribute instance
|
||||||
|
new = function(self, tag, val, len)
|
||||||
|
local o = { tag = tag, len = ( len or (val and #val or 0) ), val = val or "" }
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Creates a new Attribute instance
|
||||||
|
--
|
||||||
|
-- @param data string containing an opaque string of raw data
|
||||||
|
-- @return attr new instance of Attribute
|
||||||
|
parse = function(data)
|
||||||
|
local attr = Attribute:new()
|
||||||
|
local pos
|
||||||
|
|
||||||
|
pos, attr.tag, attr.len = bin.unpack(">II", data)
|
||||||
|
pos, attr.val = bin.unpack(">A" .. attr.len, pos)
|
||||||
|
|
||||||
|
return attr
|
||||||
|
end,
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Converts the instance to an opaque string
|
||||||
|
-- @return str containing an opaque string
|
||||||
|
__tostring = function(self)
|
||||||
|
return bin.pack(">IIA", self.tag, self.len, self.val)
|
||||||
|
end,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Attributes = {
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Creates a new Attributes table
|
||||||
|
-- @return o new instance of Attributes
|
||||||
|
new = function(self)
|
||||||
|
local o = { attribs = {} }
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Adds a new Attribute to the table
|
||||||
|
-- @param tag number containing the tag number
|
||||||
|
-- @param val string containing the tag value
|
||||||
|
-- @param len number containing the tag length
|
||||||
|
add = function(self, tag, val, len)
|
||||||
|
table.insert(self, Attribute:new(tag, val, len))
|
||||||
|
end,
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Converts the instance to an opaque string
|
||||||
|
-- @return str containing an opaque string
|
||||||
|
__tostring = function(self)
|
||||||
|
local str = ""
|
||||||
|
for _, attr in ipairs(self) do
|
||||||
|
str = str .. tostring(attr)
|
||||||
|
end
|
||||||
|
return str
|
||||||
|
end,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Request = {
|
||||||
|
|
||||||
|
FuncId = {
|
||||||
|
DevAttrReg = 0x0001,
|
||||||
|
DevAttrQry = 0x0002,
|
||||||
|
DevGetNext = 0x0003,
|
||||||
|
DevDereg = 0x0004,
|
||||||
|
SCNReg = 0x0005,
|
||||||
|
SCNDereg = 0x0006,
|
||||||
|
SCNEvent = 0x0007,
|
||||||
|
SCN = 0x0008,
|
||||||
|
DDReg = 0x0009,
|
||||||
|
DDDereg = 0x000A,
|
||||||
|
DDSReg = 0x000B,
|
||||||
|
DDSDereg = 0x000C,
|
||||||
|
ESI = 0x000D,
|
||||||
|
Heartbeat = 0x000E,
|
||||||
|
},
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Creates a new Request message
|
||||||
|
-- @param func_id number containing the function ID of the message
|
||||||
|
-- @param flags number containing the message flags
|
||||||
|
-- @param data string containing the opaque raw data
|
||||||
|
-- @param auth string containing the opaqur raw auth data
|
||||||
|
-- @param trans_id number containing the transaction id
|
||||||
|
-- @param seq_id number containing the sequence id
|
||||||
|
-- @return o new instance of Request
|
||||||
|
new = function(self, func_id, flags, data, auth, trans_id, seq_id)
|
||||||
|
local o = {
|
||||||
|
header = Header:new(func_id, ( data and #data ) or 0, flags, ( trans_id or -1 ), ( seq_id or -1 )),
|
||||||
|
data = data or ""
|
||||||
|
}
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Converts the instance to an opaque string
|
||||||
|
-- @return str containing an opaque string
|
||||||
|
__tostring = function(self)
|
||||||
|
return tostring(self.header) .. tostring(self.data) ..
|
||||||
|
( self.auth and self.auth or "" )
|
||||||
|
end,
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Response = {
|
||||||
|
|
||||||
|
Error = {
|
||||||
|
[0] = "Successful",
|
||||||
|
[1] = "Unknown Error",
|
||||||
|
[2] = "Message Format Error",
|
||||||
|
[3] = "Invalid Registration",
|
||||||
|
[4] = "RESERVED",
|
||||||
|
[5] = "Invalid Query",
|
||||||
|
[6] = "Source Unknown",
|
||||||
|
[7] = "Source Absent",
|
||||||
|
[8] = "Source Unauthorized",
|
||||||
|
[9] = "No Such Entry",
|
||||||
|
[10] = "Version Not Supported",
|
||||||
|
[11] = "Internal Error",
|
||||||
|
[12] = "Busy",
|
||||||
|
[13] = "Option Not Understood",
|
||||||
|
[14] = "Invalid Update",
|
||||||
|
[15] = "Message (FUNCTION_ID) Not Supported",
|
||||||
|
[16] = "SCN Event Rejected",
|
||||||
|
[17] = "SCN Registration Rejected",
|
||||||
|
[18] = "Attribute Not Implemented",
|
||||||
|
[19] = "FC_DOMAIN_ID Not Available",
|
||||||
|
[20] = "FC_DOMAIN_ID Not Allocated",
|
||||||
|
[21] = "ESI Not Available",
|
||||||
|
[22] = "Invalid Deregistration",
|
||||||
|
[23] = "Registration Feature Not Supported",
|
||||||
|
},
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Creates a new Response instance
|
||||||
|
-- @return o new instance of Response
|
||||||
|
new = function(self)
|
||||||
|
local o = { attrs = Attributes:new() }
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Creates a new Response instance
|
||||||
|
--
|
||||||
|
-- @param data string containing an opaque string of raw data
|
||||||
|
-- @return attr new instance of Response
|
||||||
|
parse = function(data)
|
||||||
|
local hdr = Header.parse(data)
|
||||||
|
local pos = #(tostring(hdr)) + 1
|
||||||
|
local resp = Response:new()
|
||||||
|
|
||||||
|
pos, resp.error = bin.unpack(">I", data, pos)
|
||||||
|
if ( resp.error ~= 0 ) then
|
||||||
|
return resp
|
||||||
|
end
|
||||||
|
|
||||||
|
while( pos < #data ) do
|
||||||
|
local tag, len, val
|
||||||
|
pos, tag, len = bin.unpack(">II", data, pos)
|
||||||
|
pos, val = bin.unpack("A" .. len, data, pos)
|
||||||
|
resp.attrs:add( tag, val, len )
|
||||||
|
end
|
||||||
|
return resp
|
||||||
|
end,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Session = {
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Creates a new Session instance
|
||||||
|
-- @param host table
|
||||||
|
-- @param port table
|
||||||
|
-- @return o instance of Session
|
||||||
|
new = function(self, host, port)
|
||||||
|
local o = {
|
||||||
|
host = host,
|
||||||
|
port = port,
|
||||||
|
seq_id = 0,
|
||||||
|
trans_id = 0,
|
||||||
|
}
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Connects to the server
|
||||||
|
-- @return status true on success, false on failure
|
||||||
|
connect = function(self)
|
||||||
|
self.socket = nmap.new_socket()
|
||||||
|
self.socket:set_timeout(5000)
|
||||||
|
return self.socket:connect(self.host, self.port)
|
||||||
|
end,
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Sends data to the server
|
||||||
|
-- @return status true on success, false on failure
|
||||||
|
-- @return err string containing the error message on failure
|
||||||
|
send = function(self, req)
|
||||||
|
if ( not(req.header) or not(req.header.seq_id) or not(req.header.trans_id) ) then
|
||||||
|
return false, "Failed to send invalid request"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- update the sequence and transaction ID's
|
||||||
|
req.header.seq_id = self.seq_id
|
||||||
|
req.header.trans_id = self.trans_id
|
||||||
|
|
||||||
|
local status, err = self.socket:send(tostring(req))
|
||||||
|
self.trans_id = self.trans_id + 1
|
||||||
|
|
||||||
|
return status, err
|
||||||
|
end,
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Receives data from the server
|
||||||
|
-- @return status true on success, false on failure
|
||||||
|
-- @return response instance of response
|
||||||
|
receive = function(self)
|
||||||
|
-- receive the 24 byte header
|
||||||
|
local status, buf_hdr = self.socket:receive_buf(match.numbytes(12), true)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return status, buf_hdr
|
||||||
|
end
|
||||||
|
|
||||||
|
local hdr = Header.parse(buf_hdr)
|
||||||
|
|
||||||
|
-- receive the data
|
||||||
|
status, buf_data = self.socket:receive_buf(match.numbytes(hdr.pdu_len), true)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return status, buf_data
|
||||||
|
end
|
||||||
|
|
||||||
|
return true, Response.parse(buf_hdr .. buf_data)
|
||||||
|
end,
|
||||||
|
|
||||||
|
close = function(self)
|
||||||
|
return self.close()
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Helper = {
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Creates a new Helper instance
|
||||||
|
-- @param host param
|
||||||
|
-- @param port param
|
||||||
|
-- @return o new instance of Helper
|
||||||
|
new = function(self, host, port)
|
||||||
|
local o = { session = Session:new(host, port) }
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Connects to the server
|
||||||
|
-- @return status true on success, false on failure
|
||||||
|
connect = function(self)
|
||||||
|
return self.session:connect()
|
||||||
|
end,
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Lists portals
|
||||||
|
-- @return status true on success, false on failure
|
||||||
|
-- @return resulst list of iSCSI nodes, err string on failure
|
||||||
|
listPortals = function(self)
|
||||||
|
local attribs, name = Attributes:new(), "iqn.control.node\0por"
|
||||||
|
|
||||||
|
attribs:add(Attribute.Tag.ISNS_TAG_ISCSI_NAME, name)
|
||||||
|
attribs:add(Attribute.Tag.ISNS_TAG_PORTAL_IP_ADDRESS)
|
||||||
|
attribs:add(Attribute.Tag.ISNS_TAG_DELIMITER)
|
||||||
|
attribs:add(Attribute.Tag.ISNS_TAG_PORTAL_IP_ADDRESS)
|
||||||
|
attribs:add(Attribute.Tag.ISNS_TAG_PORTAL_TCP_UDP_PORT)
|
||||||
|
attribs:add(Attribute.Tag.ISNS_TAG_ENTITY_IDENTIFIER)
|
||||||
|
|
||||||
|
local flags = 0x8c00 -- Sender is iSNS client, Last PDU, First PDU
|
||||||
|
|
||||||
|
local req = Request:new(Request.FuncId.DevAttrQry, flags, tostring(attribs))
|
||||||
|
if ( not(self.session:send(req)) ) then
|
||||||
|
return false, "Failed to send message to server"
|
||||||
|
end
|
||||||
|
|
||||||
|
local status, resp = self.session:receive()
|
||||||
|
if ( not(status) ) then
|
||||||
|
return false, "Failed to receive message from server"
|
||||||
|
end
|
||||||
|
|
||||||
|
local results = {}
|
||||||
|
local addr, proto, port
|
||||||
|
for _, attr in ipairs(resp.attrs) do
|
||||||
|
if ( attr.tag == Attribute.Tag.ISNS_TAG_PORTAL_IP_ADDRESS ) then
|
||||||
|
addr = attr.val
|
||||||
|
local pos, is_ipv4 = bin.unpack("A12", addr)
|
||||||
|
if ( is_ipv4 == "\0\0\0\0\0\0\0\0\0\0\xFF\xFF" ) then
|
||||||
|
local pos, bin_ip = bin.unpack("B4", addr, 13)
|
||||||
|
addr = ipops.bin_to_ip(bin_ip)
|
||||||
|
else
|
||||||
|
local pos, bin_ip = bin.unpack("B16", addr)
|
||||||
|
addr = ipops.bin_to_ip(bin_ip)
|
||||||
|
end
|
||||||
|
elseif ( attr.tag == Attribute.Tag.ISNS_TAG_PORTAL_TCP_UDP_PORT ) then
|
||||||
|
local pos, s1
|
||||||
|
pos, s1, port = bin.unpack(">SS", attr.val)
|
||||||
|
|
||||||
|
if ( s1 == 1 ) then
|
||||||
|
proto = "udp"
|
||||||
|
elseif ( s1 == 0 ) then
|
||||||
|
proto = "tcp"
|
||||||
|
else
|
||||||
|
proto = "UNKNOWN"
|
||||||
|
end
|
||||||
|
elseif ( addr and proto and port ) then
|
||||||
|
table.insert(results, { addr = addr, proto = proto, port = port } )
|
||||||
|
addr, proto, port = nil, nil, nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true, results
|
||||||
|
end,
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Lists iSCSI nodes
|
||||||
|
-- @return status true on success, false on failure
|
||||||
|
-- @return resulst list of iSCSI nodes, err string on failure
|
||||||
|
listISCINodes = function(self)
|
||||||
|
local attribs = Attributes:new()
|
||||||
|
local name = "iqn.control.node\0por"
|
||||||
|
attribs:add(Attribute.Tag.ISNS_TAG_ISCSI_NAME, name)
|
||||||
|
attribs:add(Attribute.Tag.ISNS_TAG_ISCSI_NAME)
|
||||||
|
attribs:add(Attribute.Tag.ISNS_TAG_DELIMITER)
|
||||||
|
attribs:add(Attribute.Tag.ISNS_TAG_ISCSI_NAME)
|
||||||
|
attribs:add(Attribute.Tag.ISNS_TAG_ISCSI_NODE_TYPE)
|
||||||
|
|
||||||
|
local flags = 0x8c00 -- Sender is iSNS client, Last PDU, First PDU
|
||||||
|
|
||||||
|
local req = Request:new(Request.FuncId.DevAttrQry, flags, tostring(attribs))
|
||||||
|
if ( not(self.session:send(req)) ) then
|
||||||
|
return false, "Failed to send message to server"
|
||||||
|
end
|
||||||
|
|
||||||
|
local status, resp = self.session:receive()
|
||||||
|
if ( not(status) ) then
|
||||||
|
return false, "Failed to receive message from server"
|
||||||
|
end
|
||||||
|
|
||||||
|
local name, ntype
|
||||||
|
local results = {}
|
||||||
|
for _, attr in ipairs(resp.attrs) do
|
||||||
|
if ( attr.tag == Attribute.Tag.ISNS_TAG_ISCSI_NAME ) then
|
||||||
|
name = attr.val
|
||||||
|
elseif( attr.tag == Attribute.Tag.ISNS_TAG_ISCSI_NODE_TYPE ) then
|
||||||
|
local _, val = bin.unpack(">I", attr.val)
|
||||||
|
if ( val == iSCSI.NodeType.CONTROL ) then
|
||||||
|
ntype = "Control"
|
||||||
|
elseif ( val == iSCSI.NodeType.INITIATOR ) then
|
||||||
|
ntype = "Initiator"
|
||||||
|
elseif ( val == iSCSI.NodeType.TARGET ) then
|
||||||
|
ntype = "Target"
|
||||||
|
else
|
||||||
|
ntype = "Unknown"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if ( name and ntype ) then
|
||||||
|
table.insert(results, { name = name:match("^([^\0]*)"), type = ntype })
|
||||||
|
name, ntype = nil, nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true, results
|
||||||
|
end,
|
||||||
|
|
||||||
|
close = function(self)
|
||||||
|
return self.session:close()
|
||||||
|
end,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return _ENV;
|
||||||
70
scripts/isns-info.nse
Normal file
70
scripts/isns-info.nse
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
local stdnse = require "stdnse"
|
||||||
|
local shortport = require "shortport"
|
||||||
|
local isns = require "isns"
|
||||||
|
local tab = require "tab"
|
||||||
|
|
||||||
|
description = [[
|
||||||
|
Lists portals and iSCSI nodes registered with the Internet Storage Name
|
||||||
|
Service (iSNS).
|
||||||
|
]]
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @usage
|
||||||
|
-- nmap -p 3205 <ip> --script isns-info
|
||||||
|
--
|
||||||
|
-- @output
|
||||||
|
-- PORT STATE SERVICE
|
||||||
|
-- 3205/tcp open unknown
|
||||||
|
-- | isns-info:
|
||||||
|
-- | Portal
|
||||||
|
-- | ip port
|
||||||
|
-- | 192.168.0.1 3260/tcp
|
||||||
|
-- | 192.168.0.2 3260/tcp
|
||||||
|
-- | iSCSI Nodes
|
||||||
|
-- | node type
|
||||||
|
-- | iqn.2001-04.com.example:storage.disk2.sys1.xyz Target
|
||||||
|
-- | iqn.2001-05.com.example:storage.disk2.sys1.xyz Target
|
||||||
|
-- |_ iqn.2001-04.a.com.example:storage.disk3.sys2.abc Target
|
||||||
|
--
|
||||||
|
|
||||||
|
portrule = shortport.port_or_service(3205, 'isns')
|
||||||
|
|
||||||
|
author = "Patrik Karlsson"
|
||||||
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||||
|
categories = {"safe", "discovery"}
|
||||||
|
|
||||||
|
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
||||||
|
|
||||||
|
action = function(host, port)
|
||||||
|
local helper = isns.Helper:new(host, port)
|
||||||
|
if ( not(helper:connect()) ) then
|
||||||
|
return fail("Failed to connect to server")
|
||||||
|
end
|
||||||
|
|
||||||
|
local status, portals = helper:listPortals()
|
||||||
|
if ( not(status) ) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local results = {}
|
||||||
|
local restab = tab.new(2)
|
||||||
|
tab.addrow(restab, "ip", "port")
|
||||||
|
for _, portal in ipairs(portals) do
|
||||||
|
tab.addrow(restab, portal.addr, ("%d/%s"):format(portal.port, portal.proto))
|
||||||
|
end
|
||||||
|
table.insert(results, { name = "Portal", tab.dump(restab) })
|
||||||
|
|
||||||
|
local status, nodes = helper:listISCINodes()
|
||||||
|
if ( not(status) ) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
restab = tab.new(2)
|
||||||
|
tab.addrow(restab, "node", "type")
|
||||||
|
for _, portal in ipairs(nodes) do
|
||||||
|
tab.addrow(restab, portal.name, portal.type)
|
||||||
|
end
|
||||||
|
table.insert(results, { name = "iSCSI Nodes", tab.dump(restab) })
|
||||||
|
|
||||||
|
return stdnse.format_output(true, results)
|
||||||
|
end
|
||||||
@@ -166,7 +166,7 @@ Entry { filename = "http-robtex-reverse-ip.nse", categories = { "discovery", "ex
|
|||||||
Entry { filename = "http-robtex-shared-ns.nse", categories = { "discovery", "external", "safe", } }
|
Entry { filename = "http-robtex-shared-ns.nse", categories = { "discovery", "external", "safe", } }
|
||||||
Entry { filename = "http-title.nse", categories = { "default", "discovery", "safe", } }
|
Entry { filename = "http-title.nse", categories = { "default", "discovery", "safe", } }
|
||||||
Entry { filename = "http-trace.nse", categories = { "discovery", "safe", "vuln", } }
|
Entry { filename = "http-trace.nse", categories = { "discovery", "safe", "vuln", } }
|
||||||
Entry { filename = "http-traceroute.nse", categories = {"discovery", "safe", } }
|
Entry { filename = "http-traceroute.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "http-unsafe-output-escaping.nse", categories = { "discovery", "intrusive", } }
|
Entry { filename = "http-unsafe-output-escaping.nse", categories = { "discovery", "intrusive", } }
|
||||||
Entry { filename = "http-userdir-enum.nse", categories = { "auth", "intrusive", } }
|
Entry { filename = "http-userdir-enum.nse", categories = { "auth", "intrusive", } }
|
||||||
Entry { filename = "http-vhosts.nse", categories = { "discovery", "intrusive", } }
|
Entry { filename = "http-vhosts.nse", categories = { "discovery", "intrusive", } }
|
||||||
@@ -203,6 +203,7 @@ Entry { filename = "irc-info.nse", categories = { "default", "discovery", "safe"
|
|||||||
Entry { filename = "irc-unrealircd-backdoor.nse", categories = { "exploit", "intrusive", "malware", "vuln", } }
|
Entry { filename = "irc-unrealircd-backdoor.nse", categories = { "exploit", "intrusive", "malware", "vuln", } }
|
||||||
Entry { filename = "iscsi-brute.nse", categories = { "brute", "intrusive", } }
|
Entry { filename = "iscsi-brute.nse", categories = { "brute", "intrusive", } }
|
||||||
Entry { filename = "iscsi-info.nse", categories = { "default", "discovery", "safe", } }
|
Entry { filename = "iscsi-info.nse", categories = { "default", "discovery", "safe", } }
|
||||||
|
Entry { filename = "isns-info.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "jdwp-version.nse", categories = { "version", } }
|
Entry { filename = "jdwp-version.nse", categories = { "version", } }
|
||||||
Entry { filename = "krb5-enum-users.nse", categories = { "auth", "intrusive", } }
|
Entry { filename = "krb5-enum-users.nse", categories = { "auth", "intrusive", } }
|
||||||
Entry { filename = "ldap-brute.nse", categories = { "brute", "intrusive", } }
|
Entry { filename = "ldap-brute.nse", categories = { "brute", "intrusive", } }
|
||||||
@@ -289,6 +290,7 @@ Entry { filename = "rexec-brute.nse", categories = { "brute", "intrusive", } }
|
|||||||
Entry { filename = "riak-http-info.nse", categories = { "discovery", "safe", } }
|
Entry { filename = "riak-http-info.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "rlogin-brute.nse", categories = { "brute", "intrusive", } }
|
Entry { filename = "rlogin-brute.nse", categories = { "brute", "intrusive", } }
|
||||||
Entry { filename = "rmi-dumpregistry.nse", categories = { "default", "discovery", "safe", } }
|
Entry { filename = "rmi-dumpregistry.nse", categories = { "default", "discovery", "safe", } }
|
||||||
|
Entry { filename = "rmi-vuln-classloader.nse", categories = { "intrusive", "vuln", } }
|
||||||
Entry { filename = "rpcap-brute.nse", categories = { "brute", "intrusive", } }
|
Entry { filename = "rpcap-brute.nse", categories = { "brute", "intrusive", } }
|
||||||
Entry { filename = "rpcap-info.nse", categories = { "discovery", "safe", } }
|
Entry { filename = "rpcap-info.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "rpcinfo.nse", categories = { "default", "discovery", "safe", } }
|
Entry { filename = "rpcinfo.nse", categories = { "default", "discovery", "safe", } }
|
||||||
|
|||||||
Reference in New Issue
Block a user