Skip to content

Commit 7e0b3af

Browse files
authored
Land #19879, Add MsDtypSecurityDescriptor to_sddl_text
Land #19879, Add MsDtypSecurityDescriptor to_sddl_text
2 parents 8c24e98 + fcee4db commit 7e0b3af

File tree

9 files changed

+1021
-551
lines changed

9 files changed

+1021
-551
lines changed

lib/msf/core/exploit/remote/ldap/queries.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,14 @@ def normalize_entry(entry, attribute_properties)
284284
end
285285
normalized_attribute[0] = time_string
286286
when 66 # String (Nt Security Descriptor)
287+
if attribute_property[:attributesyntax] == '2.5.5.15'
288+
begin
289+
sd = Rex::Proto::MsDtyp::MsDtypSecurityDescriptor.read(entry[attribute_name][0])
290+
normalized_attribute[0] = sd.to_sddl_text(domain_sid: nil)
291+
rescue StandardError => e
292+
elog('failed to parse a binary security descriptor to SDDL', error: e)
293+
end
294+
end
287295
when 127 # Object
288296
else
289297
print_error("Unknown oMSyntax entry: #{attribute_property[:omsyntax]}")

lib/rex/proto/ms_dtyp.rb

Lines changed: 446 additions & 333 deletions
Large diffs are not rendered by default.

lib/rex/proto/secauthz/well_known_sids.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ module WellKnownSids
4242
SECURITY_BUILTIN_DOMAIN_SID = "#{SECURITY_NT_AUTHORITY}-32"
4343
SECURITY_WRITE_RESTRICTED_CODE_SID = "#{SECURITY_NT_AUTHORITY}-33"
4444

45-
SECURITY_USERMODEDRIVERHOST_ID_BASE_SID = "#{SECURITY_NT_AUTHORITY}-0"
45+
SECURITY_USERMODEDRIVERHOST_ID_BASE_SID = "S-1-5-84-0-0-0-0-0"
4646
SECURITY_ALL_APP_PACKAGES = 'S-1-15-2-1'
4747
SECURITY_MANDATORY_SYSTEM_SID = 'S-1-16-16384'
4848
SECURITY_AUTHENTICATION_SERVICE_ASSERTED_SID = "S-1-18-2"

modules/auxiliary/admin/ldap/ad_cs_cert_template.rb

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,21 @@ def action_read
339339
obj, stored = get_certificate_template
340340

341341
print_status('Certificate Template:')
342-
print_status(" distinguishedName: #{obj['distinguishedname'].first}")
343-
print_status(" displayName: #{obj['displayname'].first}") if obj['displayname'].present?
342+
print_status(" distinguishedName: #{obj['distinguishedname'].first}")
343+
print_status(" displayName: #{obj['displayname'].first}") if obj['displayname'].present?
344344
if obj['objectguid'].first.present?
345345
object_guid = Rex::Proto::MsDtyp::MsDtypGuid.read(obj['objectguid'].first)
346-
print_status(" objectGUID: #{object_guid}")
346+
print_status(" objectGUID: #{object_guid}")
347+
end
348+
if obj['ntsecuritydescriptor'].first.present?
349+
begin
350+
sd = Rex::Proto::MsDtyp::MsDtypSecurityDescriptor.read(obj['ntsecuritydescriptor'].first)
351+
sddl_text = sd.to_sddl_text(domain_sid: get_domain_sid)
352+
rescue StandardError => e
353+
elog('failed to parse a binary security descriptor to SDDL', error: e)
354+
else
355+
print_status(" nTSecurityDescriptor: #{sddl_text}")
356+
end
347357
end
348358

349359
pki_flag = obj['flags']&.first

modules/auxiliary/admin/ldap/rbcd.rb

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,16 @@ def run
167167
def action_read(obj)
168168
security_descriptor = obj[ATTRIBUTE]
169169
if security_descriptor.nil?
170-
print_status('The msDS-AllowedToActOnBehalfOfOtherIdentity field is empty.')
170+
print_status("The #{ATTRIBUTE} field is empty.")
171171
return
172172
end
173173

174+
if (sddl = sd_to_sddl(security_descriptor))
175+
vprint_status("#{ATTRIBUTE}: #{sddl}")
176+
end
177+
174178
if security_descriptor.dacl.nil?
175-
print_status('The msDS-AllowedToActOnBehalfOfOtherIdentity DACL field is empty.')
179+
print_status("The #{ATTRIBUTE} DACL field is empty.")
176180
return
177181
end
178182

@@ -211,22 +215,22 @@ def action_remove(obj)
211215
security_descriptor.dacl.acl_size.clear
212216

213217
unless @ldap.replace_attribute(obj['dn'], ATTRIBUTE, security_descriptor.to_binary_s)
214-
fail_with_ldap_error('Failed to update the msDS-AllowedToActOnBehalfOfOtherIdentity attribute.')
218+
fail_with_ldap_error("Failed to update the #{ATTRIBUTE} attribute.")
215219
end
216-
print_good('Successfully updated the msDS-AllowedToActOnBehalfOfOtherIdentity attribute.')
220+
print_good("Successfully updated the #{ATTRIBUTE} attribute.")
217221
end
218222

219223
def action_flush(obj)
220224
unless obj[ATTRIBUTE]
221-
print_status('The msDS-AllowedToActOnBehalfOfOtherIdentity field is empty. No changes are necessary.')
225+
print_status("The #{ATTRIBUTE} field is empty. No changes are necessary.")
222226
return
223227
end
224228

225229
unless @ldap.delete_attribute(obj['dn'], ATTRIBUTE)
226-
fail_with_ldap_error('Failed to deleted the msDS-AllowedToActOnBehalfOfOtherIdentity attribute.')
230+
fail_with_ldap_error("Failed to deleted the #{ATTRIBUTE} attribute.")
227231
end
228232

229-
print_good('Successfully deleted the msDS-AllowedToActOnBehalfOfOtherIdentity attribute.')
233+
print_good("Successfully deleted the #{ATTRIBUTE} attribute.")
230234
end
231235

232236
def action_write(obj)
@@ -239,26 +243,37 @@ def action_write(obj)
239243
end
240244

241245
def _action_write_create(obj, delegate_from)
246+
vprint_status("Creating new #{ATTRIBUTE}...")
242247
security_descriptor = Rex::Proto::MsDtyp::MsDtypSecurityDescriptor.new
243248
security_descriptor.owner_sid = Rex::Proto::MsDtyp::MsDtypSid.new('S-1-5-32-544')
244249
security_descriptor.dacl = Rex::Proto::MsDtyp::MsDtypAcl.new
245250
security_descriptor.dacl.acl_revision = Rex::Proto::MsDtyp::MsDtypAcl::ACL_REVISION_DS
246251
security_descriptor.dacl.aces << build_ace(delegate_from['ObjectSid'])
247252

253+
if (sddl = sd_to_sddl(security_descriptor))
254+
vprint_status("New #{ATTRIBUTE}: #{sddl}")
255+
end
256+
248257
unless @ldap.add_attribute(obj['dn'], ATTRIBUTE, security_descriptor.to_binary_s)
249-
fail_with_ldap_error('Failed to create the msDS-AllowedToActOnBehalfOfOtherIdentity attribute.')
258+
fail_with_ldap_error("Failed to create the #{ATTRIBUTE} attribute.")
250259
end
251260

252-
print_good('Successfully created the msDS-AllowedToActOnBehalfOfOtherIdentity attribute.')
261+
print_good("Successfully created the #{ATTRIBUTE} attribute.")
253262
print_status('Added account:')
254263
print_status(" #{delegate_from['ObjectSid']} (#{delegate_from['sAMAccountName']})")
255264
end
256265

257266
def _action_write_update(obj, delegate_from)
267+
vprint_status("Updating existing #{ATTRIBUTE}...")
258268
security_descriptor = obj[ATTRIBUTE]
269+
270+
if (sddl = sd_to_sddl(security_descriptor))
271+
vprint_status("Old #{ATTRIBUTE}: #{sddl}")
272+
end
273+
259274
if security_descriptor.dacl
260275
if security_descriptor.dacl.aces.any? { |ace| ace.body[:sid].to_s == delegate_from['ObjectSid'].to_s }
261-
print_status("Delegation from #{delegate_from['sAMAccountName']} to #{obj['sAMAccountName']} is already enabled.")
276+
print_status("Delegation from #{delegate_from['sAMAccountName']} to #{obj['sAMAccountName']} is already configured.")
262277
end
263278
# clear these fields so they'll be calculated automatically after the update
264279
security_descriptor.dacl.acl_count.clear
@@ -271,10 +286,20 @@ def _action_write_update(obj, delegate_from)
271286

272287
security_descriptor.dacl.aces << build_ace(delegate_from['ObjectSid'])
273288

289+
if (sddl = sd_to_sddl(security_descriptor))
290+
vprint_status("New #{ATTRIBUTE}: #{sddl}")
291+
end
292+
274293
unless @ldap.replace_attribute(obj['dn'], ATTRIBUTE, security_descriptor.to_binary_s)
275-
fail_with_ldap_error('Failed to update the msDS-AllowedToActOnBehalfOfOtherIdentity attribute.')
294+
fail_with_ldap_error("Failed to update the #{ATTRIBUTE} attribute.")
276295
end
277296

278-
print_good('Successfully updated the msDS-AllowedToActOnBehalfOfOtherIdentity attribute.')
297+
print_good("Successfully updated the #{ATTRIBUTE} attribute.")
298+
end
299+
300+
def sd_to_sddl(sd)
301+
sd.to_sddl_text
302+
rescue StandardError => e
303+
elog('failed to parse a binary security descriptor to SDDL', error: e)
279304
end
280305
end
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
RSpec.describe Rex::Proto::MsDtyp::MsDtypAccessMask do
2+
subject(:instance) { described_class.from_sddl_text(sddl_text) }
3+
4+
describe '.from_sddl_text' do
5+
it 'raises an exception on invalid flags' do
6+
expect { described_class.from_sddl_text('XX') }.to raise_error(Rex::Proto::MsDtyp::SDDLParseError, 'unknown ACE access right: XX')
7+
end
8+
9+
context 'when the text is FA' do
10+
let(:sddl_text) { 'FA' }
11+
subject(:instance) { described_class.from_sddl_text(sddl_text) }
12+
13+
it 'sets the protocol to 0x1ff' do
14+
expect(instance.protocol).to eq 0x1ff
15+
end
16+
17+
it 'sets the de flag' do
18+
expect(instance.de).to eq 1
19+
end
20+
21+
it 'sets the rc flag' do
22+
expect(instance.rc).to eq 1
23+
end
24+
25+
it 'sets the wd flag' do
26+
expect(instance.wd).to eq 1
27+
end
28+
29+
it 'sets the wo flag' do
30+
expect(instance.wo).to eq 1
31+
end
32+
33+
it 'sets the sy flag' do
34+
expect(instance.sy).to eq 1
35+
end
36+
37+
it 'does not set the ma flag' do
38+
expect(instance.ma).to eq 0
39+
end
40+
41+
it 'does not set the as flag' do
42+
expect(instance.as).to eq 0
43+
end
44+
end
45+
46+
context 'when the text is KA' do
47+
let(:sddl_text) { 'KA' }
48+
49+
it 'sets the protocol to 0x3f' do
50+
expect(instance.protocol).to eq 0x3f
51+
end
52+
53+
it 'sets the de flag' do
54+
expect(instance.de).to eq 1
55+
end
56+
57+
it 'sets the rc flag' do
58+
expect(instance.rc).to eq 1
59+
end
60+
61+
it 'sets the wd flag' do
62+
expect(instance.wd).to eq 1
63+
end
64+
65+
it 'sets the wo flag' do
66+
expect(instance.wo).to eq 1
67+
end
68+
69+
it 'does not set the sy flag' do
70+
expect(instance.sy).to eq 0
71+
end
72+
73+
it 'does not set the ma flag' do
74+
expect(instance.ma).to eq 0
75+
end
76+
77+
it 'does not set the as flag' do
78+
expect(instance.as).to eq 0
79+
end
80+
end
81+
82+
context 'when the text is 0x00001234' do
83+
let(:sddl_text) { '0x00001234' }
84+
85+
it 'sets the protocol to 0x1234' do
86+
expect(instance.protocol).to eq 0x1234
87+
end
88+
end
89+
end
90+
91+
describe '#to_sddl_text' do
92+
context 'when high protocol bits are set' do
93+
subject(:instance) { described_class.new(protocol: 0x1234) }
94+
it 'dumps the value in hex' do
95+
expect(instance.to_sddl_text).to eq "0x00001234"
96+
end
97+
end
98+
end
99+
end

0 commit comments

Comments
 (0)