Skip to content

Commit 25a1318

Browse files
authored
Land rapid7#19170, Refactor smb lookupsid module
2 parents 056acd4 + 638ad36 commit 25a1318

File tree

10 files changed

+336
-307
lines changed

10 files changed

+336
-307
lines changed

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ GEM
475475
ruby-progressbar (1.13.0)
476476
ruby-rc4 (0.1.5)
477477
ruby2_keywords (0.0.5)
478-
ruby_smb (3.3.7)
478+
ruby_smb (3.3.8)
479479
bindata (= 2.4.15)
480480
openssl-ccm
481481
openssl-cmac

LICENSE_GEMS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ ruby-prof, 1.4.2, "Simplified BSD"
172172
ruby-progressbar, 1.13.0, MIT
173173
ruby-rc4, 0.1.5, MIT
174174
ruby2_keywords, 0.0.5, "ruby, Simplified BSD"
175-
ruby_smb, 3.3.7, "New BSD"
175+
ruby_smb, 3.3.8, "New BSD"
176176
rubyntlm, 0.6.3, MIT
177177
rubyzip, 2.3.2, "Simplified BSD"
178178
sawyer, 0.9.2, MIT

lib/msf/core/exploit/remote/ms_icpr.rb

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@ module Msf
1111

1212
module Exploit::Remote::MsIcpr
1313

14-
include Msf::Exploit::Remote::SMB::Client::Authenticated
14+
include Msf::Exploit::Remote::SMB::Client::Ipc
1515
include Msf::Exploit::Remote::DCERPC
16-
include Msf::Auxiliary::Report
1716

1817
# [2.2.2.7.7.4 szOID_NTDS_CA_SECURITY_EXT](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/e563cff8-1af6-4e6f-a655-7571ca482e71)
1918
OID_NTDS_CA_SECURITY_EXT = '1.3.6.1.4.1.311.25.2'.freeze
@@ -109,27 +108,6 @@ def request_certificate(opts = {})
109108

110109
module_function
111110

112-
def connect_ipc
113-
begin
114-
connect
115-
rescue Rex::ConnectionError => e
116-
raise MsIcprConnectionError, e.message
117-
end
118-
119-
begin
120-
smb_login
121-
rescue Rex::Proto::SMB::Exceptions::Error, RubySMB::Error::RubySMBError => e
122-
raise MsIcprAuthenticationError, "Unable to authenticate ([#{e.class}] #{e})."
123-
end
124-
report_service(icpr_service_data)
125-
126-
begin
127-
simple.client.tree_connect("\\\\#{sock.peerhost}\\IPC$")
128-
rescue RubySMB::Error::RubySMBError => e
129-
raise MsIcprConnectionError, "Unable to connect to the remote IPC$ share ([#{e.class}] #{e})."
130-
end
131-
end
132-
133111
def connect_icpr(tree)
134112
vprint_status('Connecting to ICertPassage (ICPR) Remote Protocol')
135113
icpr = tree.open_file(filename: 'cert', write: true, read: true)
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
###
2+
#
3+
# This mixin provides methods to open, and close policy handles, and to query policy info on the remote SMB server.
4+
#
5+
# -*- coding: binary -*-
6+
7+
module Msf
8+
9+
module Exploit::Remote::MsLsad
10+
11+
include Msf::Exploit::Remote::SMB::Client::Ipc
12+
13+
class MsLsadError < StandardError; end
14+
class MsLsadConnectionError < MsLsadError; end
15+
class MsLsadAuthenticationError < MsLsadError; end
16+
class MsLsadUnexpectedReplyError < MsLsadError; end
17+
18+
LSA_UUID = '12345778-1234-abcd-ef00-0123456789ab'.freeze
19+
LSA_VERS = '0.0'.freeze
20+
LSARPC_ENDPOINT = RubySMB::Dcerpc::Lsarpc.freeze
21+
22+
# The currently connected LSARPC pipe
23+
attr_reader :lsarpc_pipe
24+
25+
def map_security_principal_to_string(security_principal)
26+
case security_principal
27+
when 1
28+
'User'
29+
when 2
30+
'Group'
31+
when 3
32+
'Domain'
33+
when 4
34+
'Alias'
35+
when 5
36+
'Well-Known Group'
37+
when 6
38+
'Deleted Account'
39+
when 7
40+
'Invalid'
41+
when 8
42+
'Unknown'
43+
when '9'
44+
'Computer'
45+
when 10
46+
'Label'
47+
else
48+
'Unknown - Not a valid Security Principal'
49+
end
50+
end
51+
52+
def open_policy2(impersonation_level, security_context_tracking_mode, access_mask)
53+
self.lsarpc_pipe.lsar_open_policy2(
54+
system_name: simple.peerhost,
55+
object_attributes: {
56+
security_quality_of_service: {
57+
impersonation_level: impersonation_level,
58+
security_context_tracking_mode: security_context_tracking_mode
59+
}
60+
},
61+
access_mask: access_mask
62+
)
63+
end
64+
65+
def query_information_policy(policy_handle, information_class)
66+
self.lsarpc_pipe.lsar_query_information_policy(
67+
policy_handle: policy_handle,
68+
information_class: information_class
69+
)
70+
end
71+
72+
def close_policy(policy_handle)
73+
self.lsarpc_pipe.lsar_close_handle(
74+
policy_handle: policy_handle
75+
) if (self.lsarpc_pipe && policy_handle)
76+
end
77+
78+
def disconnect_lsarpc
79+
begin
80+
self.lsarpc_pipe.close if self.lsarpc_pipe&.is_connected?
81+
rescue RubySMB::Error::UnexpectedStatusCode, RubySMB::Error::CommunicationError => e
82+
wlog e
83+
end
84+
end
85+
86+
module_function
87+
88+
def connect_lsarpc(tree)
89+
begin
90+
vprint_status('Connecting to Local Security Authority (LSA) Remote Protocol')
91+
self.lsarpc_pipe = tree.open_file(filename: 'lsarpc', write: true, read: true)
92+
93+
raise MsLsadConnectionError.new('Could not open lsarpc pipe on remote SMB server.') unless lsarpc_pipe
94+
95+
vprint_status('Binding to \\lsarpc...')
96+
self.lsarpc_pipe.bind(endpoint: LSARPC_ENDPOINT)
97+
vprint_good('Bound to \\lsarpc')
98+
99+
self.lsarpc_pipe
100+
rescue RubySMB::Dcerpc::Error::FaultError => e
101+
elog(e.message, error: e)
102+
raise MsLsadUnexpectedReplyError, "Connection failed (DCERPC fault: #{e.status_name})"
103+
end
104+
end
105+
106+
protected
107+
108+
attr_writer :lsarpc_pipe
109+
110+
end
111+
112+
end
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
###
2+
#
3+
# This mixin provides methods to look-up security identifiers on the remote SMB server.
4+
#
5+
# -*- coding: binary -*-
6+
7+
module Msf
8+
9+
module Exploit::Remote::MsLsat
10+
11+
def lookup_sids(policy_handle, sids, lookup_level)
12+
sids = [sids] unless sids.is_a?(Array)
13+
14+
self.lsarpc_pipe.lsar_lookup_sids(
15+
policy_handle: policy_handle,
16+
sids: sids,
17+
lookup_level: lookup_level
18+
)
19+
end
20+
21+
end
22+
end

lib/msf/core/exploit/remote/ms_samr.rb

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module Msf
88

99
module Exploit::Remote::MsSamr
1010

11-
include Msf::Exploit::Remote::SMB::Client::Authenticated
11+
include Msf::Exploit::Remote::SMB::Client::Ipc
1212

1313
class MsSamrError < StandardError; end
1414
class MsSamrConnectionError < MsSamrError; end
@@ -22,34 +22,6 @@ class MsSamrBadConfigError < MsSamrError; end
2222

2323
module_function
2424

25-
def connect_ipc
26-
begin
27-
connect
28-
rescue Rex::ConnectionError => e
29-
raise MsSamrConnectionError, e.message
30-
end
31-
32-
begin
33-
smb_login
34-
rescue Rex::Proto::SMB::Exceptions::Error, RubySMB::Error::RubySMBError => e
35-
raise MsSamrAuthenticationError, "Unable to authenticate ([#{e.class}] #{e})."
36-
end
37-
report_service(
38-
host: rhost,
39-
port: rport,
40-
host_name: simple.client.default_name,
41-
proto: 'tcp',
42-
name: 'smb',
43-
info: "Module: #{fullname}, last negotiated version: SMBv#{simple.client.negotiated_smb_version} (dialect = #{simple.client.dialect})"
44-
)
45-
46-
begin
47-
simple.client.tree_connect("\\\\#{sock.peerhost}\\IPC$")
48-
rescue RubySMB::Error::RubySMBError => e
49-
raise MsSamrConnectionError, "Unable to connect to the remote IPC$ share ([#{e.class}] #{e})."
50-
end
51-
end
52-
5325
def connect_samr(tree)
5426
begin
5527
vprint_status('Connecting to Security Account Manager (SAM) Remote Protocol')

lib/msf/core/exploit/remote/smb/client.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,10 @@ def smb_login(simple_client = self.simple)
189189
datastore['NTLM::SendNTLM'],
190190
datastore['SMB::Native_OS'],
191191
datastore['SMB::Native_LM'],
192-
{:use_spn => datastore['NTLM::SendSPN'], :name => self.rhost}
192+
{ :use_spn => datastore['NTLM::SendSPN'], :name => simple_client.peerhost }
193193
)
194194
# XXX: Any reason to connect to the IPC$ share in this method?
195-
simple_client.connect("\\\\#{datastore['RHOST']}\\IPC$")
195+
simple_client.client.tree_connect("\\\\#{simple_client.peerhost}\\IPC$")
196196
end
197197

198198
# This method returns the native operating system of the peer
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
###
2+
#
3+
# This mixin provides a method to connect to an IPC share on the remote SMB server.
4+
#
5+
# -*- coding: binary -*-
6+
7+
module Msf
8+
9+
module Exploit::Remote::SMB::Client::Ipc
10+
11+
include Msf::Exploit::Remote::SMB::Client::Authenticated
12+
include Msf::Auxiliary::Report
13+
14+
class SmbIpcError < StandardError; end
15+
class SmbIpcConnectionError < SmbIpcError; end
16+
class SmbIpcAuthenticationError < SmbIpcError; end
17+
18+
module_function
19+
20+
def connect_ipc
21+
begin
22+
if session
23+
self.simple = session.simple_client
24+
ipc_tree = simple.client.tree_connect("\\\\#{simple.peerhost}\\IPC$")
25+
else
26+
connect
27+
# smb_login does a tree_connect to the IPC share already.
28+
ipc_tree = smb_login
29+
end
30+
rescue Rex::ConnectionError => e
31+
raise SmbIpcConnectionError, e.message
32+
rescue Rex::Proto::SMB::Exceptions::Error, RubySMB::Error::RubySMBError => e
33+
raise SmbIpcAuthenticationError, "Unable to authenticate ([#{e.class}] #{e})."
34+
end
35+
36+
report_service(
37+
host: simple.peerhost,
38+
port: simple.peerport,
39+
host_name: simple.client.default_name,
40+
proto: 'tcp',
41+
name: 'smb',
42+
info: "Module: #{fullname}, last negotiated version: SMBv#{simple.client.negotiated_smb_version} (dialect = #{simple.client.dialect})"
43+
)
44+
45+
ipc_tree
46+
end
47+
48+
def disconnect_ipc(ipc_tree)
49+
ipc_tree.disconnect! if ipc_tree
50+
end
51+
52+
end
53+
54+
end

0 commit comments

Comments
 (0)