mirror of
https://github.com/nmap/nmap.git
synced 2025-12-24 16:39:03 +00:00
o [NSE] Added rdp library and the script rdp-enum-encryption that enumerates
both the Security Layer and Encryption level of the RDP service. [Patrik Karlsson]
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
# Nmap Changelog ($Id$); -*-text-*-
|
# Nmap Changelog ($Id$); -*-text-*-
|
||||||
|
|
||||||
|
o [NSE] Added rdp library and the script rdp-enum-encryption that enumerates
|
||||||
|
both the Security Layer and Encryption level of the RDP service. [Patrik
|
||||||
|
Karlsson]
|
||||||
|
|
||||||
o [NSE] Added flume-master-info by John Bond. This script gets info
|
o [NSE] Added flume-master-info by John Bond. This script gets info
|
||||||
from Apache Flume, which is a log collection service.
|
from Apache Flume, which is a log collection service.
|
||||||
|
|
||||||
|
|||||||
337
nselib/rdp.lua
Normal file
337
nselib/rdp.lua
Normal file
@@ -0,0 +1,337 @@
|
|||||||
|
---
|
||||||
|
-- A minimal RDP library. Currently has functionality to determine encryption
|
||||||
|
-- and cipher support.
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- @author "Patrik Karlsson <patrik@cqure.net>"
|
||||||
|
-- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html
|
||||||
|
--
|
||||||
|
|
||||||
|
local bin = require("bin")
|
||||||
|
local stdnse = require("stdnse")
|
||||||
|
_ENV = stdnse.module("rdp", stdnse.seeall)
|
||||||
|
|
||||||
|
Packet = {
|
||||||
|
|
||||||
|
TPKT = {
|
||||||
|
|
||||||
|
new = function(self, data)
|
||||||
|
local o = { data = tostring(data), version = 3 }
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
__tostring = function(self)
|
||||||
|
return bin.pack(">CCSA",
|
||||||
|
self.version,
|
||||||
|
self.reserved or 0,
|
||||||
|
(self.data and #self.data + 4 or 4),
|
||||||
|
self.data
|
||||||
|
)
|
||||||
|
end,
|
||||||
|
|
||||||
|
parse = function(data)
|
||||||
|
local tpkt = Packet.TPKT:new()
|
||||||
|
local pos
|
||||||
|
|
||||||
|
pos, tpkt.version, tpkt.reserved, tpkt.length = bin.unpack(">CCS", data)
|
||||||
|
pos, tpkt.data = bin.unpack("A" .. (#data - pos), data, pos)
|
||||||
|
return tpkt
|
||||||
|
end
|
||||||
|
},
|
||||||
|
|
||||||
|
ITUT = {
|
||||||
|
|
||||||
|
new = function(self, code, data)
|
||||||
|
local o = { data = tostring(data), code = code }
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
parse = function(data)
|
||||||
|
local itut = Packet.ITUT:new()
|
||||||
|
local pos
|
||||||
|
|
||||||
|
pos, itut.length, itut.code = bin.unpack("CC", data)
|
||||||
|
|
||||||
|
if ( itut.code == 0xF0 ) then
|
||||||
|
pos, itut.eot = bin.unpack("C", data, pos)
|
||||||
|
elseif ( itut.code == 0xD0 ) then
|
||||||
|
pos, itut.dstref, itut.srcref, itut.class = bin.unpack(">SSC", data, pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
pos, itut.data = bin.unpack("A" .. (#data - pos), data, pos)
|
||||||
|
return itut
|
||||||
|
end,
|
||||||
|
|
||||||
|
__tostring = function(self)
|
||||||
|
local len = (self.code ~= 0xF0 and #self.data + 1 or 2)
|
||||||
|
local data = bin.pack("CC",
|
||||||
|
len,
|
||||||
|
self.code or 0
|
||||||
|
)
|
||||||
|
|
||||||
|
if ( self.code == 0xF0 ) then
|
||||||
|
data = data .. bin.pack("C", 0x80) -- EOT
|
||||||
|
end
|
||||||
|
|
||||||
|
return data .. self.data
|
||||||
|
end,
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Request = {
|
||||||
|
|
||||||
|
ConnectionRequest = {
|
||||||
|
|
||||||
|
new = function(self, proto)
|
||||||
|
local o = { proto = proto }
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
__tostring = function(self)
|
||||||
|
local cookie = "mstshash=nmap"
|
||||||
|
local itpkt_len = 21 + #cookie
|
||||||
|
local itut_len = 16 + #cookie
|
||||||
|
|
||||||
|
local data = bin.pack(">SSCA",
|
||||||
|
0x0000, -- dst reference
|
||||||
|
0x0000, -- src reference
|
||||||
|
0x00, -- class and options
|
||||||
|
("Cookie: %s\r\n"):format(cookie))
|
||||||
|
|
||||||
|
if ( self.proto ) then
|
||||||
|
data = data .. bin.pack("<II",
|
||||||
|
0x00080001, -- Unknown
|
||||||
|
self.proto -- protocol
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return tostring(Packet.TPKT:new(Packet.ITUT:new(0xE0, data)))
|
||||||
|
end
|
||||||
|
},
|
||||||
|
|
||||||
|
MCSConnectInitial = {
|
||||||
|
|
||||||
|
new = function(self, cipher)
|
||||||
|
local o = { cipher = cipher }
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
__tostring = function(self)
|
||||||
|
|
||||||
|
local data = bin.pack("<HIH",
|
||||||
|
"7f 65" .. -- BER: Application-Defined Type = APPLICATION 101,
|
||||||
|
"82 01 90" .. -- BER: Type Length = 404 bytes
|
||||||
|
"04 01 01" .. -- Connect-Initial::callingDomainSelector
|
||||||
|
"04 01 01" .. -- Connect-Initial::calledDomainSelector
|
||||||
|
"01 01 ff" .. -- Connect-Initial::upwardFlag = TRUE
|
||||||
|
"30 19" .. -- Connect-Initial::targetParameters (25 bytes)
|
||||||
|
"02 01 22" .. -- DomainParameters::maxChannelIds = 34
|
||||||
|
"02 01 02" .. -- DomainParameters::maxUserIds = 2
|
||||||
|
"02 01 00" .. -- DomainParameters::maxTokenIds = 0
|
||||||
|
"02 01 01" .. -- DomainParameters::numPriorities = 1
|
||||||
|
"02 01 00" .. -- DomainParameters::minThroughput = 0
|
||||||
|
"02 01 01" .. -- DomainParameters::maxHeight = 1
|
||||||
|
"02 02 ff ff" .. -- DomainParameters::maxMCSPDUsize = 65535
|
||||||
|
"02 01 02" .. -- DomainParameters::protocolVersion = 2
|
||||||
|
"30 19" .. -- Connect-Initial::minimumParameters (25 bytes)
|
||||||
|
"02 01 01" .. -- DomainParameters::maxChannelIds = 1
|
||||||
|
"02 01 01" .. -- DomainParameters::maxUserIds = 1
|
||||||
|
"02 01 01" .. -- DomainParameters::maxTokenIds = 1
|
||||||
|
"02 01 01" .. -- DomainParameters::numPriorities = 1
|
||||||
|
"02 01 00" .. -- DomainParameters::minThroughput = 0
|
||||||
|
"02 01 01" .. -- DomainParameters::maxHeight = 1
|
||||||
|
"02 02 04 20" .. -- DomainParameters::maxMCSPDUsize = 1056
|
||||||
|
"02 01 02" .. -- DomainParameters::protocolVersion = 2
|
||||||
|
"30 1c" .. -- Connect-Initial::maximumParameters (28 bytes)
|
||||||
|
"02 02 ff ff" .. -- DomainParameters::maxChannelIds = 65535
|
||||||
|
"02 02 fc 17" .. -- DomainParameters::maxUserIds = 64535
|
||||||
|
"02 02 ff ff" .. -- DomainParameters::maxTokenIds = 65535
|
||||||
|
"02 01 01" .. -- DomainParameters::numPriorities = 1
|
||||||
|
"02 01 00" .. -- DomainParameters::minThroughput = 0
|
||||||
|
"02 01 01" .. -- DomainParameters::maxHeight = 1
|
||||||
|
"02 02 ff ff" .. -- DomainParameters::maxMCSPDUsize = 65535
|
||||||
|
"02 01 02" .. -- DomainParameters::protocolVersion = 2
|
||||||
|
"04 82 01 2f" .. -- Connect-Initial::userData (307 bytes)
|
||||||
|
"00 05" .. -- object length = 5 bytes
|
||||||
|
"00 14 7c 00 01" .. -- object
|
||||||
|
"81 26" .. -- ConnectData::connectPDU length = 298 bytes
|
||||||
|
"00 08 00 10 00 01 c0 00 44 75 63 61 81 18" .. -- PER encoded (ALIGNED variant of BASIC-PER) GCC Conference Create Request PDU
|
||||||
|
"01 c0 d4 00" .. -- TS_UD_HEADER::type = CS_CORE (0xc001), length = 216 bytes
|
||||||
|
"04 00 08 00" .. -- TS_UD_CS_CORE::version = 0x0008004
|
||||||
|
"00 05" .. -- TS_UD_CS_CORE::desktopWidth = 1280
|
||||||
|
"20 03" .. -- TS_UD_CS_CORE::desktopHeight = 1024
|
||||||
|
"01 ca" .. -- TS_UD_CS_CORE::colorDepth = RNS_UD_COLOR_8BPP (0xca01)
|
||||||
|
"03 aa" .. -- TS_UD_CS_CORE::SASSequence
|
||||||
|
"09 08 00 00" .. -- TS_UD_CS_CORE::keyboardLayout = 0x409 = 1033 = English (US)
|
||||||
|
"28 0a 00 00" .. -- TS_UD_CS_CORE::clientBuild = 3790
|
||||||
|
"45 00 4d 00 50 00 2d 00 4c 00 41 00 50 00 2d 00 30 00 30 00 31 00 34 00 00 00 00 00 00 00 00 00" .. -- TS_UD_CS_CORE::clientName = ELTONS-TEST2
|
||||||
|
"04 00 00 00" .. -- TS_UD_CS_CORE::keyboardType
|
||||||
|
"00 00 00 00" .. -- TS_UD_CS_CORE::keyboardSubtype
|
||||||
|
"0c 00 00 00" .. -- TS_UD_CS_CORE::keyboardFunctionKey
|
||||||
|
"00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " ..
|
||||||
|
"00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " ..
|
||||||
|
"00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " ..
|
||||||
|
"00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " .. -- TS_UD_CS_CORE::imeFileName = ""
|
||||||
|
"01 ca" .. -- TS_UD_CS_CORE::postBeta2ColorDepth = RNS_UD_COLOR_8BPP (0xca01)
|
||||||
|
"01 00" .. -- TS_UD_CS_CORE::clientProductId
|
||||||
|
"00 00 00 00" .. -- TS_UD_CS_CORE::serialNumber
|
||||||
|
"10 00" .. -- TS_UD_CS_CORE::highColorDepth = 24 bpp
|
||||||
|
"07 00" .. -- TS_UD_CS_CORE::supportedColorDepths
|
||||||
|
"01 00" .. -- TS_UD_CS_CORE::earlyCapabilityFlags
|
||||||
|
"36 00 39 00 37 00 31 00 32 00 2d 00 37 00 38 00 " ..
|
||||||
|
"33 00 2d 00 30 00 33 00 35 00 37 00 39 00 37 00 " ..
|
||||||
|
"34 00 2d 00 34 00 32 00 37 00 31 00 34 00 00 00 " ..
|
||||||
|
"00 00 00 00 00 00 00 00 00 00 00 00 " .. -- TS_UD_CS_CORE::clientDigProductId = "69712-783-0357974-42714"
|
||||||
|
"00" .. -- TS_UD_CS_CORE::connectionType = 0 (not used as RNS_UD_CS_VALID_CONNECTION_TYPE not set)
|
||||||
|
"00" .. -- TS_UD_CS_CORE::pad1octet
|
||||||
|
"00 00 00 00" .. -- TS_UD_CS_CORE::serverSelectedProtocol
|
||||||
|
"04 c0 0c 00" .. -- TS_UD_HEADER::type = CS_CLUSTER (0xc004), length = 12 bytes
|
||||||
|
"09 00 00 00" .. -- TS_UD_CS_CLUSTER::Flags = 0x0d
|
||||||
|
"00 00 00 00" .. -- TS_UD_CS_CLUSTER::RedirectedSessionID
|
||||||
|
"02 c0 0c 00", -- TS_UD_HEADER::type = CS_SECURITY (0xc002), length = 12 bytes
|
||||||
|
-- "1b 00 00 00" .. -- TS_UD_CS_SEC::encryptionMethods
|
||||||
|
self.cipher or 0,
|
||||||
|
"00 00 00 00" .. -- TS_UD_CS_SEC::extEncryptionMethods
|
||||||
|
"03 c0 2c 00" .. -- TS_UD_HEADER::type = CS_NET (0xc003), length = 44 bytes
|
||||||
|
"03 00 00 00" .. -- TS_UD_CS_NET::channelCount = 3
|
||||||
|
"72 64 70 64 72 00 00 00" .. -- CHANNEL_DEF::name = "rdpdr"
|
||||||
|
"00 00 80 80" .. -- CHANNEL_DEF::options = 0x80800000
|
||||||
|
"63 6c 69 70 72 64 72 00" .. -- CHANNEL_DEF::name = "cliprdr"
|
||||||
|
"00 00 a0 c0" .. -- CHANNEL_DEF::options = 0xc0a00000
|
||||||
|
"72 64 70 73 6e 64 00 00" .. -- CHANNEL_DEF::name = "rdpsnd"
|
||||||
|
"00 00 00 c0" -- CHANNEL_DEF::options = 0xc0000000
|
||||||
|
)
|
||||||
|
return tostring(Packet.TPKT:new(Packet.ITUT:new(0xF0, data)))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Response = {
|
||||||
|
|
||||||
|
ConnectionConfirm = {
|
||||||
|
|
||||||
|
new = function(self)
|
||||||
|
local o = { }
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
parse = function(data)
|
||||||
|
local cc = Response.ConnectionConfirm:new()
|
||||||
|
local pos, _
|
||||||
|
|
||||||
|
cc.tpkt = Packet.TPKT.parse(data)
|
||||||
|
cc.itut = Packet.ITUT.parse(cc.tpkt.data)
|
||||||
|
return cc
|
||||||
|
end,
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
MCSConnectResponse = {
|
||||||
|
new = function(self)
|
||||||
|
local o = { }
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
parse = function(data)
|
||||||
|
local cr = Response.MCSConnectResponse:new()
|
||||||
|
|
||||||
|
cr.tpkt = Packet.TPKT.parse(data)
|
||||||
|
cr.itut = Packet.ITUT.parse(cr.tpkt.data)
|
||||||
|
return cr
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Comm = {
|
||||||
|
|
||||||
|
-- Creates a new Comm instance
|
||||||
|
-- @param host table
|
||||||
|
-- @param port table
|
||||||
|
-- @return o instance of Comm
|
||||||
|
new = function(self, host, port)
|
||||||
|
local o = { host = host, port = port }
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Connect to the server
|
||||||
|
-- @return status true on success, false on failure
|
||||||
|
-- @return err string containing error message, if status is false
|
||||||
|
connect = function(self)
|
||||||
|
self.socket = nmap.new_socket()
|
||||||
|
self.socket:set_timeout(5000)
|
||||||
|
if ( not(self.socket:connect(self.host, self.port)) ) then
|
||||||
|
return false, "Failed connecting to server"
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Close the connection to the server
|
||||||
|
-- @return status true on success, false on failure
|
||||||
|
close = function(self)
|
||||||
|
return self.socket:close()
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Sends a message to the server
|
||||||
|
-- @param pkt an instance of Request.*
|
||||||
|
-- @return status true on success, false on failure
|
||||||
|
-- @return err string containing error message, if status is false
|
||||||
|
send = function(self, pkt)
|
||||||
|
return self.socket:send(tostring(pkt))
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Receives a message from the server
|
||||||
|
-- @return status true on success, false on failure
|
||||||
|
-- @return err string containing error message, if status is false
|
||||||
|
recv = function(self)
|
||||||
|
return self.socket:receive()
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Sends a message to the server and receives the response
|
||||||
|
-- @param pkt an instance of Request.*
|
||||||
|
-- @return status true on success, false on failure
|
||||||
|
-- @return err string containing error message, if status is false
|
||||||
|
-- pkt instance of Response.* on success
|
||||||
|
exch = function(self, pkt)
|
||||||
|
local status, err = self:send(pkt)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return false, err
|
||||||
|
end
|
||||||
|
|
||||||
|
local data
|
||||||
|
status, data = self:recv()
|
||||||
|
if ( #data< 5 ) then
|
||||||
|
return false, "Packet too short"
|
||||||
|
end
|
||||||
|
|
||||||
|
local pos, itut_code = bin.unpack("C", data, 6)
|
||||||
|
if ( itut_code == 0xD0 ) then
|
||||||
|
stdnse.print_debug(2, "RDP: Received ConnectionConfirm response")
|
||||||
|
return true, Response.ConnectionConfirm.parse(data)
|
||||||
|
elseif ( itut_code == 0xF0 ) then
|
||||||
|
return true, Response.MCSConnectResponse.parse(data)
|
||||||
|
end
|
||||||
|
return false, "Received unhandled packet"
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
return _ENV;
|
||||||
160
scripts/rdp-enum-encryption.nse
Normal file
160
scripts/rdp-enum-encryption.nse
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
description = [[
|
||||||
|
Determines what Security layer and Encryption level that is supported by the
|
||||||
|
RDP service. It does so by cycling through all existing protocols and ciphers.
|
||||||
|
When run in debug mode, the script also returns the protocols and ciphers that
|
||||||
|
fail and any errors that were reported.
|
||||||
|
|
||||||
|
The script was inspired by MWR's RDP Cipher Checker
|
||||||
|
http://labs.mwrinfosecurity.com/tools/2009/01/12/rdp-cipher-checker/
|
||||||
|
]]
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @usage
|
||||||
|
-- nmap -p 3389 --script rdp-enum-encryption <ip>
|
||||||
|
--
|
||||||
|
-- @output
|
||||||
|
-- PORT STATE SERVICE
|
||||||
|
-- 3389/tcp open ms-wbt-server
|
||||||
|
-- | rdp-enum-encryption:
|
||||||
|
-- | Security layer
|
||||||
|
-- | CredSSP: SUCCESS
|
||||||
|
-- | Native RDP: SUCCESS
|
||||||
|
-- | SSL: SUCCESS
|
||||||
|
-- | RDP Encryption level: High
|
||||||
|
-- | 128-bit RC4: SUCCESS
|
||||||
|
-- |_ FIPS 140-1: SUCCESS
|
||||||
|
--
|
||||||
|
|
||||||
|
author = "Patrik Karlsson"
|
||||||
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||||
|
|
||||||
|
|
||||||
|
local shortport = require("shortport")
|
||||||
|
local rdp = require("rdp")
|
||||||
|
local stdnse = require("stdnse")
|
||||||
|
|
||||||
|
categories = {"safe", "discovery"}
|
||||||
|
|
||||||
|
portrule = shortport.port_or_service(3389, "ms-wbt-server")
|
||||||
|
|
||||||
|
local function enum_protocols(host, port)
|
||||||
|
local PROTOCOLS = {
|
||||||
|
["Native RDP"] = 0,
|
||||||
|
["SSL"] = 1,
|
||||||
|
["CredSSP"] = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
local ERRORS = {
|
||||||
|
[1] = "SSL_REQUIRED_BY_SERVER",
|
||||||
|
[2] = "SSL_NOT_ALLOWED_BY_SERVER",
|
||||||
|
[3] = "SSL_CERT_NOT_ON_SERVER",
|
||||||
|
[4] = "INCONSISTENT_FLAGS",
|
||||||
|
[5] = "HYBRID_REQUIRED_BY_SERVER"
|
||||||
|
}
|
||||||
|
|
||||||
|
local res_proto = { name = "Security layer" }
|
||||||
|
|
||||||
|
for k, v in pairs(PROTOCOLS) do
|
||||||
|
local comm = rdp.Comm:new(host, port)
|
||||||
|
if ( not(comm:connect()) ) then
|
||||||
|
return false, "ERROR: Failed to connect to server"
|
||||||
|
end
|
||||||
|
local cr = rdp.Request.ConnectionRequest:new(v)
|
||||||
|
status, response = comm:exch(cr)
|
||||||
|
comm:close()
|
||||||
|
if ( not(status) ) then
|
||||||
|
return false, response
|
||||||
|
end
|
||||||
|
|
||||||
|
local pos, success = bin.unpack("C", response.itut.data)
|
||||||
|
if ( success == 2 ) then
|
||||||
|
table.insert(res_proto, ("%s: SUCCESS"):format(k))
|
||||||
|
elseif ( nmap.debugging() > 0 ) then
|
||||||
|
local pos, err = bin.unpack("C", response.itut.data, 5)
|
||||||
|
if ( err > 0 ) then
|
||||||
|
table.insert(res_proto, ("%s: FAILED (%s)"):format(k, ERRORS[err] or "Unknown"))
|
||||||
|
else
|
||||||
|
table.insert(res_proto, ("%s: FAILED"):format(k))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(res_proto)
|
||||||
|
return true, res_proto
|
||||||
|
end
|
||||||
|
|
||||||
|
local function enum_ciphers(host, port)
|
||||||
|
|
||||||
|
local CIPHERS = {
|
||||||
|
{ ["40-bit RC4"] = 1 },
|
||||||
|
{ ["56-bit RC4"] = 8 },
|
||||||
|
{ ["128-bit RC4"] = 2 },
|
||||||
|
{ ["FIPS 140-1"] = 16 }
|
||||||
|
}
|
||||||
|
|
||||||
|
local ENC_LEVELS = {
|
||||||
|
[0] = "None",
|
||||||
|
[1] = "Low",
|
||||||
|
[2] = "Client Compatible",
|
||||||
|
[3] = "High",
|
||||||
|
[4] = "FIPS Compliant",
|
||||||
|
}
|
||||||
|
|
||||||
|
local res_ciphers = {}
|
||||||
|
|
||||||
|
local function get_ordered_ciphers()
|
||||||
|
i = 0
|
||||||
|
return function()
|
||||||
|
i = i + 1
|
||||||
|
if ( not(CIPHERS[i]) ) then return end
|
||||||
|
for k,v in pairs(CIPHERS[i]) do
|
||||||
|
return k, v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for k, v in get_ordered_ciphers() do
|
||||||
|
local comm = rdp.Comm:new(host, port)
|
||||||
|
if ( not(comm:connect()) ) then
|
||||||
|
return false, "ERROR: Failed to connect to server"
|
||||||
|
end
|
||||||
|
|
||||||
|
local cr = rdp.Request.ConnectionRequest:new()
|
||||||
|
status, response = comm:exch(cr)
|
||||||
|
if ( not(status) ) then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
local msc = rdp.Request.MCSConnectInitial:new(v)
|
||||||
|
local status, response = comm:exch(msc)
|
||||||
|
comm:close()
|
||||||
|
if ( status ) then
|
||||||
|
local pos, enc_level = bin.unpack("C", response.itut.data, 95 + 8)
|
||||||
|
local pos, enc_cipher= bin.unpack("C", response.itut.data, 95 + 4)
|
||||||
|
if ( enc_cipher == v ) then
|
||||||
|
table.insert(res_ciphers, ("%s: SUCCESS"):format(k))
|
||||||
|
end
|
||||||
|
res_ciphers.name = ("RDP Encryption level: %s"):format(ENC_LEVELS[enc_level] or "Unknown")
|
||||||
|
elseif ( nmap.debugging() > 0 ) then
|
||||||
|
table.insert(res_ciphers, ("%s: FAILURE"):format(k))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true, res_ciphers
|
||||||
|
end
|
||||||
|
|
||||||
|
action = function(host, port)
|
||||||
|
local result = {}
|
||||||
|
|
||||||
|
local status, res_proto = enum_protocols(host, port)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return res_proto
|
||||||
|
end
|
||||||
|
|
||||||
|
local status, res_ciphers = enum_ciphers(host, port)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return res_ciphers
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(result, res_proto)
|
||||||
|
table.insert(result, res_ciphers)
|
||||||
|
return stdnse.format_output(true, result)
|
||||||
|
end
|
||||||
@@ -301,6 +301,7 @@ Entry { filename = "pptp-version.nse", categories = { "version", } }
|
|||||||
Entry { filename = "qscan.nse", categories = { "discovery", "safe", } }
|
Entry { filename = "qscan.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "quake3-info.nse", categories = { "default", "discovery", "safe", "version", } }
|
Entry { filename = "quake3-info.nse", categories = { "default", "discovery", "safe", "version", } }
|
||||||
Entry { filename = "quake3-master-getservers.nse", categories = { "default", "discovery", "safe", } }
|
Entry { filename = "quake3-master-getservers.nse", categories = { "default", "discovery", "safe", } }
|
||||||
|
Entry { filename = "rdp-enum-encryption.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "rdp-vuln-ms12-020.nse", categories = { "intrusive", "vuln", } }
|
Entry { filename = "rdp-vuln-ms12-020.nse", categories = { "intrusive", "vuln", } }
|
||||||
Entry { filename = "realvnc-auth-bypass.nse", categories = { "auth", "default", "safe", } }
|
Entry { filename = "realvnc-auth-bypass.nse", categories = { "auth", "default", "safe", } }
|
||||||
Entry { filename = "redis-brute.nse", categories = { "brute", "intrusive", } }
|
Entry { filename = "redis-brute.nse", categories = { "brute", "intrusive", } }
|
||||||
|
|||||||
Reference in New Issue
Block a user