zblurx / acltoolkit Goto Github PK
View Code? Open in Web Editor NEWACL abuse swiss-knife
License: MIT License
ACL abuse swiss-knife
License: MIT License
While packaging acltoolkit for homebrew, I found some syntax warnings with py3.12
/opt/homebrew/Cellar/acltoolkit/0.2.2/libexec/lib/python3.12/site-packages/acltoolkit/get_objectacl.py:149: SyntaxWarning: invalid escape sequence '\%'
self._sid_map[sid] = '%s\%s' % (self.domain.get("name"),result.get("name"))
/opt/homebrew/Cellar/acltoolkit/0.2.2/libexec/lib/python3.12/site-packages/acltoolkit/ldap.py:107: SyntaxWarning: invalid escape sequence '\%'
user="%s\%s" % (target.domain, target.username),
/opt/homebrew/Cellar/acltoolkit/0.2.2/libexec/lib/python3.12/site-packages/acltoolkit/ldap.py:115: SyntaxWarning: invalid escape sequence '\%'
user="%s\%s" % (target.domain, target.username),
Hello zblurx
Happy new year and congratulations for your super b tool.
It's my first time trying to exploit a Windows Domain ACL issue, I found your tool linked in a blogpost from DCSync, I discovered bloodyAD and acltoolkit with this blogpost. Well, I failed miserable trying to exploit it, I will be very helpful if you could provide some insights. My case is like the one below (obtained via bloodhound - if you think it helps, I can upload images anywhere or send to your email if you prefer), looks like two paths exist from MyUser to DomainAdmins via ACL issues.
PATH 1: MyUser <---> Group1 <---> Group2 <---> (GenericAll) <---> MyDomain <---> (contains) Users Privileged Group <----> Domain Admin
PATH 2: MyUser <---> Group1 <---> Group2 <---> (AddMember) <---> Enterprise Key Accounts <---> (GenericALL)Users Privileged Group <----> Domain Admin
I'm using output from the 3 tools, I hope that you don't mind, I wanted to make sure it was not an specific issue of a specific tool.
My first try as a dumb guy was to use DCSync from the blog post and I failed miserable.
└─$ python3 DCSync.py -dc dcname.Mydomain -t "CN=muser,OU=Users,OU=London,OU=MyCompany,DC=Mydomain,DC=INT" Mydomain\\muser:'mypass'
Impacket v0.10.1.dev1+20221214.172823.8799a1a2 - Copyright 2022 Fortra
[*] Starting DCSync Attack against CN=muser,OU=Users,OU=London,OU=MyCompany,DC=Mydomain,DC=INT
[*] Initializing LDAP connection to dcname.Mydomain
[*] Using Mydomain\muser account with password ***
[*] LDAP bind OK
[*] Initializing domainDumper()
[*] Initializing LDAPAttack()
[*] Querying domain security descriptor
[-] Error when updating ACL: {'result': 50, 'description': 'insufficientAccessRights', 'dn': '', 'message': '00000005: SecErr: DSID-03152DB2, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0\n\x00', 'referrals': None, 'type': 'modifyResponse'}
It says that I don't have privilege, my guess was that I had to follow PATH2 for example and add MyUser to Enterprise Key Accounts or give GenericAll to Users Privileged Group and than DCSync, but I also failed miserable.
└─$ acltoolkit Mydomain/myuser:'mypass'@192.168.1.31 -debug -scheme ldap add-groupmember -user muser2 -group Enterprise Key Accounts
[+] Connecting to LDAP at '192.168.1.31' (192.168.1.31)
[+] Connected to 192.168.1.31, port 389, SSL False
[*] Will add CN=muser2,OU=Users,OU=London,OU=MyCompany,DC=Mydomain,DC=int to CN=Enterprise Key Accounts ,OU=Admin Groups,OU=Management,OU=MyCompany,DC=Mydomain,DC=int group
Traceback (most recent call last):
File "/home/kali/.local/bin//acltoolkit", line 8, in <module>
sys.exit(main())
File "/home/kali/.local/lib/python3.10/site-packages/acltoolkit/entry.py", line 207, in main
add_groupmember(options)
File "/home/kali/.local/lib/python3.10/site-packages/acltoolkit/add_groupmember.py", line 88, in add_groupmember
g.run()
File "/home/kali/.local/lib/python3.10/site-packages/acltoolkit/add_groupmember.py", line 38, in run
raise Exception('Could not modify object, the server reports insufficient rights: %s', ret['message'])
Exception: ('Could not modify object, the server reports insufficient rights: %s', '00002098: SecErr: DSID-031514A0, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0\n\x00')
It says that I have no privilege at all, however bloodhound told that I could AddMember, I was thinking if Bloodhound could have interpreted it wrong, but I guess the error is me. Any advice here?
I moved to give GenericAll to the Privileged group and this time the error was different in both tools which called my attention
└─$ python3 bloodyAD.py -d Mydomain -u muser -p 'mypass' --host 192.168.1.31 setGenericAll S-1-5-21-1908570442-2185358661-9027324241-2102 S-1-5-21-1908570442-2185358661-9027324241-128064
[*] S-1-5-21-1908570442-2185358661-9027324241-2102 SID is: S-1-5-21-1908570442-2185358661-9027324241-2102
Traceback (most recent call last):
File "/home/kali/bloodyAD/bloodyAD.py", line 5, in <module>
main.main()
File "/home/kali/bloodyAD/bloodyAD/main.py", line 132, in main
args.func(conn, **params)
File "/home/kali/bloodyAD/bloodyAD/modules.py", line 334, in setGenericAll
setAttr(conn, target, ldap_attribute, [new_sd.getData()], control_flag)
File "/home/kali/bloodyAD/bloodyAD/utils.py", line 155, in setAttr
ldap_conn.modify(dn, {attribute: [ldap3.MODIFY_REPLACE, value]}, controls)
File "/usr/lib/python3/dist-packages/ldap3/core/connection.py", line 1150, in modify
response = self.post_send_single_response(self.send('modifyRequest', request, controls))
File "/usr/lib/python3/dist-packages/ldap3/strategy/sync.py", line 160, in post_send_single_response
responses, result = self.get_response(message_id)
File "/usr/lib/python3/dist-packages/ldap3/strategy/base.py", line 403, in get_response
raise LDAPOperationResult(result=result['result'], description=result['description'], dn=result['dn'], message=result['message'], response_type=result['type'])
ldap3.core.exceptions.LDAPInsufficientAccessRightsResult: LDAPInsufficientAccessRightsResult - 50 - insufficientAccessRights - None - 00000005: SecErr: DSID-03152DB2, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0
- modifyResponse - None
─$ acltoolkit Mydomain/muser:'mypass'@192.168.1.31 -debug -scheme ldap give-genericall -target-sid S-1-5-21-1908570442-2185358661-9027324241-2102 -granted-sid S-1-5-21-1908570442-2185358661-9027324241-128064
[+] Connecting to LDAP at '192.168.1.31' (192.168.1.31)
[+] Connected to 192.168.1.31, port 389, SSL False
[*] Find target object: CN=_svcSccmWks,OU=Contas de Servico,OU=Contas de Infraestrutura,OU=Management,OU=MyCompany,DC=Mydomain,DC=int
[*] Granted object will be: CN=muser2,OU=Users,OU=London,OU=MyCompany,DC=Mydomain,DC=int
Traceback (most recent call last):
File "/home/kali/.local/bin//acltoolkit", line 8, in <module>
sys.exit(main())
File "/home/kali/.local/lib/python3.10/site-packages/acltoolkit/entry.py", line 203, in main
give_genericall(options)
File "/home/kali/.local/lib/python3.10/site-packages/acltoolkit/give_genericall.py", line 114, in give_genericall
g.run()
File "/home/kali/.local/lib/python3.10/site-packages/acltoolkit/give_genericall.py", line 46, in run
raise Exception('Could not modify object, the server reports a constrained violation: %s', ret['message'])
Exception: ('Could not modify object, the server reports a constrained violation: %s', '0000051B: AtrErr: DSID-030F2312, #1:\n\t0: 0000051B: DSID-030F2312, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 20119 (nTSecurityDescriptor)\n\x00')
Where -target-sid is the value of "Users Privileged Group" and -granted-sid is the SID of Myuser.
One thing that called my attention is that the errors are different from both tools. Curious, not?
Have you seen this before? I searched at Google and it says in some forums that the error from the second tool could be privilege missing (similar to the error of the first tool) and others some crazy stuff about CN / DN names. Any guess?
I was curious if Bloodhound got data wrong, so I used these awesome tools to see the privilege of Myuser and it display the following.
└─$ acltoolkit Mydomain/muser:'mypass'@192.168.1.31 -debug -scheme ldap get-objectacl
[+] Connecting to LDAP at '192.168.1.31' (192.168.1.31)
[+] Connected to 192.168.1.31, port 389, SSL False
Sid : S-1-5-21-1908570442-2185358661-9027324241-112468
Name : Mydomain\muser
DN : CN=muser,OU=Users,OU=London,OU=Mycompany,DC=Mydomain,DC=int
Class : top, person, organizationalPerson, user
adminCount : True
The first thing that called my attention was this "adminCount: True". Does it means that the user was supposed to be Admin?
A bunch of information about groups that I'm member and finally the end (that looks interesting to me):
Dacl
ObjectSid : S-1-5-21-1908570442-2185358661-9027324241-20452
Name : Mydomain\Exchange Servers
AceType : ACCESS_ALLOWED_OBJECT_ACE
AccessMask : 256
ADRights : EXTENDED_RIGHTS
IsInherited : False
ObjectAceType : DS-Replication-Synchronize
ObjectSid : S-1-1-0
Name : Everyone
AceType : ACCESS_ALLOWED_OBJECT_ACE
AccessMask : 256
ADRights : EXTENDED_RIGHTS
IsInherited : False
ObjectAceType : User-Change-Password
ObjectSid : S-1-5-10
Name : Principal Self
AceType : ACCESS_ALLOWED_OBJECT_ACE
AccessMask : 256
ADRights : EXTENDED_RIGHTS
IsInherited : False
ObjectAceType : User-Change-Password
ObjectSid : S-1-5-10
Name : Principal Self
AceType : ACCESS_ALLOWED_OBJECT_ACE
AccessMask : 304
ADRights : EXTENDED_RIGHTS, WRITE_PROPERTY, READ_PROPERTY
IsInherited : False
ObjectAceType : Private-Information
ObjectSid : S-1-5-21-1908570442-2185358661-9027324241-512
Name : Mydomain\Domain Admins
AceType : ACCESS_ALLOWED_ACE
AccessMask : 917951
ADRights : WRITE_OWNER, WRITE_DACL, GENERIC_READ, EXTENDED_RIGHTS, WRITE_PROPERTY, SELF, DELETE_CHILD, CREATE_CHILD
IsInherited : False
ObjectSid : S-1-5-21-1908570442-2185358661-9027324241-519
Name : Mydomain\Enterprise Admins
AceType : ACCESS_ALLOWED_ACE
AccessMask : 917951
ADRights : WRITE_OWNER, WRITE_DACL, GENERIC_READ, EXTENDED_RIGHTS, WRITE_PROPERTY, SELF, DELETE_CHILD, CREATE_CHILD
IsInherited : False
ObjectSid : S-1-5-32-544
Name : BUILTIN\Administrator
AceType : ACCESS_ALLOWED_ACE
AccessMask : 983487
ADRights : WRITE_OWNER, WRITE_DACL, GENERIC_READ, DELETE, EXTENDED_RIGHTS, WRITE_PROPERTY, SELF, DELETE_CHILD, CREATE_CHILD
IsInherited False
I got a bit confused here, in this case the ADRights is what I should consider? Or the IsInherited as False means that I dont have this priv?
This AccessMask appears weird to me, I was searching about it and found https://learn.microsoft.com/en-us/windows/win32/secauthz/access-mask
But I cant find a value that represent for example 983487, even converting from decimal to hex (983487) it does not match. Do you know any tool or site that may help to convert it properly?
I did with the great bloodyAD as well.
─$ python3 bloodyAD.py -d Mydomain -u muser -p 'mypass' --host 192.168.1.31 getObjectAttributes S-1-5-21-1908570442-2185358661-9027324241-112468
{
"accountExpires": “xxxxxxx”,
"adminCount": 1,
"badPasswordTime": "xxxxxxx”",
"badPwdCount": 0,
"cn": "muser",
"codePage": 0,
"company": "Company Name",
"countryCode": 0,
"dSCorePropagationData": [
"xxxxxxx"
],
"department": “Some “User,
"description": [
“Employee”
],
"displayName": “My “Name,
"distinguishedName": "CN=muser,OU=Users,OU=London,OU=MyCompany,DC=Mydomain,DC=int",
"extensionAttribute1": “CompanyName”,
"extensionAttribute10": "xxxxxxx”",
"extensionAttribute11": "xxxxxxx”",
"extensionAttribute12": "xxxxxxx”",
"extensionAttribute13": "xxxxxxx”",
"extensionAttribute14": "xxxxxxx”,
"extensionAttribute3": "xxxxxxx”",
"extensionAttribute4": "xxxxxxx”",
Bunch of stuff not related…
"mS-DS-ConsistencyGuid": {
"encoded": “Base64 data=",
"encoding": "base64"
},
"mail": "gxxxxxxx”",
"mailNickname": "muser",
"manager": "CN=mymanagerName,OU=Users,OU=London,OU=MyCompany,DC=Mydomain,DC=int",
"memberOf": [
“A “lot of groups”
],
"msDS-ExternalDirectoryObjectId": "User_ID”,
"msDS-KeyCredentialLink": [
“Long numbers - ID?”
],
"msExchArchiveGUID": {
"encoded": “base”64,
"encoding": "base64"
},
"msExchArchiveName": [
"Personal Archive - xxxxxxx”"
],
Stuff about exchange….
],
"msExchUserAccountControl": 0,
"msExchUserHoldPolicies": [
“Hexa”
],
"msExchVersion": Numbers,
"msExchWhenMailboxCreated": “Date”,
"nTSecurityDescriptor": {
"Owner": "Domain Admins"
},
"name": "muser",
"objectCategory": "CN=Person,CN=Schema,CN=Configuration,DC=Mydomain,DC=int",
"objectClass": [
"top",
"person",
"organizationalPerson",
"user"
],
"objectGUID": “{GID}”,
"objectSid": “My”SID,
"pager": "muser",
Other useless data…
I tried set-objectowner and a lot of other combinations, all with the same errors.
This thing of ACE and ACL is a bit obscure to me yet, just to try learn I got another user and this one was very different and a few things called my attention while enumerating objects and privileges...
└─$ acltoolkit mydomain/muser:'Mypass'@192.168.1.31 -debug -scheme ldap get-objectacl
[+] Connecting to LDAP at '192.168.1.31' (192.168.1.31)
[+] Connected to 192.168.1.31, port 389, SSL False
Sid : S-1-5-21-1908570442-2185358661-9027324241-110446
Name : Mydomain\muser
DN : CN=muser,OU=Users,OU=London,OU=Mcompany,DC=Mydomain,DC=int
Class : top, person, organizationalPerson, user
adminCount : False
First thing, adminCount is False, which is different from my previous user. However below it gets curious
The DS-Replication-Synchronize does not show up. Normal? Is it expected?
However on the DACL part it says:
ObjectSid : S-1-5-21-1908570442-2185358661-9027324241-512
Name : Mydomain\Domain Admins
AceType : ACCESS_ALLOWED_ACE
AccessMask : 983551
ADRights : GENERIC_ALL
IsInherited : False
It says GENERIC_ALL, and for enterprise admins also GENERIC_ALL and IsInherited true this time (come from a groups that this member belongs I guess).
ObjectSid : S-1-5-21-1908570442-2185358661-9027324241-519
Name : Mydomain\Enterprise Admins
AceType : ACCESS_ALLOWED_ACE
AccessMask : 983551
ADRights : GENERIC_ALL
IsInherited : True
If I try DCsync or for example set GenericAll I get the same error as before, saying INSUFF_ACCESS_RIGHTS...
I tried all kind of stuff, even the ones that are not supposed to work! LOL
└─$ python3 bloodyAD.py -d Mydomain -u muser -p 'mypass' --host 192.168.1.31 addUser NewUser TestPass123
Traceback (most recent call last):
File "/home/kali/bloodyAD/bloodyAD.py", line 5, in <module>
main.main()
File "/home/kali/bloodyAD/bloodyAD/main.py", line 132, in main
args.func(conn, **params)
File "/home/kali/bloodyAD/bloodyAD/modules.py", line 107, in addUser
ldap_conn.add(user_dn, attributes=attr)
File "/usr/lib/python3/dist-packages/ldap3/core/connection.py", line 1013, in add
response = self.post_send_single_response(self.send('addRequest', request, controls))
File "/usr/lib/python3/dist-packages/ldap3/strategy/sync.py", line 160, in post_send_single_response
responses, result = self.get_response(message_id)
File "/usr/lib/python3/dist-packages/ldap3/strategy/base.py", line 403, in get_response
raise LDAPOperationResult(result=result['result'], description=result['description'], dn=result['dn'], message=result['message'], response_type=result['type'])
ldap3.core.exceptions.LDAPInsufficientAccessRightsResult: LDAPInsufficientAccessRightsResult - 50 - insufficientAccessRights - None - 00000005: SecErr: DSID-03152DB2, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0
- addResponse - None
Sorry for long post
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.