diff --git a/nselib/msrpc.lua b/nselib/msrpc.lua index a7db422d9..eb6e6e866 100644 --- a/nselib/msrpc.lua +++ b/nselib/msrpc.lua @@ -4417,7 +4417,7 @@ end --####################################################################-- --# 3) RRAS RASRPC OPERATIONS --####################################################################-- -local RRAS_DEBUG_LVL = 3 --debug level for rras operations when calling stdnse.print_debug +local RRAS_DEBUG_LVL = 2 --debug level for rras operations when calling stdnse.print_debug --####################################################################-- --- RRAS operation numbers. @@ -4466,6 +4466,9 @@ function RRAS_SubmitRequest(smbstate, pReqBuffer, dwcbBufSize) req_blob = req_blob .. msrpctypes.marshall_int32(dwcbBufSize) --call the function local status, result + stdnse.print_debug( + RRAS_DEBUG_LVL, + "RRAS_SubmitRequest: Calling...") status, result = call_function( smbstate, RRAS_Opnums["RasRpcSubmitRequest"], @@ -4478,12 +4481,157 @@ function RRAS_SubmitRequest(smbstate, pReqBuffer, dwcbBufSize) result) return false, result end + stdnse.print_debug( + RRAS_DEBUG_LVL, + "RRAS_SubmitRequest: Returned successfully") --dissect the reply local rep_blob rep_blob = result return true, rep_blob end +--####################################################################-- +--# 1) DNS SERVER MANAGEMENT SERVICE INTERFACE +--####################################################################-- +DNSSERVER_UUID_STR = "50abc2a4-574d-40b3-9d66-ee4fd5fba076" +DNSSERVER_UUID = string.char(0xa4, 0xc2,0xab, 0x50, 0x4d, 0x57, 0xb3, 0x40, 0x9d, 0x66, 0xee, 0x4f, 0xd5, 0xfb, 0xa0, 0x76) +DNSSERVER_PATH = "\\DNSSERVER" +DNSSERVER_VERSION = 5 + +--####################################################################-- +--# 2) DNS SERVER MANAGEMENT SERVICE TYPES +--####################################################################-- +---The list of names that are used in (name, value) pairs in DNS Server +--Configuration information is given below. +-- @see [MS-DNSP] 3.1.1.1 DNS Server Configuration Information +DNSSERVER_ConfInfo = + { + DNSSERVER_IntProp = {}, + DNSSERVER_AddrArrProp = {}, + DNSSERVER_StrProp = {}, + DNSSERVER_StrLstProp = {} + } + +--####################################################################-- +--# 3) DNS SERVER MANAGEMENT SERVICE OPERATIONS +--####################################################################-- +local DNSSERVER_DEBUG_LVL = 2 --debug level for dnsserver operations when calling stdnse.print_debug + +--####################################################################-- +--- DNSSERVER operation numbers. +-- @see [MS-DNSP] 3.1.4 Message Processing Events and Sequencing Rules +--####################################################################-- +DNSSERVER_Opnums = {} +DNSSERVER_Opnums['R_DnssrvOperation'] = 0 +DNSSERVER_Opnums['R_DnssrvQuery'] = 1 +DNSSERVER_Opnums['R_DnssrvComplexOperation'] = 2 +DNSSERVER_Opnums['R_DnssrvEnumRecords'] = 3 +DNSSERVER_Opnums['R_DnssrvUpdateRecord'] = 4 +DNSSERVER_Opnums['R_DnssrvOperation2'] = 5 +DNSSERVER_Opnums['R_DnssrvQuery2'] = 6 +DNSSERVER_Opnums['R_DnssrvComplexOperation2'] = 7 +DNSSERVER_Opnums['R_DnssrvEnumRecords2'] = 8 +DNSSERVER_Opnums['R_DnssrvUpdateRecord2'] = 9 + +--####################################################################-- +--[[ +LONG R_DnssrvQuery( + [in, unique, string] LPCWSTR pwszServerName, + [in, unique, string] LPCSTR pszZone, + [in, unique, string] LPCSTR pszOperation, + [out] PDWORD pdwTypeId, + [out, switch_is(*pdwTypeId)] DNSSRV_RPC_UNION* ppData); +--]] +---Issues type specific information queries to server. This method is +--obsoleted by R_DnssrvQuery2. +-- @param smbstate The smb object. +-- @param server_name String that designates a fully qualified domain +--name of the target server. The server MUST ignore this value. +-- @param zone String that designates the name of the zone to be queried. +--For operations specific to a particular zone, this field MUST contain +--the name of the zone. For all other operations, this field MUST be nil. +-- @param operation String that designates the name of the operation to +--be performed on the server. These are two sets of allowed values for +--pszOperation: +--* zone == nil -> see DNSSERVER_ConfInfo table. +--* zone == "some_zone" -> see DNSSERVER_ZoneInfo table. +-- @return (status, result) +--* status == true -> +--that indicates the type of result['data']. +--** result['data'] - A DNSSRV_RPC_UNION blob that contains a +--** result['type_id'] - Integer that on success contains a value of type DNS_RPC_TYPEID +--data-structure as indicated by result['type_id']. +--* status == false -> +--** result - Is a error message that caused the fuzz. +-- @see [MS-DNSP] 3.1.4.2 R_DnssrvQuery (Opnum 1) +--####################################################################-- +function DNSSERVER_Query(smbstate, server_name, zone, operation) + local status + --call + local req_blob, srv_name_utf16, zone_ascii, operation_ascii + --[in, unique, string] LPCWSTR pwszServerName, + local unique_ptr + unique_ptr = 0x00020000 + srv_name_utf16 = msrpctypes.string_to_unicode(server_name, true) + req_blob = bin.pack("VULNERABLE for vulnerable or PATCHED for not vulnerable. If the check --- was skipped, NOTRUN is returned. If the service is not active then NOTUP +--@return (status, result) +--* status == false -> result == NOTUP which designates +--that the targeted Ras RPC service is not active. +--* status == true -> +-- ** result == VULNERABLE for vulnerable. +-- ** result == PATCHED for not vulnerable. +-- ** result == NOTRUN if check skipped. function check_ms06_025(host) --check for safety flag if(nmap.registry.args.safe ~= nil) then @@ -437,6 +442,7 @@ function check_ms06_025(host) msrpc.RRAS_RegTypes['GETDEVCONFIG'], msrpc.random_crap(3000)) status, sr_result = msrpc.RRAS_SubmitRequest(smbstate, req) + msrpc.stop_smb(smbstate) --sanity check if(status == false) then stdnse.print_debug( @@ -448,11 +454,61 @@ function check_ms06_025(host) return true, PATCHED end else - msrpc.stop_smb(smbstate) return true, PATHED end end +---Check the existence of ms07_029 vulnerability in Microsoft Dns Server service. +--This check is not safe as it crashes the Dns Server RPC service its dependencies. +--@param host Host object. +--@return (status, result) +--* status == false -> result == NOTUP which designates +--that the targeted Dns Server RPC service is not active. +--* status == true -> +-- ** result == VULNERABLE for vulnerable. +-- ** result == PATCHED for not vulnerable. +-- ** result == NOTRUN if check skipped. +function check_ms07_029(host) + --create the SMB session + local status, smbstate + status, smbstate = msrpc.start_smb(host, msrpc.DNSSERVER_PATH) + if(status == false) then + return false, NOTUP + end + --bind to DNSSERVER service + local bind_result + status, bind_result = msrpc.bind(smbstate, msrpc.DNSSERVER_UUID, msrpc.DNSSERVER_VERSION) + if(status == false) then + msrpc.stop_smb(smbstate) + stdnse.print_debug( + msrpc.DNSSERVER_DEBUG_LVL, + "DNSSERVER_Query: Bind failed: %s", + bind_result) + return false, NOTUP + end + --call + local req_blob, q_result + status, q_result = msrpc.DNSSERVER_Query( + smbstate, + "VULNSRV", + string.rep("\\\13", 1000), + 1)--any op num will do + --sanity check + msrpc.stop_smb(smbstate) + if(status == false) then + stdnse.print_debug( + 3, + "check_ms07_029: DNSSERVER_Query failed") + if(q_result == "NT_STATUS_PIPE_BROKEN") then + return true, VULNERABLE + else + return true, PATCHED + end + else + return true, PATCHED + end +end + ---Returns the appropriate text to display, if any. -- --@param check The name of the check; for example, 'ms08-067'. @@ -548,19 +604,41 @@ action = function(host) -- 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)) + if(status == false) then + if(result == NOTUP) then + table.insert(response, get_response("MS06-025", "NO SERVICE", "the Ras RPC service is inactive", 1)) + else + table.insert(response, get_response("MS06-025", "ERROR", result, 0, 1)) + end 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)) elseif(result == NOTUP) then - table.insert(response, get_response("MS06-025", "NO SERVICE", "the vulnerable service is inactive", 1)) + table.insert(response, get_response("MS06-025", "NO SERVICE", "the Ras RPC service is inactive", 1)) else table.insert(response, get_response("MS06-025", "NOT VULNERABLE", nil, 1)) end end + + -- Check for ms07-029 + status, result = check_ms07_029(host) + if(status == false) then + if(result == NOTUP) then + table.insert(response, get_response("MS07-029", "NO SERVICE", "the Dns Server RPC service is inactive", 1)) + else + table.insert(response, get_response("MS07-029", "ERROR", result, 0, 1)) + end + else + if(result == VULNERABLE) then + table.insert(response, get_response("MS07-029", "VULNERABLE", nil, 0)) + elseif(result == NOTRUN) then + table.insert(response, get_response("MS07-029", "CHECK DISABLED", "remove 'safe=1' argument to run", 1)) + else + table.insert(response, get_response("MS07-029", "NOT VULNERABLE", nil, 1)) + end + end return stdnse.format_output(true, response) end