Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MsDtypSecurityDescriptor#to_sddl_text #19879

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

zeroSteiner
Copy link
Contributor

@zeroSteiner zeroSteiner commented Feb 13, 2025

This updates the existing MsDtypSecurityDescriptor class to include a #to_sddl_text method. This allows an initialized object to be displayed using the Security Descriptor Definition Language defined by Microsoft. This is the counter part to the .from_sddl_text class method which parses SDDL text into an initialized object. During the course of the development, a few bugs were fixed in the SID to SDDL text mapping, and support for access masks as hex (e.g. 0x12345678) was supported. The domain_sid keyword argument is optional. When it's specified, it'll be used to reduce known SIDs to their SDDL two letter short code. When it's not specified, the SID is left as is.

Finally, three modules were updated to print the SDDL text when operating with security descriptors so the user can view it. In the RBCD module, this is particularly useful because the module modifies the security descriptor, so allowing the user to view it makes what is happening easier to understand and debug.

Verification (Metasploit)

List the steps needed to make sure this thing works

  • Start msfconsole
  • Use the ldap_query module and run a single query that includes the ntsecuritydescriptor attribute. See that it's parsed and displayed.
  • Use the ad_cs_cert_template module and the READ action, see the security descriptor is parsed and displayed.
  • Use the rbcd module and the READaction, see the security descriptor is parsed and displayed. It may be necessary to create one with theWRITEaction first since themsDS-AllowedToActOnBehalfOfOtherIdentity` attribute doesn't exist by default.

Verification (Technical Accuracy)

The following Powershell functions can be used to convert from binary to SDDL security descriptors.

Powershell Code
# Function to convert SDDL SID to actual SID string
function Convert-SDDLSidToSid {
    param(
        [Parameter(Mandatory=$true)]
        [string]$SDDLSid
    )
    
    try {
        # Create a new security descriptor with the SDDL SID as owner
        $sd = New-Object System.Security.AccessControl.DirectorySecurity
        $sddl = "O:$SDDLSid" # Use the SID as owner since we just need it to be parsed
        $sd.SetSecurityDescriptorSddlForm($sddl)
        
        # Get the owner (which is our SDDL SID converted to full SID)
        $sid = $sd.GetOwner([System.Security.Principal.SecurityIdentifier]).Value
        return $sid
    }
    catch {
        return "Error: Could not convert '$SDDLSid' to SID"
    }
}

function Convert-SddlToBinary {
    param (
        [Parameter(Mandatory=$true)]
        [string]$Sddl
    )
    
    try {
        $sd = New-Object System.Security.AccessControl.RawSecurityDescriptor($Sddl)
        $binary = New-Object byte[] $sd.BinaryLength
        $sd.GetBinaryForm($binary, 0)
        return ($binary | ForEach-Object { $_.ToString("X2") }) -join ""
    }
    catch {
        return "Error converting SDDL: $_"
    }
}

function Convert-BinaryToSddl {
    param (
        [Parameter(Mandatory=$true)]
        [string]$HexString
    )
    
    try {
        # Convert hex string to byte array
        $byteArray = [byte[]]::new($HexString.Length / 2)
        for ($i = 0; $i -lt $HexString.Length; $i += 2) {
            $byteArray[$i/2] = [Convert]::ToByte($HexString.Substring($i, 2), 16)
        }
        
        # Create a new RawSecurityDescriptor from the byte array
        $sd = New-Object System.Security.AccessControl.RawSecurityDescriptor($byteArray, 0)
        return $sd.GetSddlForm([System.Security.AccessControl.AccessControlSections]::All)
    }
    catch {
        return "Error converting binary to SDDL: $_"
    }
}

This Powershell code can be use to double check that a security descriptor is correct. The following snippet can be used to validate the SDDL SID short code mappings. In this case the domain SID is S-1-5-21-3978004297-3499718965-4169012971. In the output on my Server 2019 test system, there are 4 codes that couldn't be converted to a SID that are included in the language definition. Those codes are KA, CN, AP, and EK. To retain compatibility, Metasploit's implementation will accept those codes as input, but will not output them. On output, the full SID will be used instead which ensure compatibility with Windows systems that don't support the codes.

SDDL SID short code validation
# taken from: Rex::Proto::MsDtyp::MsDtypSid.const_get(:SDDL_SIDS).map {|k,v| [k,v.sub("${DOMAIN_SID}", 'S-1-5-21-3978004297-3499718965-4169012971')] }.to_h.each { |k,v| $stdout.puts "#{k},#{v}\n" }
$csvString = @"
AO,S-1-5-32-548
AP,S-1-5-21-3978004297-3499718965-4169012971-525
AU,S-1-5-11
BA,S-1-5-32-544
BG,S-1-5-32-546
BO,S-1-5-32-551
BU,S-1-5-32-545
CA,S-1-5-21-3978004297-3499718965-4169012971-517
CD,S-1-5-32-574
CG,S-1-3-1
CN,S-1-5-21-3978004297-3499718965-4169012971-522
CO,S-1-3-0
DA,S-1-5-21-3978004297-3499718965-4169012971-512
DC,S-1-5-21-3978004297-3499718965-4169012971-515
DD,S-1-5-21-3978004297-3499718965-4169012971-516
DG,S-1-5-21-3978004297-3499718965-4169012971-514
DU,S-1-5-21-3978004297-3499718965-4169012971-513
EA,S-1-5-21-3978004297-3499718965-4169012971-519
ED,S-1-5-9
EK,S-1-5-21-3978004297-3499718965-4169012971-32
ER,S-1-5-32-573
ES,S-1-5-32-576
HA,S-1-5-32-578
HI,S-1-16-12288
IS,S-1-5-32-568
IU,S-1-5-4
KA,S-1-5-21-3978004297-3499718965-4169012971-526
LA,S-1-5-21-3978004297-3499718965-4169012971-500
LG,S-1-5-21-3978004297-3499718965-4169012971-501
LS,S-1-5-19
LU,S-1-5-32-559
LW,S-1-16-4096
ME,S-1-16-8192
MP,S-1-16-8448
MU,S-1-5-32-558
NO,S-1-5-32-556
NS,S-1-5-20
NU,S-1-5-2
OW,S-1-3-4
PA,S-1-5-21-3978004297-3499718965-4169012971-520
PO,S-1-5-32-550
PS,S-1-5-10
PU,S-1-5-32-547
RA,S-1-5-32-575
RC,S-1-5-12
RD,S-1-5-32-555
RE,S-1-5-32-552
RM,S-1-5-32-580
RO,S-1-5-21-3978004297-3499718965-4169012971-498
RS,S-1-5-21-3978004297-3499718965-4169012971-553
RU,S-1-5-32-554
SA,S-1-5-21-3978004297-3499718965-4169012971-518
SI,S-1-16-16384
SO,S-1-5-32-549
SS,S-1-18-2
SU,S-1-5-6
SY,S-1-5-18
UD,S-1-5-84-0-0-0-0-0
WD,S-1-1-0
WR,S-1-5-33
"@
$mappings = @{}
$csvString | ConvertFrom-CSV -Header "SDDL","SID" | ForEach-Object {
    $mappings[$_.SDDL] = $_.SID
}
Write-Host ("`nSDDL  ExpectedSID                                              ActualSID Matches")
Write-Host ("----  ----------                                              ---------                                               -------")
$mappings.GetEnumerator() | ForEach-Object {
    $sddlSid = $_.Name
    $expectedSid = $_.Value
    $actualSid = Convert-SDDLSidToSid -SDDLSid $sddlSid
    
    $match = $actualSid -eq $expectedSid
    $line = "{0,-6}{1,-55}{2,-55}{3}" -f $sddlSid, $expectedSid, $actualSid, $(if ($match) { "" } else { "" })
 
   if ($match) {
        Write-Host $line
    } else {
        Write-Host $line -ForegroundColor Red
    }
}

Demo

metasploit-framework (S:0 J:0) auxiliary(admin/ldap/rbcd) > write
[*] Running module against 192.168.159.10
[+] Successfully bound to the LDAP server!
[*] Discovering base DN automatically
[*] Creating new msDS-AllowedToActOnBehalfOfOtherIdentity...
[*] New msDS-AllowedToActOnBehalfOfOtherIdentity: O:BAD:(A;;0xf31fffff;;;S-1-5-21-3978004297-3499718965-4169012971-1602)
[+] Successfully created the msDS-AllowedToActOnBehalfOfOtherIdentity attribute.
[*] Added account:
[*]   S-1-5-21-3978004297-3499718965-4169012971-1602 (WIN-NJ6DUF1OCAM$)
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:0) auxiliary(admin/ldap/rbcd) >
metasploit-framework (S:0 J:0) auxiliary(admin/ldap/ad_cs_cert_template) > read
[*] Running module against 192.168.159.10
[+] Successfully bound to the LDAP server!
[*] Discovering base DN automatically
[+] Read certificate template data for: CN=User,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=msflab,DC=local
[*] Certificate template data written to: /home/smcintyre/.msf4/loot/20250213171340_default_192.168.159.10_windows.ad.cs.te_828133.json
[*] Certificate Template:
[*]   distinguishedName:    CN=User,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=msflab,DC=local
[*]   displayName:          User
[*]   objectGUID:           42c80bef-c7df-4bca-931a-e2780325874f
[*]   nTSecurityDescriptor: D:PAI(OA;;RPWPCR;0e10c968-78fb-11d2-90d4-00c04f79dc55;;DA)(OA;;RPWPCR;0e10c968-78fb-11d2-90d4-00c04f79dc55;;DU)(OA;;RPWPCR;0e10c968-78fb-11d2-90d4-00c04f79dc55;;EA)(A;;CCDCLCSWRPWPDTLOSDRCWDWO;;;DA)(A;;CCDCLCSWRPWPDTLOSDRCWDWO;;;EA)(A;;LCRPLORC;;;AU)
[*]   flags: 0x0001023a
[*]      * CT_FLAG_AUTO_ENROLLMENT
[*]      * CT_FLAG_ADD_TEMPLATE_NAME
[*]      * CT_FLAG_IS_DEFAULT
[*]      * CT_FLAG_ADD_EMAIL
[*]      * CT_FLAG_PUBLISH_TO_DS
[*]      * CT_FLAG_EXPORTABLE_KEY
[*]   msPKI-Certificate-Name-Flag: 0xa6000000
[*]     * CT_FLAG_SUBJECT_ALT_REQUIRE_UPN
[*]     * CT_FLAG_SUBJECT_ALT_REQUIRE_EMAIL
[*]     * CT_FLAG_SUBJECT_REQUIRE_EMAIL
[*]     * CT_FLAG_SUBJECT_REQUIRE_DIRECTORY_PATH
[*]   msPKI-Enrollment-Flag: 0x00000029
[*]     * CT_FLAG_INCLUDE_SYMMETRIC_ALGORITHMS
[*]     * CT_FLAG_PUBLISH_TO_DS
[*]     * CT_FLAG_AUTO_ENROLLMENT
[*]   msPKI-Private-Key-Flag: 0x00000010
[*]     * CT_FLAG_EXPORTABLE_KEY
[*]   msPKI-RA-Signature: 0x00000000
[*]   msPKI-Template-Schema-Version: 1
[*]   pKIKeyUsage: 0x00000000
[*]   pKIExtendedKeyUsage:
[*]     * 1.3.6.1.5.5.7.3.2 (Client Authentication)
[*]     * 1.3.6.1.5.5.7.3.4 (Secure Email)
[*]     * 1.3.6.1.4.1.311.10.3.4 (Encrypting File System)
[*]   pKIMaxIssuingDepth: 0
[*]   showInAdvancedViewOnly: TRUE
[+] The operation completed successfully!
[*] Auxiliary module execution completed

@smcintyre-r7 smcintyre-r7 added enhancement rn-enhancement release notes enhancement labels Feb 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement rn-enhancement release notes enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants