diff --git a/nselib/msrpc.lua b/nselib/msrpc.lua index 52e186968..a7db422d9 100644 --- a/nselib/msrpc.lua +++ b/nselib/msrpc.lua @@ -311,7 +311,7 @@ local function call_function(smbstate, opnum, arguments) 0x18 + string.len(arguments), -- Frag length (0x18 = the size of this data) 0x0000, -- Auth length 0x41414141, -- Call ID (I use 'AAAA' because it's easy to recognize) - 0x0 + string.len(arguments), -- Alloc hint + 0x00000038, -- Alloc hint 0x0000, -- Context ID opnum, -- Opnum arguments @@ -4347,4 +4347,173 @@ function get_share_info(host, name) return true, netsharegetinfo_result end +--####################################################################-- +--# 1) RRAS RASRPC INTERFACE +--####################################################################-- +ROUTER_PATH = "\\router" --also can be reached across "\\srvsvc" pipe in WinXP +RASRPC_UUID = string.char(0x36, 0x00, 0x61, 0x20, 0x22, 0xfa, 0xcf, 0x11, 0x98, 0x23, 0x00, 0xa0, 0xc9, 0x11, 0xe5, 0xdf) +RASRPC_VERSION = 1 +--####################################################################-- +--# 2) RRAS RASRPC TYPES +--####################################################################-- + +--####################################################################-- +--typedef enum _ReqTypes{ +-- REQTYPE_PORTENUM = 21,//Request to enumerate all the port information on the RRAS. +-- REQTYPE_GETINFO = 22,//Request to get information about a specific port on the RRAS. +-- REQTYPE_GETDEVCONFIG = 73,//Request to get device information on the RRAS. +-- REQTYPE_SETDEVICECONFIGINFO = 94,//Request to set device configuration information on RRAS. +-- REQTYPE_GETDEVICECONFIGINFO = 95,//Request to get device configuration information on RRAS. +-- REQTYPE_GETCALLEDID = 105,//Request to get CalledId information for a specific device on RRAS. +-- REQTYPE_SETCALLEDID = 106,//Request to set CalledId information for a specific device on RRAS. +-- REQTYPE_GETNDISWANDRIVERCAPS = 111//Request to get the encryption capabilities of the RRAS. +--} ReqTypes; +--- The ReqTypes enumerations indicate the different types of message requests that can be passed in +--the RB_ReqType field of RequestBuffer structure. +-- @see [MS-RRASM] 2.2.1.1.18 ReqTypes +--####################################################################-- +RRAS_RegTypes = {} +RRAS_RegTypes['PORTENUM'] = 21 +RRAS_RegTypes['GETINFO'] = 22 +RRAS_RegTypes['GETDEVCONFIG'] = 73 --this method is vulnerable to ms06-025 +RRAS_RegTypes['SETDEVICECONFIGINFO'] = 94 +RRAS_RegTypes['GETDEVICECONFIGINFO'] = 95 +RRAS_RegTypes['GETCALLEDID'] = 105 +RRAS_RegTypes['SETCALLEDID'] = 106 +RRAS_RegTypes['GETNDISWANDRIVERCAPS'] = 111 + +--####################################################################-- +--typedef struct _RequestBuffer { +-- DWORD RB_PCBIndex;//A unique identifier for the port. +-- ReqTypes RB_Reqtype;//A ReqTypes enumeration value indicating the request type sent to the server. +-- DWORD RB_Dummy;//MUST be set to the size of the ULONG_PTR on the client. +-- DWORD RB_Done;//MBZ +-- LONGLONG Alignment;//MBZ +-- BYTE RB_Buffer[1];//variable size +--} RequestBuffer; +--- The RequestBuffer is a generic information container used by the RasRpcSubmitRequest +--method to set or retrieve information on RRAS server. This method performs +--serialization of RequestBuffer structure. +-- @return Returns a blob of RequestBuffer structure. +-- @note This structure is not an IDL specification and as such is not translated into NDR. +-- @see [MS-RRASM] 2.2.1.2.218 RequestBuffer +--####################################################################-- +function RRAS_marshall_RequestBuffer(RB_PCBIndex, RB_ReqType, RB_Buffer) + local rb_blob, RB_Dummy, RB_Done, Alignment + RB_Dummy = 4 + RB_Done = 0 + Alignment = 0 + rb_blob = bin.pack("3.3.4 Message Processing Events and Sequencing Rules +--####################################################################-- +RRAS_Opnums = {} +RRAS_Opnums["RasRpcDeleteEntry"] = 5 +RRAS_Opnums["RasRpcGetUserPreferences"] = 9 +RRAS_Opnums["RasRpcSetUserPreferences"] = 10 +RRAS_Opnums["RasRpcGetSystemDirectory"] = 11 +RRAS_Opnums["RasRpcSubmitRequest"] = 12 +RRAS_Opnums["RasRpcGetInstalledProtocolsEx"] = 14 +RRAS_Opnums["RasRpcGetVersion"] = 15 + +--####################################################################-- +--DWORD RasRpcSubmitRequest( +-- [in] handle_t hServer,//An RPC binding handle. (not send) +-- [in, out, unique, size_is(dwcbBufSize)] PBYTE pReqBuffer,//A pointer to a buffer of size dwcbBufSize. +-- [in] DWORD dwcbBufSize//Size in byte of pReqBuffer. +--); +---The RasRpcSubmitRequest method retrieves or sets the configuration data on RRAS server. +-- @param smbstate The smb object. +-- @param pReqBuffer The buffer MUST be large enough to hold the RequestBuffer +--structure and RequestBuffer.RB_Buffer data. RequestBuffer.RB_Reqtype +--specifies the request type which will be processed by the server and +--RequestBuffer.RB_Buffer specifies the structure specific to RB_Reqtype +--to be processed. RequestBuffer.RB_PCBIndex MUST be set to the unique port identifier +--whose information is sought for ReqTypes REQTYPE_GETINFO and REQTYPE_GETDEVCONFIG. +--For other valid ReqTypes, RequestBuffer.RB_PCBIndex MUST be set to zero. +-- @param dwcbBufSize Integer representing the size of pRegBuffer in bytes. +-- @return (status, result) +--* status == true -> result is a blob that represent a pRegBuffer . +--* status == false -> result is a error message that caused the fuzz. +-- @see [MS-RRASM] 3.3.4.5 RasRpcSubmitRequest (Opnum 12) +--####################################################################-- +function RRAS_SubmitRequest(smbstate, pReqBuffer, dwcbBufSize) + --sanity check + if(dwcbBufSize == nil) then + dwcbBufSize = string.len(pReqBuffer) + end + --pack the request + local req_blob + --[in, out, unique, size_is(dwcbBufSize) PBYTE pReqBuffer, + req_blob = bin.pack("(align-datalen%align)%align. +--####################################################################-- +function get_pad(data, align, pad_byte) + pad_byte = pad_byte or "\00" + return string.rep(pad_byte, (align-string.len(data)%align)%align) +end + +--####################################################################-- +---Generates a random string of the requested length. +--@param length The length of the string to return. +--@param set The set of letters to choose from. Default: ASCII letters and numbers +--@return The random string. +--####################################################################-- +function random_crap(length, charset) + charset = charset or "0123456789abcdefghijklmnoprstuvzxwyABCDEFGHIJKLMNOPRSTUVZXWY" + local random_str = "" + for i = 1, length, 1 do + local random = math.random(#charset) + random_str = random_str .. string.sub(charset, random, random) + end + return random_str +end + diff --git a/scripts/smb-check-vulns.nse b/scripts/smb-check-vulns.nse index d24c0efa8..311963970 100644 --- a/scripts/smb-check-vulns.nse +++ b/scripts/smb-check-vulns.nse @@ -397,6 +397,61 @@ local function check_smbv2_dos(host) return true, PATCHED end +---Check the existence of ms06_025 vulnerability in Microsoft Remote Routing +--and Access Service. This check is not safe as it crashes the RRAS service and +--its dependencies. +--@param host Host object. +--@return (status, result) If status is false, result is an error code; otherwise, result is either +-- VULNERABLE for vulnerable or PATCHED for not vulnerable. If the check +-- was skipped, NOTRUN is returned. +function check_ms06_025(host) + --check for safety flag + if(nmap.registry.args.safe ~= nil) then + return true, NOTRUN + end + if(nmap.registry.args.unsafe == nil) then + return true, NOTRUN + end + --create the SMB session + local status, smb_result, smbstate, err_msg + status, smb_result = msrpc.start_smb(host, msrpc.ROUTER_PATH) + if(status == false) then + err_msg = smb_result + status, smb_result = msrpc.start_smb(host, msrpc.SRVSVC_PATH) --rras is accessible across SRVSVC pipe + if(status == false) then + return false, err_msg + end + end + smbstate = smb_result + --bind to RRAS service + local bind_result + status, bind_result = msrpc.bind(smbstate, msrpc.RASRPC_UUID, msrpc.RASRPC_VERSION, nil) + if(status == false) then + msrpc.stop_smb(smbstate) + return false, bind_result + end + local req, buff, sr_result + req = msrpc.RRAS_marshall_RequestBuffer( + 0x01, + msrpc.RRAS_RegTypes['GETDEVCONFIG'], + msrpc.random_crap(3000)) + status, sr_result = msrpc.RRAS_SubmitRequest(smbstate, req) + --sanity check + if(status == false) then + stdnse.print_debug( + 3, + "check_ms06_025: RRAS_SubmitRequest failed") + msrpc.stop_smb(smbstate) + if(sr_result == "NT_STATUS_PIPE_BROKEN") then + return true, VULNERABLE + else + return true, PATCHED + end + else + return true, PATHED + end +end + ---Returns the appropriate text to display, if any. -- --@param check The name of the check; for example, 'ms08-067'. @@ -490,6 +545,20 @@ action = function(host) end end + -- Check for ms06-025 + status, result = check_ms06_025(host) + if(status == false) then + table.insert(response, get_response("MS06-025", "ERROR", result, 0, 1)) + else + if(result == VULNERABLE) then + table.insert(response, get_response("MS06-025", "VULNERABLE", nil, 0)) + elseif(result == NOTRUN) then + table.insert(response, get_response("MS06-025", "CHECK DISABLED", "remove 'safe=1' argument to run", 1)) + else + table.insert(response, get_response("MS06-025", "NOT VULNERABLE", nil, 1)) + end + end + return stdnse.format_output(true, response) end