Skip to content

Commit

Permalink
fix for adcs info parsing, adding windows laps sup
Browse files Browse the repository at this point in the history
  • Loading branch information
Skelsec committed Apr 15, 2023
1 parent 88770d9 commit 0bdf96b
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 6 deletions.
2 changes: 1 addition & 1 deletion msldap/_version.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

__version__ = "0.5.4"
__version__ = "0.5.5"
__banner__ = \
"""
# msldap %s
Expand Down
34 changes: 34 additions & 0 deletions msldap/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,40 @@ async def get_all_laps(self):
attributes = ['cn','ms-mcs-AdmPwd']
async for entry, err in self.pagedsearch(ldap_filter, attributes):
yield entry, err

async def get_all_laps_windows(self):
"""
Fetches all LAPS passwords for all machines. This functionality is only available to specific high-privileged users.
:return: Async generator which yields (`dict`, None) tuple on success or (None, `Exception`) on error
:rtype: Iterator[(:class:`dict`, :class:`Exception`)]
"""

ldap_filter = r'(sAMAccountType=805306369)'
# first try to get the plaintext password (the new windows laps doesn't necessary encrypt the PWs)
attributes = ['cn','ms-LAPS-Password']
async for entry, err in self.pagedsearch(ldap_filter, attributes):
yield entry, err

# now try to get the encrypted password
attributes = ['cn','ms-LAPS-EncryptedPassword']
async for entry, err in self.pagedsearch(ldap_filter, attributes):
yield entry, err

# now try to get the encrypted password history
attributes = ['cn','ms-LAPS-EncryptedPasswordHistory']
async for entry, err in self.pagedsearch(ldap_filter, attributes):
yield entry, err

# now try to get the encrypted DSRM password
attributes = ['cn','ms-LAPS-EncryptedDSRMPassword']
async for entry, err in self.pagedsearch(ldap_filter, attributes):
yield entry, err

# now try to get the encrypted DSRM password history
attributes = ['cn','ms-LAPS-EncryptedDSRMPasswordHistory']
async for entry, err in self.pagedsearch(ldap_filter, attributes):
yield entry, err

async def get_schemaentry(self, dn:str):
"""
Expand Down
29 changes: 27 additions & 2 deletions msldap/examples/msldapclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -534,13 +534,38 @@ async def do_gpos(self):
async def do_laps(self):
"""Feteches all laps passwords"""
try:
# trying to get the old version LAPS
async for entry, err in self.connection.get_all_laps():
if err is not None:
raise err
pwd = '<MISSING>'
if 'ms-Mcs-AdmPwd' in entry['attributes']:
pwd = entry['attributes']['ms-Mcs-AdmPwd']
print('%s : %s' % (entry['attributes']['cn'], pwd))
print('%s : %s' % (entry['attributes']['cn'], pwd))

# now trying to get the new version LAPS
async for entry, err in self.connection.get_all_laps_windows():
if err is not None:
raise err

if 'ms-LAPS-Password' in entry['attributes']:
pwd = entry['attributes']['ms-LAPS-Password']
print('%s : %s' % (entry['attributes']['cn'], pwd))

if 'ms-LAPS-EncryptedPassword' in entry['attributes']:
pwd = entry['attributes']['ms-LAPS-EncryptedPassword']
print('%s : %s' % (entry['attributes']['cn'], pwd))

if 'ms-LAPS-EncryptedPasswordHistory' in entry['attributes']:
pwd = entry['attributes']['ms-LAPS-EncryptedPasswordHistory']
print('%s : %s' % (entry['attributes']['cn'], pwd))

if 'ms-LAPS-EncryptedDSRMPassword' in entry['attributes']:
pwd = entry['attributes']['ms-LAPS-EncryptedDSRMPassword']
print('%s : %s' % (entry['attributes']['cn'], pwd))

if 'ms-LAPS-EncryptedDSRMPasswordHistory' in entry['attributes']:
pwd = entry['attributes']['ms-LAPS-EncryptedDSRMPasswordHistory']
print('%s : %s' % (entry['attributes']['cn'], pwd))

return True
except:
Expand Down
14 changes: 12 additions & 2 deletions msldap/ldap_objects/adcertificatetemplate.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,19 @@ def print_sids(buffer, sidlist, offset = 6):
t += "Vulnerabilities: %s\r\n" % ", ".join(self.vulns)

if self.Certificate_Name_Flag is not None:
t += "msPKI-Certificate-Name-Flag: %s\r\n" % str(CertificateNameFlag(self.Certificate_Name_Flag)).split('.',1)[1].replace('|',', ')
x = str(CertificateNameFlag(self.Certificate_Name_Flag)).split('.',1)
if len(x) >= 2:
x = x[1].replace('|',', ')
else:
x = str(self.Certificate_Name_Flag).replace('|',', ')
t += "msPKI-Certificate-Name-Flag: %s\r\n" % x
if self.Enrollment_Flag is not None:
t += "msPKI-Enrollment-Flag: %s\r\n" % str(EnrollmentFlag(self.Enrollment_Flag)).split('.',1)[1].replace('|',', ')
x = str(EnrollmentFlag(self.Enrollment_Flag)).split('.',1)
if len(x) >= 2:
x = x[1].replace('|',', ')
else:
x = str(self.Enrollment_Flag).replace('|',', ')
t += "msPKI-Enrollment-Flag: %s\r\n" % x
if self.RA_Signature is not None:
t += "msPKI-RA-Signature: %s\r\n" % self.RA_Signature
if self.pKIExtendedKeyUsage is not None:
Expand Down
9 changes: 8 additions & 1 deletion msldap/protocol/typeconversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,14 @@ def multi_sd(x, encode=False):
'securityIdentifier' : single_bytes,
'unicodePwd' : single_str,
'ms-Mcs-AdmPwd' : single_str,
'msDS-AllowedToActOnBehalfOfOtherIdentity' : single_bytes,
'ms-LAPS-EncryptedPassword': single_bytes,
'ms-LAPS-EncryptedPasswordHistory': multi_bytes,
'ms-LAPS-EncryptedDSRMPassword': single_bytes,
'ms-LAPS-EncryptedDSRMPasswordHistory': multi_bytes,
'ms-LAPS-Password': single_str,
'ms-LAPS-PasswordExpirationTime': single_interval,
'msDS-AllowedToActOnBehalfOfOtherIdentity': single_bytes,
'ms-LAPS-Encrypted-Password-Attributes': single_bytes,
'cACertificate': single_bytes,
'certificateTemplates': multi_str,
'cACertificateDN': single_str,
Expand Down

0 comments on commit 0bdf96b

Please sign in to comment.