Lucene search

K
nmapRon BowesNMAP:SMB-ENUM-GROUPS.NSE
HistoryNov 20, 2009 - 4:05 p.m.

smb-enum-groups NSE Script

2009-11-2016:05:06
Ron Bowes
nmap.org
127

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.973 High

EPSS

Percentile

99.8%

Obtains a list of groups from the remote Windows system, as well as a list of the group’s users. This works similarly to enum.exe with the /G switch.

The following MSRPC functions in SAMR are used to find a list of groups and the RIDs of their users. Keep in mind that MSRPC refers to groups as “Aliases”.

  • Bind: bind to the SAMR service.
  • Connect4: get a connect_handle.
  • EnumDomains: get a list of the domains.
  • LookupDomain: get the RID of the domains.
  • OpenDomain: get a handle for each domain.
  • EnumDomainAliases: get the list of groups in the domain.
  • OpenAlias: get a handle to each group.
  • GetMembersInAlias: get the RIDs of the members in the groups.
  • Close: close the alias handle.
  • Close: close the domain handle.
  • Close: close the connect handle.

Once the RIDs have been termined, the

  • Bind: bind to the LSA service.
  • OpenPolicy2: get a policy handle.
  • LookupSids2: convert SIDs to usernames.

I (Ron Bowes) originally looked into the possibility of using the SAMR function LookupRids2 to convert RIDs to usernames, but the function seemed to return a fault no matter what I tried. Since enum.exe also switches to LSA to convert RIDs to usernames, I figured they had the same issue and I do the same thing.

Script Arguments

randomseed, smbbasic, smbport, smbsign

See the documentation for the smb library.

smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername

See the documentation for the smbauth library.

Example Usage

nmap --script smb-enum-users.nse -p445 <host>
sudo nmap -sU -sS --script smb-enum-users.nse -p U:137,T:139 <host>

Script Output

Host script results:
| smb-enum-groups:
|   Builtin\Administrators (RID: 544): Administrator, Daniel
|   Builtin\Users (RID: 545): <empty>
|   Builtin\Guests (RID: 546): Guest
|   Builtin\Performance Monitor Users (RID: 558): <empty>
|   Builtin\Performance Log Users (RID: 559): Daniel
|   Builtin\Distributed COM Users (RID: 562): <empty>
|   Builtin\IIS_IUSRS (RID: 568): <empty>
|   Builtin\Event Log Readers (RID: 573): <empty>
|   azure\HomeUsers (RID: 1000): Administrator, Daniel, HomeGroupUser$
|_  azure\HelpLibraryUpdaters (RID: 1003): <empty>

Requires


local msrpc = require "msrpc"
local smb = require "smb"
local stdnse = require "stdnse"
local string = require "string"
local table = require "table"
local tableaux = require "tableaux"

description = [[
Obtains a list of groups from the remote Windows system, as well as a list of the group's users.
This works similarly to <code>enum.exe</code> with the <code>/G</code> switch.

The following MSRPC functions in SAMR are used to find a list of groups and the RIDs of their users. Keep
in mind that MSRPC refers to groups as "Aliases".

* <code>Bind</code>: bind to the SAMR service.
* <code>Connect4</code>: get a connect_handle.
* <code>EnumDomains</code>: get a list of the domains.
* <code>LookupDomain</code>: get the RID of the domains.
* <code>OpenDomain</code>: get a handle for each domain.
* <code>EnumDomainAliases</code>: get the list of groups in the domain.
* <code>OpenAlias</code>: get a handle to each group.
* <code>GetMembersInAlias</code>: get the RIDs of the members in the groups.
* <code>Close</code>: close the alias handle.
* <code>Close</code>: close the domain handle.
* <code>Close</code>: close the connect handle.

Once the RIDs have been termined, the
* <code>Bind</code>: bind to the LSA service.
* <code>OpenPolicy2</code>: get a policy handle.
* <code>LookupSids2</code>: convert SIDs to usernames.

I (Ron Bowes) originally looked into the possibility of using the SAMR function <code>LookupRids2</code>
to convert RIDs to usernames, but the function seemed to return a fault no matter what I tried. Since
enum.exe also switches to LSA to convert RIDs to usernames, I figured they had the same issue and I do
the same thing.
]]

---
-- @usage
-- nmap --script smb-enum-users.nse -p445 <host>
-- sudo nmap -sU -sS --script smb-enum-users.nse -p U:137,T:139 <host>
--
-- @output
-- Host script results:
-- | smb-enum-groups:
-- |   Builtin\Administrators (RID: 544): Administrator, Daniel
-- |   Builtin\Users (RID: 545): <empty>
-- |   Builtin\Guests (RID: 546): Guest
-- |   Builtin\Performance Monitor Users (RID: 558): <empty>
-- |   Builtin\Performance Log Users (RID: 559): Daniel
-- |   Builtin\Distributed COM Users (RID: 562): <empty>
-- |   Builtin\IIS_IUSRS (RID: 568): <empty>
-- |   Builtin\Event Log Readers (RID: 573): <empty>
-- |   azure\HomeUsers (RID: 1000): Administrator, Daniel, HomeGroupUser$
-- |_  azure\HelpLibraryUpdaters (RID: 1003): <empty>
--
-- @xmloutput
-- <table key="Builtin">
--   <table key="RID 544">
--     <table key="member_sids">
--       <elem>S-1-5-21-12345678-1234567890-0987654321-500</elem>
--       <elem>S-1-5-21-12345678-1234567890-0987654321-1001</elem>
--     </table>
--     <elem key="name">Administrators</elem>
--     <table key="members">
--       <elem>Administrator</elem>
--       <elem>Daniel</elem>
--     </table>
--   </table>
--   <table key="RID 545">
--     <table key="member_sids">
--       <elem>S-1-5-4</elem>
--       <elem>S-1-5-11</elem>
--     </table>
--     <elem key="name">Users</elem>
--     <table key="members"></table>
--   </table>
--   <table key="RID 546">
--     <table key="member_sids">
--       <elem>S-1-5-21-12345678-1234567890-0987654321-501</elem>
--     </table>
--     <elem key="name">Guests</elem>
--     <table key="members">
--       <elem>Guest</elem>
--     </table>
--   </table>
--   <table key="RID 559">
--     <table key="member_sids">
--       <elem>S-1-5-21-12345678-1234567890-0987654321-1001</elem>
--     </table>
--     <elem key="name">Performance Log Users</elem>
--     <table key="members">
--       <elem>Daniel</elem>
--     </table>
--   </table>
--   <table key="RID 562">
--     <table key="member_sids"></table>
--     <elem key="name">Distributed COM Users</elem>
--     <table key="members"></table>
--   </table>
--   <table key="RID 568">
--     <table key="member_sids">
--       <elem>S-1-5-17</elem>
--     </table>
--     <elem key="name">IIS_IUSRS</elem>
--     <table key="members"></table>
--   </table>
-- </table>
-- <table key="azure">
--   <table key="RID 1000">
--     <table key="member_sids">
--       <elem>S-1-5-21-12345678-1234567890-0987654321-500</elem>
--       <elem>S-1-5-21-12345678-1234567890-0987654321-1001</elem>
--       <elem>S-1-5-21-12345678-1234567890-0987654321-1002</elem>
--     </table>
--     <elem key="name">HomeUsers</elem>
--     <table key="members">
--       <elem>Administrator</elem>
--       <elem>Daniel</elem>
--       <elem>HomeGroupUser$</elem>
--     </table>
--   </table>
--   <table key="RID 1003">
--     <table key="member_sids"></table>
--     <elem key="name">HelpLibraryUpdaters</elem>
--     <table key="members"></table>
--   </table>
-- </table>

author = "Ron Bowes"
copyright = "Ron Bowes"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"discovery","intrusive"}
dependencies = {"smb-brute"}


hostrule = function(host)
  return smb.get_port(host) ~= nil
end

local empty = {"<empty>"}

action = function(host)
  local status, groups = msrpc.samr_enum_groups(host)
  if(not(status)) then
    return stdnse.format_output(false, "Couldn't enumerate groups: " .. groups)
  end

  local response = stdnse.output_table()
  local response_str = {}

  local domains = tableaux.keys(groups)
  table.sort(domains)
  for _, domain_name in ipairs(domains) do
    local dom_groups = stdnse.output_table()
    response[domain_name] = dom_groups
    local domain_data = groups[domain_name]

    local rids = tableaux.keys(domain_data)
    table.sort(rids)
    for _, rid in ipairs(rids) do
      local group_data = domain_data[rid]
      -- TODO: Map SIDs to names, show non-named SIDs
      table.insert(response_str,
        string.format("\n  %s\\%s (RID: %s): %s", domain_name, group_data.name, rid,
          table.concat(#group_data.members > 0 and group_data.members or empty, ", "))
        )
      dom_groups[string.format("RID %d", rid)] = group_data
    end
  end

  return response, table.concat(response_str)
end

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.973 High

EPSS

Percentile

99.8%

Related for NMAP:SMB-ENUM-GROUPS.NSE