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

[dacledit.py] New example script for DACL manipulation #1291

Merged
merged 26 commits into from
Apr 26, 2024

Conversation

ShutdownRepo
Copy link
Contributor

Equivalent to Add/Get-DomainObjectAcl from PowerSploit's PowerView with additional features.
This script can be used to read, write, remove, backup, restore ACEs (Access Control Entries) in an object DACL (Discretionary Access Control List)
The script also resolved SID and GUID and input principals can be supplied either with their sAMAccountName, DN (Distinguished Name) or SID (Security IDentifier).
Since it's an Impacket script, all major authentication means are supported (ntlm plaintext, kerberos plaintext, pass-the-hash, overpass-the-hash, pass-the-ticket, pass-the-key, etc.)
This script can be used for Access Control abuse when an attacker-controlled object has WriteDacl over another for example (more about this on The Hacker Recipes).

In the screenshot below is an example of a DCSync "right" (i.e. GetChanges and GetChangesAll ACEs) addition to the domain object DACL.

dacledit_dcsync_filteredsearch_restore_noted

In the screenshot below is an example of a DACL read without filtering.

dacledit_read

Nota bene:

  • At the moment, only ACCESS_ALLOWED_ACE and ACCESS_ALLOWED_OBJECT_ACE ACE types are supported for full parsing, they are the most common ones. Contributors could implement parsing of the other types if they wish.
  • An interesting feature could be to add an "analyze" action that would read an object DACL but print it in a nicer, more readable form (reference).
  • The built-in rights in the tool replicate what PowerView offers: FullControl (maxed out simple permission, combination of ACE access masks), WriteMembers, ResetPassword, and DCSync (DS-Replication-Get-Changes and DS-Replication-Get-Changes-All extended rights)
  • The pull request also includes a list of schema objects and their GUID listed in MS-ADA 1, 2 and 3, added in the lib

Co-authored by @BlWasp

@ShutdownRepo
Copy link
Contributor Author

@BlWasp added support for ACCESS_DENIED_ACE and ACCESS_DENIED_OBJECT_ACE ACE types
An option -ace-type to filter on the allowed/denied type

@mubix
Copy link
Contributor

mubix commented May 5, 2022

This is awesome! Definitely using this 👍

@ShutdownRepo ShutdownRepo marked this pull request as ready for review July 17, 2022 17:58
@ShutdownRepo ShutdownRepo marked this pull request as draft July 21, 2022 21:48
@ShutdownRepo
Copy link
Contributor Author

Converting this PR to draft since there is an issue on the restore feature. If the -file argument is supplied with an existing filename, it will get overwritten with an automatic new backup. I need to fix this before converting the PR to "ready for review".
Thanks @Synzack for pointing it out (in DMs)!

@s0i37
Copy link

s0i37 commented Oct 5, 2022

BTW, ACL read/edit is already implemented in msldap. Also winacl is a good python library for parsing any ACL.
For example skelsec/msldap#22

@knobrazz
Copy link

i need dacledit.py for HTB can anyone help?

@ShutdownRepo
Copy link
Contributor Author

i need dacledit.py for HTB can anyone help?

Either merge the PR yourself on a fork of yours, or if you don’t know how and won’t DIY you can also use Exegol (https://github.com/ShutdownRepo/Exegol) or my Impacket fork’s exegol branch (https://github.com/ShutdownRepo/impacket/tree/exegol)

@Zamanry
Copy link

Zamanry commented Dec 1, 2022

Love the contribution! I am new to DACLs, ACEs, etc, so bear with me please. I am running dacledit.py on Kali 2023.3 using Python 3.10 and only attempting password changes on Windows 10. Both systems are non-domain joined.

My coworker and I are trying to use this tool in an environment where we have compromised PC$ which has GenericAll rights over an OU, CompanyA, where we are trying to change the password on user auditor1 which is within the CompanyA OU. Unfortunately, the below command does not provide us the right to force change auditor1 password:

python ./dacledit.py domain.tld/'PC$' -hashes 'LM:NTLM' -action write -target-dn 'OU=COMPANYA,OU=DOMAIN USERS,DC=DOMAIN,DC=TLD'

When we use the read parameter to verify a successful write, PC$ will have allowed full control over the COMPANYA OU. Please note we are using the same domain controller throughout the process and even making sure to target the Schema Master DC. However, we are unable to use Windows RSAT's Set-ADAccountPassword -Server dc.domain.tld -Identity 'auditor1' -Reset in a runas netonly shell under the PC$ context to change the password. We get Access Denied on the return. The new password attempted to use was 32 characters with 4/4 complexity which will meet domain password requirements. This runas shell is successfully authenticating to the domain and returns results from Get-ADUser -Server dc.domain.tld -Identity 'auditor1'.

This is where our knowledge gets a little fuzzy. We believe the reason we cannot change the password OR add a SPN to auditor1 using krbrelayx to kerberoast, is because of inheritance. We manually modified dacledit.py to specify the OBJECT_INHERIT_ACE flag for principal PC$ targeting COMPANYA OU and can confirm this was successfully written to the DC using this code change:
image

However, once again, we cannot password change auditor1 or add an SPN to auditor1. We are theorizing we need two ACE flags, OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE so that PC$ can modify the OU which will then allow PC$ to modify auditor1.

tldr; We think it would be cool for dacledit.py to allow a parameter to specify which ACE flags you want. From our understanding and why we can't get this to work, is needing to combine/mask? OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE together in their binary required ACE flag format. We don't know how to do that after researching for a few hours and would love to see this feature be added.

We were able to confirm the ACE/DACL was successfully written using aced (see my PR there for OU DN listing), but BloodHound (only the GUI, not parsing the files) using PC$ (targeting the same DC) did not say we could force change auditor1 password. Any help on our issue here or thoughts on the potential enhancement would be great.

My resources:

@Zamanry
Copy link

Zamanry commented Dec 2, 2022

Love the contribution! I am new to DACLs, ACEs, etc, so bear with me please. I am running dacledit.py on Kali 2023.3 using Python 3.10 and only attempting password changes on Windows 10. Both systems are non-domain joined.

My coworker and I are trying to use this tool in an environment where we have compromised PC$ which has GenericAll rights over an OU, CompanyA, where we are trying to change the password on user auditor1 which is within the CompanyA OU. Unfortunately, the below command does not provide us the right to force change auditor1 password:

python ./dacledit.py domain.tld/'PC$' -hashes 'LM:NTLM' -action write -target-dn 'OU=COMPANYA,OU=DOMAIN USERS,DC=DOMAIN,DC=TLD'

When we use the read parameter to verify a successful write, PC$ will have allowed full control over the COMPANYA OU. Please note we are using the same domain controller throughout the process and even making sure to target the Schema Master DC. However, we are unable to use Windows RSAT's Set-ADAccountPassword -Server dc.domain.tld -Identity 'auditor1' -Reset in a runas netonly shell under the PC$ context to change the password. We get Access Denied on the return. The new password attempted to use was 32 characters with 4/4 complexity which will meet domain password requirements. This runas shell is successfully authenticating to the domain and returns results from Get-ADUser -Server dc.domain.tld -Identity 'auditor1'.

This is where our knowledge gets a little fuzzy. We believe the reason we cannot change the password OR add a SPN to auditor1 using krbrelayx to kerberoast, is because of inheritance. We manually modified dacledit.py to specify the OBJECT_INHERIT_ACE flag for principal PC$ targeting COMPANYA OU and can confirm this was successfully written to the DC using this code change: image

However, once again, we cannot password change auditor1 or add an SPN to auditor1. We are theorizing we need two ACE flags, OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE so that PC$ can modify the OU which will then allow PC$ to modify auditor1.

tldr; We think it would be cool for dacledit.py to allow a parameter to specify which ACE flags you want. From our understanding and why we can't get this to work, is needing to combine/mask? OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE together in their binary required ACE flag format. We don't know how to do that after researching for a few hours and would love to see this feature be added.

We were able to confirm the ACE/DACL was successfully written using aced (see my PR there for OU DN listing), but BloodHound (only the GUI, not parsing the files) using PC$ (targeting the same DC) did not say we could force change auditor1 password. Any help on our issue here or thoughts on the potential enhancement would be great.

My resources:

My coworker and I managed to get the OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE ACE flags to apply through reverting the above screenshot's change and changing 0x00 to 0x03. We were able to successfully change the auditor1 account password. For anyone else reading this, our understanding is just adding together the desired ACE flags from this Microsoft link and changing that piece of code above.

@BlWasp
Copy link
Contributor

BlWasp commented Dec 15, 2022

Hey all ! @Zamanry thanks for your comment are your explains ! I have added the -inheritance option. This switch will now setup the flag value to 0x03.

This Tweeter thread also explains very well the situation : https://twitter.com/M4yFly/status/1603035773628215296

@Zamanry
Copy link

Zamanry commented Dec 15, 2022

Hey all ! @Zamanry thanks for your comment are your explains ! I have added the -inheritance option. This switch will now setup the flag value to 0x03.

This Tweeter thread also explains very well the situation : https://twitter.com/M4yFly/status/1603035773628215296

This is what I figured would be the simplest approach. My only concern is if there is ever a time in which someone would want some specific inheritance flags (again not my area of expertise), they wouldn't be able to easily set those flags. But definitely think having object vs. container high level parameters is a good start.

@ShutdownRepo
Copy link
Contributor Author

ShutdownRepo commented Dec 15, 2022

Hey all ! @Zamanry thanks for your comment are your explains ! I have added the -inheritance option. This switch will now setup the flag value to 0x03.
This Tweeter thread also explains very well the situation : https://twitter.com/M4yFly/status/1603035773628215296

This is was what I figured would be the best simple approach. My only concern is if there is ever a time in which someone would want some specific inheritance flags (again not my area of expertise). But definitely think having object vs. container high level parameters is a good start.

Yup, @BlWasp and I figured the -inheritance flag would be a good, high-level, start, if there's another specific need later on, we'll manage then :)

Added guidance to The Hacker Recipe's mindmap: https://www.thehacker.recipes/ad/movement/dacl

@BlWasp
Copy link
Contributor

BlWasp commented Dec 16, 2022

Hey all ! @Zamanry thanks for your comment are your explains ! I have added the -inheritance option. This switch will now setup the flag value to 0x03.
This Tweeter thread also explains very well the situation : https://twitter.com/M4yFly/status/1603035773628215296

This is what I figured would be the simplest approach. My only concern is if there is ever a time in which someone would want some specific inheritance flags (again not my area of expertise), they wouldn't be able to easily set those flags. But definitely think having object vs. container high level parameters is a good start.

Hello, yes as indicated by @ShutdownRepo this is just a starting point. In an offensive point of view the other ACE flags are not particularly useful, but they could be added later top the parameter 😃

@trigat
Copy link

trigat commented Jul 3, 2023

I'm confused. Can someone tell me where I can find dacledit.py?

@BlWasp
Copy link
Contributor

BlWasp commented Jul 5, 2023

I'm confused. Can someone tell me where I can find dacledit.py?

This PR has not been merged for the moment. You can use the source repo of the PR with the good branch : https://github.com/ShutdownRepo/impacket/tree/dacledit

@n3rada
Copy link

n3rada commented Jul 21, 2023

Wait, still not merged? How?

@ShutdownRepo
Copy link
Contributor Author

Wait, still not merged? How?

In the mean time you'll find it @ ThePorgs/Impacket, or in Exegol

@ShutdownRepo ShutdownRepo changed the title [dacledit] New example script for DACL manipulation [dacledit.py] New example script for DACL manipulation Aug 23, 2023
@ShutdownRepo
Copy link
Contributor Author

any news here?

@anadrianmanrique
Copy link
Contributor

@ShutdownRepo I'll be reviewing this PR. This looks like and old one, but also straightforward to integrated. I'll let you know the results of the review. Thanks

@anadrianmanrique anadrianmanrique merged commit 65f4407 into fortra:master Apr 26, 2024
9 checks passed
@anadrianmanrique
Copy link
Contributor

merged now into master branch. Thanks for the amazing work!

@ShutdownRepo
Copy link
Contributor Author

Awesome, thank you @anadrianmanrique for the review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
high High priority item
Projects
None yet
Development

Successfully merging this pull request may close these issues.