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