Git Product home page Git Product logo

ad_miner's Introduction

ADMiner

ADMiner is an Active Directory audit tool that leverages cypher queries to crunch data from the BloodHound graph database (neo4j) and gives you a global overview of existing weaknesses through a web-based static report, including detailed listing, dynamic graphs, key indicators history, along with risk ratings.

Main page

You can also observe indicators over time to help measuring mitigation efficiency. Main page

ADMiner was created and is maintained by the Mazars Cybersecurity Audit & Advisory team.

Installation and setup

The easier way is to do the following command using pipx:

pipx install 'git+https://github.com/Mazars-Tech/AD_Miner.git'

Or, the same way using pip:

pip install 'git+https://github.com/Mazars-Tech/AD_Miner.git'

But remain careful and aware that doing this with pip will "polute" your packages.

Prerequisites

To run AD Miner, you first need a neo4j database which contains the Active Directory objects:

  1. To extract the data from the domain, you can use tools like SharpHound, RustHound or BloodHound.py.
  2. Ingest the json files using BloodHound or BloodHound CE. To automate this step, you can use BloodHound Automation.
  3. By default, BloodHound creates a neo4j base accessible on port 7687.

Usage

Run the tool:

AD-miner [-h] [-b BOLT] [-u USERNAME] [-p PASSWORD] [-e EXTRACT_DATE] [-r RENEWAL_PASSWORD] [-a] [-c] [-l LEVEL] -cf CACHE_PREFIX [-ch NB_CHUNKS] [-co NB_CORES] [--rdp] [--evolution EVOLUTION] [--cluster CLUSTER]

Example:

AD-miner -c -cf My_Report -u neo4j -p mypassword

To better handle large data sets, it is possible to enable multi-threading and also to use a cluster of neo4j databases, as shown in the following example (where server1 handles 32 threads and server2 handles 16) :

AD-miner -c -cf My_Report -b bolt://server1:7687 -u neo4j -p mypassword  --cluster server1:7687:32,server2:7687:16

Options:

-h, --help              Show this help message and exit
-b, --bolt              Neo4j bolt connection (default: bolt://127.0.0.1:7687)
-u, --username          Neo4j username (default : neo4j)
-p, --password          Neo4j password (default : neo5j)
-e, --extract_date      Extract date (e.g., 20220131). Default: last logon date
-r, --renewal_password  Password renewal policy in days. Default: 90
-c, --cache             Use local file for neo4j data
-l, --level             Recursive level for path queries
-cf, --cache_prefix     Cache file to use (in case of multiple company cache files)
-ch, --nb_chunks        Number of chunks for parallel neo4j requests. Default : number of CPU
-co, --nb_cores         Number of cores for parallel neo4j requests. Default : number of CPU
--gpo_low               Perform a faster but incomplete query for GPO
--rdp                   Include the CanRDP edge in graphs
--evolution             Evolution over time : location of json data files. ex : '../../tests/'
--cluster               Nodes of the cluster to run parallel neo4j queries. ex : host1:port1:nCore1,host2:port2:nCore2,...

In the graph pages, you can right-click on the graph nodes to cluster them or to open the cluster.

If you have azure, an azure-specific Dashbord appears automatically (still under development)

Evolution

If you have multiple AD-Miner reports over time, you can easily track the evolution with the --evolution argument: each AD-Miner report generates a JSON data file alongside the index.html file. You just need to gather these different JSON files into a single folder and specify the path to that folder after the --evolution argument.

A tab called 'Evolution over time' then appears on the main page.

Also, views by categories 'permissions,' 'passwords,' 'kerberos' also allow you to track changes over time.

Smartest paths

AD Miner can compute paths based on their actual exploitability. Indeed, sometimes the shortest path is difficult to exploit (here because of the ExecuteDCOM before the HasSession).

While a longer but simpler path exists (here with MemberOf and AdminTo instead of ExecuteDCOM).

AD Miner automatically switches to smartest path mode when your neo4j database has the Graph Data Science plugin installed (https://neo4j.com/docs/graph-data-science/current/). The easiest way to install this plugin is to define an environment variable in your neo4j docker: NEO4J_PLUGINS=["graph-data-science"]

List of controls that currently support full graph coverage and smartest paths:

  • objects_to_domain_admin

Discord

You can join the AD Miner Discord : https://discord.com/invite/5Hpj4Gs5SS

Feel free to share any thoughts, feedback or issue that you can come up with regarding AD Miner as it's still evolving ๐Ÿ› ๏ธ

Implemented controls

The following provides a list controls that have already been implemented in AD Miner :

Dormant accounts Tier 0 sessions violation Control path cross domain from DA to DA
Ghost computers Machine accounts with admin privs Control paths to GPOs
Accounts without password expiration Obsolete OS Control paths to servers
Accounts with old passwords Inadequate number of domain admins Control paths to OU
Accounts with clear-text passwords RDP access Control paths to GMSA passwords
Kerberoastable accounts Domain functional level Control path to AdminSDHolder container
AS-REP Roastable accounts Users with admin privs Users with path to DNS Admins
Accounts with SID history Machine accounts with high privs ACL anomalies on group objects
LAPS status Non tier 0 with DCSync capabilities Objects with path to an Operator Group
LAPS access Unconstrained delegations ADCS local admin privs
KRBTGT password age Constrained delegations Empty groups/OU
DC Shadow to DA Role-based constrained delegations Guest accounts
DC Shadow to all Control paths to domain admins Pre-Windows 2000 group
Admincount relevance Protected Users Primary Group ID

Contributing

Check out how to contribute here.

ad_miner's People

Contributors

0cmenog avatar alac88 avatar banlone avatar dreamkinn avatar jmbesnard avatar k4amos avatar laxa avatar lejopra avatar lkvarnhammar avatar mazars-tech avatar n3rada avatar snowpeacock avatar tanguy-boisset avatar vangelishoareau avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ad_miner's Issues

--Azure flag doesn't work

When using the --Azure flag I am getting an error that I don't get if I skip that flag. Looks to me like perhaps lines 67-1169 (in neo4j_class.py) need to have an extra tab removed? I manually untabbed those lines and then rebuilt the package and it no longer errors out when using that flag, but if you cannot reproduce I can get the exact error message. Thanks!

Report fails with ACL/ADLocalGroup

Describe the bug
Working with a dataset that includes 3 domains and 5 tenants. The report errors out with a KeyError: 'ADLocalGroup'

Terminal Output
[+]Generate paths of objects that can RCBD on a computer Traceback (most recent call last): File "/root/.local/bin/AD-miner", line 8, in <module> sys.exit(main()) ^^^^^^ File "/root/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/__main__.py", line 184, in main users = Users(arguments, neo4j, domains) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/root/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/sources/modules/users.py", line 255, in __init__ self.number_group_ACL_anomaly = self.genGroupAnomalyAcl(domain) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/root/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/sources/modules/users.py", line 1563, in genGroupAnomalyAcl "label": f"{generic_formating.get_label_icon_dictionary()[formated_data[name_label_instance]['label']]} {formated_data[name_label_instance]['label']}" , ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ KeyError: 'ADLocalGroup'

Screenshots
image

System information

  • AD_Miner 1.2.0, installed using Python 3.11.2
  • Bloodhound-ce
  • Data collected with Sharphound
    image

Additional context
As discussed in discord, running this query MATCH (d:ADLocalGroup) DETACH DELETE d , deleting the relevant cache files (acl) makes ad-miner run successfully.

Issue running AD miner

Describe the bug
Running AD miner with the log collected with SharpHound throws error "empty neo4j database"

Terminal Output
[!]Empty neo4j database : you need to collect data with Sharphound (https://github.com/BloodHoundAD/SharpHound), BloodHound.py (https://github.com/dirkjanm/BloodHound.py) or RustHound (https://github.com/NH-RED-TEAM/RustHound) [!]And then you can fill your neo4j database with Bloodhound (https://github.com/BloodHoundAD/BloodHound)

Screenshots
image

System information

  • Linux kali 6.3.0-kali1-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.3.7-1kali1 (2023-06-29) x86_64 GNU/Linux
  • Python 3.11.4

Error message : holders of that lock are waiting for ForsetiClient on "Requesting : Objects with path to DA"

Error messages appearing while launching the tool :

[!]{code: Neo.TransientError.Transaction.DeadlockDetected} {message: ForsetiClient[transactionId=11316, clientId=49] can't acquire ExclusiveLock{owner=ForsetiClient[transactionId=11318, clientId=65]} on NODE(10408), because holders of that lock are waiting for ForsetiClient[transactionId=11316, clientId=49].
Wait list:ExclusiveLock[
Client[11318] waits for [ForsetiClient[transactionId=11316, clientId=49],ForsetiClient[transactionId=11320, clientId=67]]]}
[!]multiprocessing.pool.RemoteTraceback:
"""
Traceback (most recent call last):
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\multiprocessing\pool.py", line 125, in worker
result = (True, func(*args, **kwds))
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\multiprocessing\pool.py", line 51, in starmapstar
return list(itertools.starmap(args[0], args[1]))
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\site-packages\ad_miner\sources\modules\neo4j_class.py", line 284, in executeParallelRequest
for record in tx.run(q):
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\site-packages\neo4j_sync\work\result.py", line 251, in iter
self._connection.fetch_message()
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\site-packages\neo4j_sync\io_common.py", line 180, in inner
func(*args, **kwargs)
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\site-packages\neo4j_sync\io_bolt.py", line 658, in fetch_message
res = self._process_message(tag, fields)
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\site-packages\neo4j_sync\io_bolt4.py", line 326, in _process_message
response.on_failure(summary_metadata or {})
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\site-packages\neo4j_sync\io_common.py", line 247, in on_failure
raise Neo4jError.hydrate(**metadata)
neo4j.exceptions.TransientError: {code: Neo.TransientError.Transaction.DeadlockDetected} {message: ForsetiClient[transactionId=11316, clientId=49] can't acquire ExclusiveLock{owner=ForsetiClient[transactionId=11318, clientId=65]} on NODE(10408), because holders of that lock are waiting for ForsetiClient[transactionId=11316, clientId=49].
Wait list:ExclusiveLock[
Client[11318] waits for [ForsetiClient[transactionId=11316, clientId=49],ForsetiClient[transactionId=11320, clientId=67]]]}
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\site-packages\ad_miner_main_.py", line 77, in populate_data_and_cache
neo4j.process_request(neo4j, request_key)
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\site-packages\ad_miner\sources\modules\neo4j_class.py", line 375, in process_request
result = self.parallelWriteRequest(self, items)
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\site-packages\ad_miner\sources\modules\neo4j_class.py", line 635, in parallelRequestLegacy
for _ in tqdm.tqdm(
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\site-packages\tqdm\std.py", line 1195, in iter
for obj in iterable:
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\site-packages\ad_miner\sources\modules\istarmap.py", line 19, in
return (item for chunk in result for item in chunk)
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\multiprocessing\pool.py", line 873, in next
raise value
neo4j.exceptions.TransientError: {code: Neo.TransientError.Transaction.DeadlockDetected} {message: ForsetiClient[transactionId=11316, clientId=49] can't acquire ExclusiveLock{owner=ForsetiClient[transactionId=11318, clientId=65]} on NODE(10408), because holders of that lock are waiting for ForsetiClient[transactionId=11316, clientId=49].
Wait list:ExclusiveLock[
Client[11318] waits for [ForsetiClient[transactionId=11316, clientId=49],ForsetiClient[transactionId=11320, clientId=67]]]}

Then it continues its things and when requests are finished :

[+]Requests finished !
[+]Computing domains objects
Traceback (most recent call last):
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 196, in _run_module_as_main
return run_code(code, main_globals, None,
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 86, in run_code
exec(code, run_globals)
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\Scripts\AD-miner.exe_main
.py", line 7, in
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\site-packages\ad_miner_main
.py", line 182, in main
domains = Domains(arguments, neo4j)
File "C:\Users\Romain\AppData\Local\Programs\Python\Python310\lib\site-packages\ad_miner\sources\modules\domains.py", line 29, in init
self.objects_to_domain_admin = neo4j.all_requests["objects_to_domain_admin"][
KeyError: 'result'

Thanks for your help

KeyError: 'result' when Computing domain objects

Describe the bug
After installing the latest version of AD_Miner using pipx, and launching it, multiple errors occured, but I think that only the latest one is related to the problem. Indeed, the render folder is empty, but not the cache_neo4j folder:

$ ls -la render_test/
total 44
drwxr-xr-x 8 t0 t0  4096 Nov 21 19:51 .
drwxr-xr-x 4 t0 t0 12288 Nov 21 19:51 ..
drwxr-xr-x 2 t0 t0  4096 Nov 21 18:44 assets
drwxr-xr-x 2 t0 t0  4096 Nov 21 18:44 css
drwxr-xr-x 2 t0 t0  4096 Nov 21 19:51 csv
drwxr-xr-x 2 t0 t0  4096 Nov 21 19:51 html
drwxr-xr-x 4 t0 t0  4096 Nov 21 18:44 icons
-rw-r--r-- 1 t0 t0    59 Nov 21 19:51 index.html
drwxr-xr-x 2 t0 t0  4096 Nov 21 19:51 js
$ ls -la render_test/html/
total 8
drwxr-xr-x 2 t0 t0 4096 Nov 21 19:51 .
drwxr-xr-x 8 t0 t0 4096 Nov 21 19:51 ..
$ ls -la render_test/csv/
total 8
drwxr-xr-x 2 t0 t0 4096 Nov 21 19:51 .
drwxr-xr-x 8 t0 t0 4096 Nov 21 19:51 ..
$ ls -la cache_neo4j
total 1748
drwxr-xr-x 2 t0 t0  12288 Nov 21 20:06 .
drwxr-xr-x 4 t0 t0  12288 Nov 21 19:51 ..
-rw-r--r-- 1 t0 t0 464323 Nov 21 19:51 test_anomaly_acl_1
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_can_read_gmsapassword_of_adm
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_can_read_laps
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_computers_admin_on_computers
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_computers_members_high_privilege
-rw-r--r-- 1 t0 t0   7864 Nov 21 19:51 test_computers_not_connected_since
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_cross_domain_domain_admins
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_da_to_da
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_dc_impersonation
-rw-r--r-- 1 t0 t0     83 Nov 21 19:51 test_dcsync_list
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_delete_orphans
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_del_fake_dc_admins
-rw-r--r-- 1 t0 t0    969 Nov 21 19:51 test_dom_admin_on_non_dc
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_domain_map_trust
-rw-r--r-- 1 t0 t0 186906 Nov 21 19:51 test_domain_OUs
-rw-r--r-- 1 t0 t0     33 Nov 21 19:51 test_domains
-rw-r--r-- 1 t0 t0   6252 Nov 21 19:51 test_dormant_accounts
-rw-r--r-- 1 t0 t0  15830 Nov 21 19:51 test_get_computers_linked_admin_group
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_get_count_of_member_admin_group
-rw-r--r-- 1 t0 t0 279564 Nov 21 19:51 test_get_empty_groups
-rw-r--r-- 1 t0 t0    266 Nov 21 19:51 test_get_empty_ous
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_get_groups_linked_admin_group
-rw-r--r-- 1 t0 t0  66959 Nov 21 19:51 test_get_users_direct_admin
-rw-r--r-- 1 t0 t0  14729 Nov 21 19:51 test_get_users_linked_admin_group
-rw-r--r-- 1 t0 t0    187 Nov 21 19:51 test_get_users_password_not_required
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_graph_rbcd
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_graph_rbcd_to_da
-rw-r--r-- 1 t0 t0     58 Nov 21 19:51 test_guest_accounts
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_has_sid_history
-rw-r--r-- 1 t0 t0    119 Nov 21 19:51 test_krb_pwd_last_change
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_nb_as-rep_roastable_accounts
-rw-r--r-- 1 t0 t0  15756 Nov 21 19:51 test_nb_computers
-rw-r--r-- 1 t0 t0  11256 Nov 21 19:51 test_nb_computers_laps
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_nb_computer_unconstrained_delegations
-rw-r--r-- 1 t0 t0   1681 Nov 21 19:51 test_nb_domain_admins
-rw-r--r-- 1 t0 t0     33 Nov 21 19:51 test_nb_domain_collected
-rw-r--r-- 1 t0 t0    304 Nov 21 19:51 test_nb_domain_controllers
-rw-r--r-- 1 t0 t0  10787 Nov 21 19:51 test_nb_enabled_accounts
-rw-r--r-- 1 t0 t0 126420 Nov 21 19:51 test_nb_groups
-rw-r--r-- 1 t0 t0    356 Nov 21 19:51 test_nb_kerberoastable_accounts
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_nb_user_password_cleartext
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_nb_users_unconstrained_delegations
-rw-r--r-- 1 t0 t0   1077 Nov 21 19:51 test_objects_admincount
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_objects_to_adcs
-rw-r--r-- 1 t0 t0   5704 Nov 21 19:51 test_objects_to_dcsync
-rw-r--r-- 1 t0 t0   4939 Nov 21 19:51 test_objects_to_domain_admin
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_objects_to_operators_member
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_objects_to_ou_handlers
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_objects_to_unconstrained_delegation
-rw-r--r-- 1 t0 t0  15783 Nov 21 19:51 test_os
-rw-r--r-- 1 t0 t0   8504 Nov 21 19:51 test_password_last_change
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_preparation_request_nodes
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_preparation_request_relations
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_pre_windows_2000_compatible_access_group
-rw-r--r-- 1 t0 t0   3475 Nov 21 19:51 test_primaryGroupID_lower_than_1000
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_rbcd
-rw-r--r-- 1 t0 t0    151 Nov 21 19:51 test_rdp_access
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_can_extract_dc_secrets
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_can_load_code
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_can_logon_dc
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_containsda
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_containsdc
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_da
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_dag
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_dagg
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_daggg
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_dagg_types
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_dag_types
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_da_types
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_dc
-rw-r--r-- 1 t0 t0    321 Nov 21 19:51 test_set_dcsync1
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_dcsync2
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_ghost_computer
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_gpo_links_count
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_gpos_has_links
-rw-r--r-- 1 t0 t0   1522 Nov 21 19:51 test_set_groups_direct_admin
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_groups_has_members
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_groups_indirect_admin_1
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_groups_indirect_admin_2
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_groups_indirect_admin_3
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_groups_indirect_admin_4
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_groups_members_count
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_is_adcs
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_is_adminsdholder
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_is_da_dc
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_is_dnsadmin
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_is_group_operator
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_is_operator_member
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_nonda
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_nondag
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_nondc
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_non_server
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_path_candidate
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_server
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_unconstrained_delegations
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_set_upper_domain_name
-rw-r--r-- 1 t0 t0    156 Nov 21 19:51 test_unpriviledged_users_with_admincount
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_unpriv_to_dnsadmins
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_unpriv_users_to_GPO_computer_enforced
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_unpriv_users_to_GPO_computer_not_enforced
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_unpriv_users_to_GPO_init
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_unpriv_users_to_GPO_user_enforced
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_unpriv_users_to_GPO_user_not_enforced
-rw-r--r-- 1 t0 t0   2925 Nov 21 19:51 test_user_password_never_expires
-rw-r--r-- 1 t0 t0   5863 Nov 21 19:51 test_users_admin_on_computers
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_users_admin_on_servers_1
-rw-r--r-- 1 t0 t0    421 Nov 21 19:51 test_users_admin_on_servers_2
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_users_constrained_delegations
-rw-r--r-- 1 t0 t0   1983 Nov 21 19:51 test_users_shadow_credentials
-rw-r--r-- 1 t0 t0  93439 Nov 21 19:51 test_users_shadow_credentials_to_non_admins
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_users_to_unconstrained_delegation
-rw-r--r-- 1 t0 t0    100 Nov 21 19:51 test_vuln_functional_level
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_vuln_permissions_adminsdholder
-rw-r--r-- 1 t0 t0      5 Nov 21 19:51 test_vuln_sidhistory_dangerous

Terminal Output

$ AD-miner -u neo4j -p bloodhound -cf test
[+]Base : 185 | Base : 2137 | Base : 217 | Base : 21 | Base : 1 | Base : 18 | Base : 42 | Relations : 30814
[1/118] [+]Requesting : Delete orphan objects that have no labels
[-]Done in 0.00 s - 0 objects
[2/118] [+]Requesting : Clean AD Miner custom attributes
[-]Done in 0.10 s - 0 objects
[3/118] [+]Requesting : Delete objects for which SID could not resolved
[!]{code: Neo.ClientError.Statement.SyntaxError} {message: The property existence syntax `... exists(variable.property)` is no longer supported. Please use `variable.property IS NOT NULL` instead. (line 1, column 22 (offset: 21))
"MATCH (n) WHERE (NOT EXISTS(n.domain) AND NOT (n:Domain)) OR NOT EXISTS(n.name) DETACH DELETE n"
                      ^}
[!]Traceback (most recent call last):
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/__main__.py", line 76, in populate_data_and_cache
    neo4j.process_request(neo4j, request_key)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/sources/modules/neo4j_class.py", line 286, in process_request
    result = self.writeRequest(self, request_key)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/sources/modules/neo4j_class.py", line 320, in simpleRequest
    result = tx.run(request["request"])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/transaction.py", line 156, in run
    result._tx_ready_run(query, parameters)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/result.py", line 120, in _tx_ready_run
    self._run(query, parameters, None, None, None, None)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/result.py", line 166, in _run
    self._attach()
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/result.py", line 274, in _attach
    self._connection.fetch_message()
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_common.py", line 180, in inner
    func(*args, **kwargs)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_bolt.py", line 658, in fetch_message
    res = self._process_message(tag, fields)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_bolt5.py", line 317, in _process_message
    response.on_failure(summary_metadata or {})
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_common.py", line 247, in on_failure
    raise Neo4jError.hydrate(**metadata)
neo4j.exceptions.CypherSyntaxError: {code: Neo.ClientError.Statement.SyntaxError} {message: The property existence syntax `... exists(variable.property)` is no longer supported. Please use `variable.property IS NOT NULL` instead. (line 1, column 22 (offset: 21))
"MATCH (n) WHERE (NOT EXISTS(n.domain) AND NOT (n:Domain)) OR NOT EXISTS(n.name) DETACH DELETE n"
                      ^}
[...]
[32/118] [+]Requesting : Set ou_candidate=TRUE to candidates eligible to shortestou to DA
[!]{code: Neo.ClientError.Statement.SyntaxError} {message: The property existence syntax `... exists(variable.property)` is no longer supported. Please use `variable.property IS NOT NULL` instead. (line 1, column 79 (offset: 78))
"MATCH (m) WHERE NOT m.name IS NULL AND ((m:Computer AND (m.is_dc=false OR NOT EXISTS(m.is_dc))) OR (m:User AND (m.is_da=false OR NOT EXISTS(m.is_da)))) SET m.ou_candidate=TRUE"
                                                                               ^}
[!]Traceback (most recent call last):
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/__main__.py", line 76, in populate_data_and_cache
    neo4j.process_request(neo4j, request_key)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/sources/modules/neo4j_class.py", line 286, in process_request
    result = self.writeRequest(self, request_key)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/sources/modules/neo4j_class.py", line 320, in simpleRequest
    result = tx.run(request["request"])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/transaction.py", line 156, in run
    result._tx_ready_run(query, parameters)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/result.py", line 120, in _tx_ready_run
    self._run(query, parameters, None, None, None, None)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/result.py", line 166, in _run
    self._attach()
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/result.py", line 274, in _attach
    self._connection.fetch_message()
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_common.py", line 180, in inner
    func(*args, **kwargs)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_bolt.py", line 658, in fetch_message
    res = self._process_message(tag, fields)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_bolt5.py", line 317, in _process_message
    response.on_failure(summary_metadata or {})
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_common.py", line 247, in on_failure
    raise Neo4jError.hydrate(**metadata)
neo4j.exceptions.CypherSyntaxError: {code: Neo.ClientError.Statement.SyntaxError} {message: The property existence syntax `... exists(variable.property)` is no longer supported. Please use `variable.property IS NOT NULL` instead. (line 1, column 79 (offset: 78))
"MATCH (m) WHERE NOT m.name IS NULL AND ((m:Computer AND (m.is_dc=false OR NOT EXISTS(m.is_dc))) OR (m:User AND (m.is_da=false OR NOT EXISTS(m.is_da)))) SET m.ou_candidate=TRUE"
                                                                               ^}
[...]
[104/118] [+]Requesting : anomaly_acl_2
[!]{code: Neo.ClientError.Statement.SyntaxError} {message: The property existence syntax `... exists(variable.property)` is no longer supported. Please use `variable.property IS NOT NULL` instead. (line 1, column 24 (offset: 23))
"MATCH (gg:Group) WHERE EXISTS(gg.members_count) with gg as g order by gg.members_count DESC MATCH (g)-[r2{isacl:true}]->(n) WHERE ((g.is_da IS NULL OR g.is_da=FALSE) AND (g.is_dc IS NULL OR g.is_dc=FALSE)) OR (NOT n.domain CONTAINS '.' + g.domain AND n.domain <> g.domain) RETURN g.members_count,n.name,g.name,type(r2),LABELS(g)[0] order by g.members_count DESC"
                        ^}
[!]Traceback (most recent call last):
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/__main__.py", line 76, in populate_data_and_cache
    neo4j.process_request(neo4j, request_key)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/sources/modules/neo4j_class.py", line 288, in process_request
    result = self.simpleRequest(self, request_key)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/sources/modules/neo4j_class.py", line 320, in simpleRequest
    result = tx.run(request["request"])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/transaction.py", line 156, in run
    result._tx_ready_run(query, parameters)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/result.py", line 120, in _tx_ready_run
    self._run(query, parameters, None, None, None, None)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/result.py", line 166, in _run
    self._attach()
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/result.py", line 274, in _attach
    self._connection.fetch_message()
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_common.py", line 180, in inner
    func(*args, **kwargs)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_bolt.py", line 658, in fetch_message
    res = self._process_message(tag, fields)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_bolt5.py", line 317, in _process_message
    response.on_failure(summary_metadata or {})
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_common.py", line 247, in on_failure
    raise Neo4jError.hydrate(**metadata)
neo4j.exceptions.CypherSyntaxError: {code: Neo.ClientError.Statement.SyntaxError} {message: The property existence syntax `... exists(variable.property)` is no longer supported. Please use `variable.property IS NOT NULL` instead. (line 1, column 24 (offset: 23))
"MATCH (gg:Group) WHERE EXISTS(gg.members_count) with gg as g order by gg.members_count DESC MATCH (g)-[r2{isacl:true}]->(n) WHERE ((g.is_da IS NULL OR g.is_da=FALSE) AND (g.is_dc IS NULL OR g.is_dc=FALSE)) OR (NOT n.domain CONTAINS '.' + g.domain AND n.domain <> g.domain) RETURN g.members_count,n.name,g.name,type(r2),LABELS(g)[0] order by g.members_count DESC"
                        ^}

[...]
[113/118] [+]Requesting : Users that are local admins cross-domain
[!]{code: Neo.ClientError.Statement.SyntaxError} {message: Aggregation column contains implicit grouping expressions. For example, in 'RETURN n.a, n.a + n.b + count(*)' the aggregation expression 'n.a + n.b + count(*)' includes the implicit grouping key 'n.b'. It may be possible to rewrite the query by extracting these grouping/aggregation expressions into a preceding WITH clause. Illegal expression(s): paths (line 1, column 382 (offset: 381))
"MATCH p1=(u{enabled:true})-[r:MemberOf*1..4]->(g:Group{is_admin:true})-[rr:AdminTo]->(c:Computer) WHERE c.ghost_computer IS NULL AND u.domain <> c.domain AND NOT c.domain CONTAINS u.domain WITH collect(distinct p1) as paths OPTIONAL MATCH q=(u{enabled:true})-[r:AdminTo]->(c:Computer) WHERE c.ghost_computer IS NULL AND u.domain <> c.domain AND NOT c.domain CONTAINS u.domain WITH paths + collect(distinct q) as allPaths UNWIND allPaths as p RETURN DISTINCT p"
                                                                                                                                                                                                                                                                                                                                                                                              ^}
[!]Traceback (most recent call last):
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/__main__.py", line 76, in populate_data_and_cache
    neo4j.process_request(neo4j, request_key)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/sources/modules/neo4j_class.py", line 288, in process_request
    result = self.simpleRequest(self, request_key)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/sources/modules/neo4j_class.py", line 312, in simpleRequest
    for record in tx.run(request["request"]):
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/transaction.py", line 156, in run
    result._tx_ready_run(query, parameters)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/result.py", line 120, in _tx_ready_run
    self._run(query, parameters, None, None, None, None)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/result.py", line 166, in _run
    self._attach()
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/work/result.py", line 274, in _attach
    self._connection.fetch_message()
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_common.py", line 180, in inner
    func(*args, **kwargs)
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_bolt.py", line 658, in fetch_message
    res = self._process_message(tag, fields)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_bolt5.py", line 317, in _process_message
    response.on_failure(summary_metadata or {})
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/neo4j/_sync/io/_common.py", line 247, in on_failure
    raise Neo4jError.hydrate(**metadata)
neo4j.exceptions.CypherSyntaxError: {code: Neo.ClientError.Statement.SyntaxError} {message: Aggregation column contains implicit grouping expressions. For example, in 'RETURN n.a, n.a + n.b + count(*)' the aggregation expression 'n.a + n.b + count(*)' includes the implicit grouping key 'n.b'. It may be possible to rewrite the query by extracting these grouping/aggregation expressions into a preceding WITH clause. Illegal expression(s): paths (line 1, column 382 (offset: 381))
"MATCH p1=(u{enabled:true})-[r:MemberOf*1..4]->(g:Group{is_admin:true})-[rr:AdminTo]->(c:Computer) WHERE c.ghost_computer IS NULL AND u.domain <> c.domain AND NOT c.domain CONTAINS u.domain WITH collect(distinct p1) as paths OPTIONAL MATCH q=(u{enabled:true})-[r:AdminTo]->(c:Computer) WHERE c.ghost_computer IS NULL AND u.domain <> c.domain AND NOT c.domain CONTAINS u.domain WITH paths + collect(distinct q) as allPaths UNWIND allPaths as p RETURN DISTINCT p"
                                                                                                                                                                                                                                                                                                                                                                                              ^}
[...]
[+]Requests finished !
[+]Computing domains objects
**Traceback (most recent call last):
  File "/home/t0/.local/bin/AD-miner", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/__main__.py", line 178, in main
    domains = Domains(arguments, neo4j)
              ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/t0/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/sources/modules/domains.py", line 147, in __init__
    self.cross_domain_local_admins_paths = neo4j.all_requests["cross_domain_local_admins"]["result"]
                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^
KeyError: 'result'**

Lines were no errors occurred are skipped.

System information

  • Fresh install of a Debian 12 VM
$ neo4j version
neo4j 5.13.0
# python3 --version
Python 3.11.2

TypeError - '>' not supported between instances of 'NoneType' and 'int'

Describe the bug
Upon executing the tool with default settings, I encountered a TypeError which prevented the correct generation of the /html/index.html file.
Terminal Output

Traceback (most recent call last):
  File "/home/capi/.local/bin/AD-miner", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/home/capi/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/__main__.py", line 162, in main
    rating_dic = rating(users, domains, computers, objects, arguments)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/capi/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/sources/modules/rating.py", line 165, in rating
    d[2 if users.number_group_ACL_anomaly > 0 else 5].append("group_anomaly_acl")
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: '>' not supported between instances of 'NoneType' and 'int'

Screenshots
imagen

System information

  • OS Windows 11 and WSL kali
  • Python version Python 3.11.5

Error in genDAPage `argument of type 'NoneType' is not iterable`

Describe the bug
I get the following error when generating the report pages:
AD-miner -c -cf Report -u $user -p $pw

Terminal Output

[+]Requests finished !
[+]Computing domains objects
[+]Split objects into types...
[+][Done]
[+]... from OUs
[+]... from GPOs
[+]... from groups
[+]... from OUs
[+]... from GPOs
[+]Generate paths to Kerberos Unconstrained Delegations
Traceback (most recent call last):
  File "/root/AD_Miner/.venv/bin/AD-miner", line 6, in <module>
    sys.exit(main())
             ^^^^^^
  File "/root/AD_Miner/ad_miner/__main__.py", line 183, in main
    domains = Domains(arguments, neo4j)
              ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/AD_Miner/ad_miner/sources/modules/domains.py", line 266, in __init__
    self.genDAPage()
  File "/root/AD_Miner/ad_miner/sources/modules/domains.py", line 448, in genDAPage
    if "Domain Admin" in da["admin type"]
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: argument of type 'NoneType' is not iterable

System information

  • Kali
  • Python 3.11.9

AD-Miner fails with an error when computing domain objects

Describe the bug
After processing the data from the neo4j db, AD-Miner fails with an error when computing domain objects

This is similar to #88, despite me having neo4j version 4 running.

Terminal Output

[+]Requests finished !
[+]Computing domains objects
Traceback (most recent call last):
  File "/root/.local/share/virtualenvs/ADMiner-hgMaw5Gu/bin/AD-miner", line 8, in <module>
    sys.exit(main())
  File "/root/.local/share/virtualenvs/ADMiner-hgMaw5Gu/lib/python3.10/site-packages/ad_miner/__main__.py", line 182, in main
    domains = Domains(arguments, neo4j)
  File "/root/.local/share/virtualenvs/ADMiner-hgMaw5Gu/lib/python3.10/site-packages/ad_miner/sources/modules/domains.py", line 169, in __init__
    self.compromise_paths_of_OUs = neo4j.all_requests["compromise_paths_of_OUs"][
KeyError: 'result'

Screenshots
image

System information

  • OS for AD-Miner: Linux kali 5.18.0-kali5-amd64 #1 SMP PREEMPT_DYNAMIC Debian 5.18.5-1kali6 (2022-07-07) x86_64 GNU/Linux
  • OS for BH and neo4j: Windows 10 21H2
  • Python 3.10.7
  • neo4j 4.4.14
  • BH 4.3.1 Legacy

Additional context
I ran the stuff twice. Once with directly collecting the data from the database and the 2nd time with the cached data.
Both times same error.

Ghost Domain Controllers

In the Domain Controllers view, ghost DCs should be highlighted following the ANSSI control point.

Suggestion:

  • ghost DC should be displayed first
  • ghost icon could be red to help identify inactive DC
  • Add a last_logon column

Main page access

Hi

How to have the main page (as in your github page) with :

  • Global risk
  • General statistics
  • Indicators of exposure breakdown
  • ...

Me, i launch a web server with python and i navigate in the differents pages :
python3 -m http.server 8080

Is it normal in my index.html there is just a redirection ?
My command :
AD-miner -c -cf company_name -u neo4j -p mypassword

Thank you

Josmeyr farmtech

Creating some helpful solution for the ever changing globalized world

Adding Azurehound data to bloodhound result in a crash of the tool

Describe the bug
After adding data dumped from Azurehound, relaunching the tool with no cache (fresh start) will result in the following error

Terminal Output

Traceback (most recent call last):
  File "/home/adrien/.local/bin/AD-miner", line 8, in <module>
    sys.exit(main())
  File "/home/adrien/.local/pipx/venvs/ad-miner/lib/python3.9/site-packages/ad_miner/__main__.py", line 186, in main
    azure = Azure(arguments, neo4j, domains)
  File "/home/adrien/.local/pipx/venvs/ad-miner/lib/python3.9/site-packages/ad_miner/sources/modules/azure.py", line 66, in __init__
    self.genAzureAdminsAndOnPrem()
  File "/home/adrien/.local/pipx/venvs/ad-miner/lib/python3.9/site-packages/ad_miner/sources/modules/azure.py", line 261, in genAzureAdminsAndOnPrem
    "Name": '<i class="bi bi-gem"></i> ' + user["Name"]
KeyError: 'Name'

Improvable path to Domain Admins?

I just tested AD-miner on my personal lab and found out that there may be an incomplete/incorrect short-cut.

Lets say we own the walter.white user which has a GenericAll on the Users container as shown below:
da

According to AD-miner, we could get to the Domain Admins group, which I think is not feasable (even though it's a member of the container). The exploitation steps could be as below:

  1. Change the inheritance in the Users container to "This object and all descendant objects" (we assume it previously was "This object only").
  2. The difficulty starts from here: In an ideal world we could add ourselves to the Domain Admins group. However, since this group has by default AdminCount=1, it won't inherit ACEs from their parents containers or OU ; so we can't. There are some groups that can be abused to become domain admin such as the Cert Publishers group under some circumstances or maybe the Group Policy Creator Owners group (I believe, I haven't tested).

My take on this: If my analysis is right, then I believe this path should not be so straightforward. Having a GenericAll privilege on the Users container means we can reach some Tier-0 groups that are not protected by this AdminCount=1. So, I think it may be better to either point out these groups directly, or create a transitive link from these groups to the Domain Admins group if there's indeed a path.

References:


Edit: I just realized it was probably due to how BloodHound works, rather than AD-miner. I think it's best to close the issue then ๐Ÿ˜…

analysis never finishes

Describe the bug
ad-miner -c -cf bla -u neo4j -p secret never finishes despite running for a few days now

Terminal Output
[+]Connected to database
[1/119] [+]Requesting : Delete orphan objects that have no labels
[-]Done in 0.61 s - 0 objects
[2/119] [+]Requesting : Clean AD Miner custom attributes
[-]Done in 0.23 s - 0 objects
[3/119] [+]Requesting : Delete objects for which SID could not resolved
[-]Done in 0.13 s - 0 objects
[4/119] [+]Requesting : Set domain names to upper case when not the case
[-]Done in 0.07 s - 0 objects
[5/119] [+]Requesting : Clean AD Miner custom relations
[-]Done in 0.02 s - 0 objects
[6/119] [+]Requesting : Set is_server=TRUE to computers for which operatingsystem contains Server)
[-]Done in 0.07 s - 0 objects
[7/119] [+]Requesting : Set is_server=FALSE to other computers )
[-]Done in 0.10 s - 0 objects
[8/119] [+]Requesting : Set dc=TRUE to computers that are domain controllers)
[-]Done in 0.04 s - 0 objects
[9/119] [+]Requesting : Set dc=FALSE to computers that are not domain controllers)
[-]Done in 0.11 s - 0 objects
[10/119] [+]Requesting : ADD CanExtractDCSecrets relation from BACKUP OPERATORS OR SERVER OPERATORS groups to DCs of same domain
[-]Done in 0.07 s - 0 objects
[11/119] [+]Requesting : ADD UnconstrainedDelegations relation from objects with KUD to the corresponding domain
[-]Done in 0.09 s - 0 objects
[12/119] [+]Requesting : Set is_adminsdholder to Container with AdminSDHOLDER in name
[-]Done in 0.05 s - 0 objects
[13/119] [+]Requesting : Set is_dnsadmin to Group with DNSAdmins in name
[-]Done in 0.03 s - 0 objects
[14/119] [+]Requesting : ADD CanLoadCode relation from PRINT OPERATORS groups to DCs of same domain
[-]Done in 0.06 s - 0 objects
[15/119] [+]Requesting : ADD CanLogOnLocallyOnDC relation from ACCOUNT OPERATORS groups to DCs of same domain
[-]Done in 0.07 s - 0 objects
[16/119] [+]Requesting : Set da=TRUE to users that are domain admins or administrators or enterprise admin
[-]Done in 0.05 s - 0 objects
[17/119] [+]Requesting : Set the da type (domain, enterprise, key or builtin)
[-]Done in 0.12 s - 0 objects
[18/119] [+]Requesting : Set da=TRUE to groups that are domain admins or administrators or enterprise admin
[-]Done in 0.05 s - 0 objects
[19/119] [20/119] [+]Requesting : Set da=TRUE to groups that are domain admins or administrators or enterprise admin
[-]Done in 0.04 s - 0 objects
[21/119] [22/119] [+]Requesting : Set dag=TRUE to the exact domain admin group (end with 512)
[-]Done in 0.03 s - 0 objects
[23/119] [+]Requesting : Set is_da=FALSE to all objects that do not have is_da=TRUE
[-]Done in 0.42 s - 0 objects
[24/119] [+]Requesting : Set is_dag=FALSE to all objects that do not have is_da=TRUE
[-]Done in 0.39 s - 0 objects
[25/119] [+]Requesting : Delete AdminTo edges from non-DA to DC
[-]Done in 0.02 s - 0 objects
[26/119] [+]Requesting : Set is_group_operator to Operator Groups (cf: ACCOUNT OPERATORS, SERVER OPERATORS, BACKUP OPERATORS, PRINT OPERATORS)
[-]Done in 0.06 s - 0 objects
[27/119] [+]Requesting : Set is_operator_member to objects member of Operator Groups (cf: ACCOUNT OPERATORS, SERVER OPERATORS, BACKUP OPERATORS, PRINT OPERATORS)
[-]Done in 0.09 s - 0 objects
[28/119] [+]Requesting : Set dcsync=TRUE to nodes that can DCSync (GetChanges/GetChangesAll)
[-]Done in 2.30 s - 5 objects
[29/119] [+]Requesting : Set dcsync=TRUE to nodes that can DCSync (GenericAll/AllExtendedRights)
[-]Done in 2.40 s - 837 objects
[30/119] [+]Requesting : Get list of objects that can DCsync (and should probably not be to)
[-]Done in 0.07 s - 262 objects
[31/119] [+]Requesting : Set path_candidate=TRUE to candidates eligible to shortestPath to DA
[-]Done in 0.49 s - 0 objects
[32/119] [+]Requesting : Set ou_candidate=TRUE to candidates eligible to shortestou to DA
[-]Done in 0.40 s - 0 objects
[33/119] [+]Requesting : Set contains_da_dc=TRUE to all objects that contains a domain administrator
[-]Done in 0.05 s - 0 objects
[34/119] [+]Requesting : Set contains_da_dc=TRUE to all objects that contains a domain controller
[-]Done in 0.06 s - 0 objects
[35/119] [+]Requesting : Set is_da_dc=TRUE to all objects that are domain controller or domain admins
[-]Done in 0.10 s - 0 objects
[36/119] [+]Requesting : Set members_count to groups (recursivity = 5)
scope size : 15688 | nb chunks : 36 | nb cores : 36
100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 36/36 [34:24<00:00, 57.34s/it]
[-]Done in 34.41 m - 0 objects
[37/119] [+]Requesting : Set has_member=True to groups with member, else false
[-]Done in 0.16 s - 0 objects
[38/119] [+]Requesting : Set the number of machines where Computers, Users, or Groups are admin (if too long, set recursivity to 3 into the query)
[-]Done in 12.65 s - 0 objects
[39/119] [+]Requesting : Set the count of links/object where the GPO is applied
[-]Done in 0.06 s - 0 objects
[40/119] [+]Requesting : Set has_links=True to GPOs with links, else false
[-]Done in 0.03 s - 0 objects
[41/119] [+]Requesting : Set is_adcs to ADCS servers
[-]Done in 0.04 s - 1 objects
[42/119] [+]Requesting : Set groups which are direct admins of computers
[-]Done in 0.12 s - 133 objects
[43/119] [+]Requesting : 1 - Set groups which are indirect admins of computers, ie. admins of admin groups (see precedent request)
[-]Done in 0.07 s - 47 objects
[44/119] [+]Requesting : 2 - Set groups which are indirect admins of computers, ie. admins of admin groups (see precedent request)
[-]Done in 0.03 s - 0 objects
[45/119] [+]Requesting : 3 - Set groups which are indirect admins of computers, ie. admins of admin groups (see precedent request)
[-]Done in 0.02 s - 0 objects
[46/119] [+]Requesting : 4 - Set groups which are indirect admins of computers, ie. admins of admin groups (see precedent request)
[-]Done in 0.02 s - 0 objects
[47/119] [+]Requesting : Count number of domains collected
[-]Done in 0.02 s - 1 objects
[48/119] [+]Requesting : Count number of users in group
[-]Done in 0.10 s - 0 objects
[49/119] [+]Requesting : Returns all users member of an admin group
[-]Done in 5.28 s - 16067 objects
[50/119] [+]Requesting : Returns all groups member of an admin group
[-]Done in 0.10 s - 170 objects
[51/119] [+]Requesting : Returns all computers administrated by an admin group
[-]Done in 8.73 s - 27799 objects
[52/119] [+]Requesting : Return direct admin users
[-]Done in 0.24 s - 291 objects
[53/119] [+]Requesting : Set ghost_computer=TRUE to computers that did not login for more than 90 days
[-]Done in 0.12 s - 0 objects
[54/119] [+]Requesting : List of domains
[-]Done in 0.02 s - 1 objects
[55/119] [+]Requesting : Number of domain controllers
[-]Done in 0.03 s - 13 objects
[56/119] [+]Requesting : Domain Organisational Units
[-]Done in 1.43 s - 48397 objects
[57/119] [+]Requesting : Non privileged users that can impersonate privileged users
scope size : 14680 | nb chunks : 36 | nb cores : 36
100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 36/36 [00:10<00:00, 3.56it/s]
[-]Done in 10.42 s - 1872 objects
[58/119] [+]Requesting : Non privileged users that can be impersonated by non privileged users
scope size : 15678 | nb chunks : 36 | nb cores : 36
100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 36/36 [19:31<00:00, 32.54s/it]
[-]Done in 19.57 m - 352944 objects
[59/119] [+]Requesting : Number of domain accounts
[-]Done in 0.56 s - 19608 objects
[60/119] [+]Requesting : Number of domain accounts enabled
[-]Done in 0.58 s - 14692 objects
[61/119] [+]Requesting : Number of domain accounts disabled
[-]Done in 0.15 s - 4915 objects
[62/119] [+]Requesting : Number of groups
[-]Done in 0.65 s - 15688 objects
[63/119] [+]Requesting : Number of computers
[-]Done in 0.51 s - 12011 objects
[64/119] [+]Requesting : Computers not connected since
[-]Done in 0.46 s - 12011 objects
[65/119] [+]Requesting : Number of domain admin accounts
[-]Done in 0.11 s - 12 objects
[66/119] [+]Requesting : Number of OS
[-]Done in 0.49 s - 10630 objects
[67/119] [+]Requesting : Kerberos password last change in days
[-]Done in 0.03 s - 1 objects
[68/119] [+]Requesting : Number of Kerberoastable accounts
[-]Done in 0.07 s - 111 objects
[69/119] [+]Requesting : Number of AS-REP Roastable accounts
[-]Done in 0.04 s - 0 objects
[70/119] [+]Requesting : Number of machines with unconstrained delegations
[-]Done in 0.05 s - 4 objects
[71/119] [+]Requesting : Number of users with unconstrained delegations
[-]Done in 0.05 s - 7 objects
[72/119] [+]Requesting : Number of users with constrained delegations
[-]Done in 0.03 s - 0 objects
[73/119] [+]Requesting : Number of enabled and never used accounts
[-]Done in 0.16 s - 3685 objects
[74/119] [+]Requesting : Dormant accounts
[-]Done in 0.30 s - 6004 objects
[75/119] [+]Requesting : Password last change in days
[-]Done in 0.65 s - 14692 objects
[76/119] [+]Requesting : Number of accounts where password cleartext password is populated
[-]Done in 0.04 s - 0 objects
[77/119] [+]Requesting : Number of accounts where password is not required
[-]Done in 0.08 s - 1 objects
[78/119] [+]Requesting : Number of sleeping accounts per domain
[-]Done in 0.04 s - 1 objects
[79/119] [+]Requesting : N objects have AdminSDHolder
[-]Done in 0.11 s - 283 objects
[80/119] [+]Requesting : Last logon in days
[-]Done in 0.57 s - 14692 objects
[81/119] [+]Requesting : Password never expired
[-]Done in 0.13 s - 1592 objects
[82/119] [+]Requesting : Domain accounts breakdown
[-]Done in 0.08 s - 1 objects
[83/119] [+]Requesting : Domain computers breakdown
[-]Done in 0.07 s - 1 objects
[84/119] [+]Requesting : High privilege group computer member
[-]Done in 0.35 s - 0 objects
[85/119] [+]Requesting : Objects with path to DA
scope size : 44579 | nb chunks : 36 | nb cores : 36
100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 36/36 [00:41<00:00, 1.14s/it]
[-]Done in 41.55 s - 16163 objects
[86/119] [+]Requesting : Objects with path to ADCS servers
scope size : 44579 | nb chunks : 36 | nb cores : 36
100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 36/36 [00:01<00:00, 19.81it/s]
[-]Done in 2.11 s - 526 objects
[87/119] [+]Requesting : Users admin on machines
[-]Done in 12.32 s - 335624 objects
[88/119] [+]Requesting : Users admin on servers nยฐ1
scope size : 14680 | nb chunks : 36 | nb cores : 36
100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 36/36 [00:07<00:00, 4.73it/s]
[-]Done in 7.91 s - 14680 objects
[89/119] [+]Requesting : Users admin on servers nยฐ2
scope size : 14680 | nb chunks : 36 | nb cores : 36
100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 36/36 [00:01<00:00, 25.77it/s]
[-]Done in 1.62 s - 14680 objects
[90/119] [+]Requesting : Number of computers admin of computers
[-]Done in 0.34 s - 464 objects
[91/119] [+]Requesting : Domain map trust
[-]Done in 0.03 s - 0 objects
[92/119] [+]Requesting : Object with path to non-DC computers with unconstrained delegations
scope size : 44579 | nb chunks : 36 | nb cores : 36
100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 36/36 [00:46<00:00, 1.30s/it]
[-]Done in 47.84 s - 64654 objects
[93/119] [+]Requesting : Objects with paths to users that have unconstrained delegations
scope size : 44579 | nb chunks : 36 | nb cores : 36
100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 36/36 [01:18<00:00, 2.19s/it]
[-]Done in 1.32 m - 1841 objects
[94/119] [+]Requesting : Number of computers with laps
[-]Done in 0.45 s - 11094 objects
[95/119] [+]Requesting : Objects allowed to read LAPS
[-]Done in 19.36 s - 462 objects
[96/119] [+]Requesting : Objects to dcsync
scope size : 44343 | nb chunks : 36 | nb cores : 36
100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 36/36 [22:01<00:00, 36.70s/it]
[-]Done in 22.97 m - 4172874 objects
[97/119] [+]Requesting : Domain admin with session on non DC computers
[-]Done in 0.05 s - 3 objects
[98/119] [+]Requesting : Unprivileged users with path to DNSAdmins
scope size : 14680 | nb chunks : 36 | nb cores : 36
100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 36/36 [00:09<00:00, 3.65it/s]
[-]Done in 10.08 s - 1 objects
[99/119] [+]Requesting : Users with RDP-access to Computers
[-]Done in 20.46 s - 622860 objects
[100/119] [+]Requesting : Non-domain admins that can directly or indirectly impersonate a Domain Controller
[-]Done in 2.95 s - 13 objects
[101/119] [+]Requesting : RBCD attacks
scope size : 14680 | nb chunks : 36 | nb cores : 36
100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 36/36 [00:16<00:00, 2.24it/s]
[-]Done in 17.49 s - 565395 objects
[102/119] [+]Requesting : Builds RBCD attack path graph and sets is_rbcd_target attribute

System information

  • OS: Windows 10
  • Python version: 3.10.11

Additional context
it happily ate all 36 cores in the early analysis, but now nothing has happened for quite a while, in the order of 2 days. The ad-miner.exe process uses 0 cpu and 500k memory.

neo4j.exceptions.CypherSyntaxError: {code: Neo.ClientError.Statement.SyntaxError} {message: The property existence syntax `... exists(variable.property)` is no longer supported. Please use `variable.property IS NOT NULL` instead.

Neo4j Version 1.5.8 (1.5.8.105)
Collected with bloodhound.py

AD-miner -c -cf My_Report -u neo4j -p password -b bolt://localhost:7687
Traceback (most recent call last):
  File "/opt/homebrew/bin/AD-miner", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/opt/homebrew/lib/python3.12/site-packages/ad_miner/__main__.py", line 144, in main
    extract_date, total_objects, number_relations, boolean_azure = pre_request(arguments)
                                                                   ^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.12/site-packages/ad_miner/sources/modules/neo4j_class.py", line 90, in pre_request
    for record in tx.run(
                  ^^^^^^^
  File "/opt/homebrew/lib/python3.12/site-packages/neo4j/_sync/work/transaction.py", line 156, in run
    result._tx_ready_run(query, parameters)
  File "/opt/homebrew/lib/python3.12/site-packages/neo4j/_sync/work/result.py", line 120, in _tx_ready_run
    self._run(query, parameters, None, None, None, None)
  File "/opt/homebrew/lib/python3.12/site-packages/neo4j/_sync/work/result.py", line 166, in _run
    self._attach()
  File "/opt/homebrew/lib/python3.12/site-packages/neo4j/_sync/work/result.py", line 274, in _attach
    self._connection.fetch_message()
  File "/opt/homebrew/lib/python3.12/site-packages/neo4j/_sync/io/_common.py", line 180, in inner
    func(*args, **kwargs)
  File "/opt/homebrew/lib/python3.12/site-packages/neo4j/_sync/io/_bolt.py", line 658, in fetch_message
    res = self._process_message(tag, fields)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.12/site-packages/neo4j/_sync/io/_bolt5.py", line 317, in _process_message
    response.on_failure(summary_metadata or {})
  File "/opt/homebrew/lib/python3.12/site-packages/neo4j/_sync/io/_common.py", line 247, in on_failure
    raise Neo4jError.hydrate(**metadata)
neo4j.exceptions.CypherSyntaxError: {code: Neo.ClientError.Statement.SyntaxError} {message: The property existence syntax `... exists(variable.property)` is no longer supported. Please use `variable.property IS NOT NULL` instead. (line 1, column 17 (offset: 16))
"MATCH (n) WHERE EXISTS(n.tenantid) return n LIMIT 1"
                 ^}

no output in output folder

After running it I end up with an empty html folder.
The index.html is also non-functional.

Domain: TREE.DOMAIN.COM.PE

Error when all 119 checks are finished:

Traceback (most recent call last):
File "/home/pentest/.local/bin/AD-miner", line 8, in
sys.exit(main())
File "/home/pentest/.local/pipx/venvs/ad-miner/lib/python3.10/site-packages/ad_miner/main.py", line 155, in main
domains = Domains(arguments, neo4j)
File "/home/pentest/.local/pipx/venvs/ad-miner/lib/python3.10/site-packages/ad_miner/sources/modules/domains.py", line 222, in init
self.generatePathToOUHandlers(self)
File "/home/pentest/.local/pipx/venvs/ad-miner/lib/python3.10/site-packages/ad_miner/sources/modules/domains.py", line 1582, in generatePathToOUHandlers
self.paths_to_ou_handlers[path.nodes[-1].domain].append(path)
KeyError: 'TREE.DOMAIN.COM.PE'

AD Miner install in Windows 10 via pipx drops error (Python 3.12.0)

I just ran it from cmdline as shown in README and got this error: "module 'pkgutil' has no attribute 'ImpImporter'". Please help if possible.

pipx install 'git+https://github.com/Mazars-Tech/AD_Miner.git'
Fatal error from pip prevented installation. Full pip output in file:
    C:\Users\user\.local\pipx\logs\cmd_2023-10-03_12.07.56_pip_errors.log

pip seemed to fail to build package:
    neo4j==5.6.0

Some possibly relevant errors from pip install:
    error: subprocess-exited-with-error
    AttributeError: module 'pkgutil' has no attribute 'ImpImporter'. Did you mean: 'zipimporter'?

Error installing AD_Miner from spec 'git+https://github.com/Mazars-Tech/AD_Miner.git'.

rendered html pages with a '/' in name fail to render

I run AD_Miner on Windows and everything works, except i got this error and the app stops completely

description: error while running AD_Miner:

[+]Requests finished !
[+]Computing domains objects
Traceback (most recent call last):
  File "C:\Program Files\Python310\lib\runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Program Files\Python310\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Program Files\Python310\scripts\AD-miner.exe\__main__.py", line 7, in <module>
  File "C:\Program Files\Python310\lib\site-packages\ad_miner\__main__.py", line 182, in main
    domains = Domains(arguments, neo4j)
  File "C:\Program Files\Python310\lib\site-packages\ad_miner\sources\modules\domains.py", line 255, in __init__
    self.generatePathToOUHandlers(self)
  File "C:\Program Files\Python310\lib\site-packages\ad_miner\sources\modules\domains.py", line 1463, in generatePathToOUHandlers
    inbound_list_page.render()
  File "C:\Program Files\Python310\lib\site-packages\ad_miner\sources\modules\page_class.py", line 38, in render
    with open(
FileNotFoundError: [Errno 2] No such file or directory: './render_test/html/path_objects_to_ou_handlers_inbound_list_WINDOWS 10/[email protected]'

I changed the source of page_class.py on line 39 to
"./render_%s/html/%s" % (self.render_prefix, (self.name.replace(sep, '_')).replace('/', '-')), "w", encoding='utf-8'

this will replace the '/' with '-' in the title and the code runs successfully now..
not sure if this fix is handled correctly, but it works for me

Issue when generate report

Describe the bug
il try generate default report "D-miner -c -cf My_Report -u neo4j -p *********"
And met some issue.....

Terminal Output

[1/111] [+]From cache : Delete orphan objects that have no labels - 0 objects
[2/111] [+]From cache : Clean AD Miner custom attributes - 0 objects
[3/111] [+]From cache : Delete objects for which SID could not resolved - 0 objects
[4/111] [+]From cache : Set domain names to upper case when not the case - 0 objects
[5/111] [+]From cache : Clean AD Miner custom relations - 0 objects
[6/111] [+]From cache : Set is_server=TRUE to computers for which operatingsystem contains Server) - 0 objects
[7/111] [+]From cache : Set is_server=FALSE to other computers ) - 0 objects
[8/111] [+]From cache : Set dc=TRUE to computers that are domain controllers) - 0 objects
[9/111] [+]From cache : Set dc=FALSE to computers that are not domain controllers) - 0 objects
[10/111] [+]From cache : ADD CanExtractDCSecrets relation from BACKUP OPERATORS OR SERVER OPERATORS groups to DCs of same domain - 0 objects
[11/111] [+]From cache : ADD UnconstrainedDelegations relation from objects with KUD to the corresponding domain - 0 objects
[12/111] [+]From cache : Set is_adminsdholder to Container with AdminSDHOLDER in name - 0 objects
[13/111] [+]From cache : Set is_dnsadmin to Group with DNSAdmins in name - 0 objects
[14/111] [+]From cache : ADD CanLoadCode relation from PRINT OPERATORS groups to DCs of same domain - 0 objects
[15/111] [+]From cache : ADD CanLogOnLocallyOnDC relation from ACCOUNT OPERATORS groups to DCs of same domain - 0 objects
[16/111] [+]From cache : Set da=TRUE to users that are domain admins or administrators or enterprise admin - 0 objects
[17/111] [+]From cache : Set the da type (domain, enterprise, key or builtin) - 0 objects
[18/111] [+]From cache : Set da=TRUE to groups that are domain admins or administrators or enterprise admin - 0 objects
[19/111] [+]From cache : Set the da type (domain, enterprise, key or builtin) - 0 objects
[20/111] [+]From cache : Set da=TRUE to groups that are domain admins or administrators or enterprise admin - 0 objects
[21/111] [+]From cache : Set the da type (domain, enterprise, key or builtin) - 0 objects
[22/111] [+]From cache : Set dag=TRUE to the exact domain admin group (end with 512) - 0 objects
[23/111] [+]From cache : Set is_da=FALSE to all objects that do not have is_da=TRUE - 0 objects
[24/111] [+]From cache : Set is_dag=FALSE to all objects that do not have is_da=TRUE - 0 objects
[25/111] [+]From cache : Delete AdminTo edges from non-DA to DC - 0 objects
[26/111] [+]From cache : Set is_group_operator to Operator Groups (cf: ACCOUNT OPERATORS, SERVER OPERATORS, BACKUP OPERATORS, PRINT OPERATORS) - 0 objects
[27/111] [+]From cache : Set is_operator_member to objects member of Operator Groups (cf: ACCOUNT OPERATORS, SERVER OPERATORS, BACKUP OPERATORS, PRINT OPERATORS) - 0 objects
[28/111] [+]From cache : Set dcsync=TRUE to nodes that can DCSync (GetChanges/GetChangesAll) - 0 objects
[29/111] [+]From cache : Set dcsync=TRUE to nodes that can DCSync (GenericAll/AllExtendedRights) - 0 objects
[30/111] [+]From cache : Get list of objects that can DCsync (and should probably not be to) - 0 objects
[31/111] [+]From cache : Set path_candidate=TRUE to candidates eligible to shortestPath to DA - 0 objects
[32/111] [+]From cache : Set ou_candidate=TRUE to candidates eligible to shortestou to DA - 0 objects
[33/111] [+]From cache : Set contains_da_dc=TRUE to all objects that contains a domain administrator - 0 objects
[34/111] [+]From cache : Set contains_da_dc=TRUE to all objects that contains a domain controller - 0 objects
[35/111] [+]From cache : Set is_da_dc=TRUE to all objects that are domain controller or domain admins - 0 objects
[36/111] [+]From cache : Set members_count to groups (recursivity = 5) - 0 objects
[37/111] [+]From cache : Set has_member=True to groups with member, else false  - 0 objects
[38/111] [+]From cache : Set the count of links/object where the GPO is applied - 0 objects
[39/111] [+]From cache : Set has_links=True to GPOs with links, else false  - 0 objects
[40/111] [+]From cache : Set is_adcs to ADCS servers - 0 objects
[41/111] [+]From cache : Set groups which are direct admins of computers - 0 objects
[42/111] [+]From cache : 1 - Set groups which are indirect admins of computers, ie. admins of admin groups (see precedent request) - 0 objects
[43/111] [+]From cache : 2 - Set groups which are indirect admins of computers, ie. admins of admin groups (see precedent request) - 0 objects
[44/111] [+]From cache : 3 - Set groups which are indirect admins of computers, ie. admins of admin groups (see precedent request) - 0 objects
[45/111] [+]From cache : 4 - Set groups which are indirect admins of computers, ie. admins of admin groups (see precedent request) - 0 objects
[46/111] [+]From cache : Count number of domains collected - 0 objects
[47/111] [+]From cache : Count number of users in group - 0 objects
[48/111] [+]From cache : Returns all users member of an admin group - 0 objects
[49/111] [+]From cache : Returns all groups member of an admin group - 0 objects
[50/111] [+]From cache : Returns all computers administrated by an admin group - 0 objects
[51/111] [+]From cache : Return direct admin users - 0 objects
[52/111] [+]From cache : Set ghost_computer=TRUE to computers that did not login for more than 90 days - 0 objects
[53/111] [+]From cache : List of domains - 0 objects
[54/111] [+]From cache : Number of domain controllers - 0 objects
[55/111] [+]From cache : Domain Organisational Units - 0 objects
[56/111] [+]From cache : Non privileged users that can impersonate privileged users - 0 objects
[57/111] [+]Requesting : Non privileged users that can be impersonated by non privileged users
[!]list index out of range
[!]Traceback (most recent call last):
  File "/home/kali/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/__main__.py", line 76, in populate_data_and_cache
    neo4j.process_request(neo4j, request_key)
  File "/home/kali/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/sources/modules/neo4j_class.py", line 233, in process_request
    scopeSize = tx.run(scopeQuery).value()[0]
                ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^
IndexError: list index out of range

[58/111] [+]From cache : Number of domain accounts enabled - 0 objects
[59/111] [+]From cache : Number of groups - 0 objects
[60/111] [+]From cache : Number of computers - 0 objects
[61/111] [+]From cache : Computers not connected since - 0 objects
[62/111] [+]From cache : Number of domain admin accounts - 0 objects
[63/111] [+]From cache : Number of OS - 0 objects
[64/111] [+]From cache : Kerberos password last change in days - 0 objects
[65/111] [+]From cache : Number of Kerberoastable accounts - 0 objects
[66/111] [+]From cache : Number of AS-REP Roastable accounts - 0 objects
[67/111] [+]From cache : Number of machines with unconstrained delegations - 0 objects
[68/111] [+]From cache : Number of users with unconstrained delegations - 0 objects
[69/111] [+]From cache : Number of users with constrained delegations - 0 objects
[70/111] [+]From cache : Dormant accounts - 0 objects
[71/111] [+]From cache : Password last change in days - 0 objects
[72/111] [+]From cache : Number of accounts where password cleartext password is populated - 0 objects
[73/111] [+]From cache : Number of accounts where password is not required - 0 objects
[74/111] [+]From cache : N objects have AdminSDHolder - 0 objects
[75/111] [+]From cache : Password never expired - 0 objects
[76/111] [+]From cache : High privilege group computer member - 0 objects
[77/111] [+]From cache : Objects with path to DA - 0 objects
[78/111] [+]From cache : Objects with path to ADCS servers - 0 objects
[79/111] [+]From cache : Users admin on machines - 0 objects
[80/111] [+]From cache : Users admin on servers nยฐ1 - 0 objects
[81/111] [+]From cache : Users admin on servers nยฐ2 - 0 objects
[82/111] [+]From cache : Number of computers admin of computers - 0 objects
[83/111] [+]From cache : Domain map trust - 0 objects
[84/111] [+]From cache : Object with path to non-DC computers with unconstrained delegations  - 0 objects
[85/111] [+]From cache : Objects with paths to users that have unconstrained delegations  - 0 objects
[86/111] [+]From cache : Number of computers with laps - 0 objects
[87/111] [+]From cache : Objects allowed to read LAPS - 0 objects
[88/111] [+]From cache : Objects to dcsync - 0 objects
[89/111] [+]From cache : Domain admin with session on non DC computers - 0 objects
[90/111] [+]From cache : Unprivileged users with path to DNSAdmins - 0 objects
[91/111] [+]From cache : Users with RDP-access to Computers  - 0 objects
[92/111] [+]From cache : Non-domain admins that can directly or indirectly impersonate a Domain Controller  - 0 objects
[93/111] [+]From cache : RBCD attacks - 0 objects
[94/111] [+]From cache : Builds RBCD attack path graph and sets is_rbcd_target attribute  - 0 objects
[95/111] [+]From cache : Builds RBCD targets to DA paths - 0 objects
[96/111] [+]From cache : paths to objects that can link a gpo on an OU - 0 objects
[97/111] [+]From cache : Insufficient forest and domains functional levels. According to ANSSI (on a scale from 1 to 5, 5 being the better): the security level is at 1 if functional level (FL) <= Windows 2008 R2, at 3 if FL <= Windows 2012R2, at 4 if FL <= Windows 2016 / 2019 / 2022. - 0 objects
[98/111] [+]From cache : Accounts or groups with unexpected SID history - 0 objects
[99/111] [+]From cache : Objects allowed to read the GMSA of objects with admincount=True - 0 objects
[100/111] [+]From cache : Unprivileged users with path to an Operator Member - 0 objects
[101/111] [+]From cache : Dangerous permissions on the adminSDHolder object - 0 objects
[102/111] [+]From cache : Paths between two domain admins belonging to different domains - 0 objects
[103/111] [+]From cache : group_anomaly_acl - 0 objects
[104/111] [+]From cache : Returns empty groups - 0 objects
[105/111] [+]From cache : Returns empty ous - 0 objects
[106/111] [+]From cache : Objects that have a SID History - 0 objects
[107/111] [+]From cache : Initialization request for GPOs [WARNING: If this query is too slow, you can use --gpo_low] - 0 objects
[108/111] [+]From cache : Compromisable GPOs to users (enforced) - 0 objects
[109/111] [+]From cache : Compromisable GPOs to users (not enforced) - 0 objects
[110/111] [+]From cache : Compromisable GPOs to computers (enforced) - 0 objects
[111/111] [+]From cache : Compromisable GPOs to computers (not enforced) - 0 objects
[+]Requests finished !
[+]Computing domains objects
[+]Generate paths to objects that can GPLink GPOs on OUs
[+]Split objects into types...
[+][Done]
[+]Generate paths to unconstrained delegations
[+]Generating path to unconstrained 2nd phase ????
Traceback (most recent call last):
  File "/home/kali/.local/bin/AD-miner", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/home/kali/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/__main__.py", line 171, in main
    domains = Domains(arguments, neo4j)
              ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/kali/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/sources/modules/domains.py", line 243, in __init__
    self.genDAPage()
  File "/home/kali/.local/pipx/venvs/ad-miner/lib/python3.11/site-packages/ad_miner/sources/modules/domains.py", line 390, in genDAPage
    self.max_da_per_domain = max(count_da.values())
                             ^^^^^^^^^^^^^^^^^^^^^^
ValueError: max() arg is an empty sequence

Screenshots
image
System information

  • OS
    NAME="Kali GNU/Linux"
    VERSION_ID="2023.3"
    VERSION="2023.3"
    VERSION_CODENAME=kali-rolling

  • Python version 3.11.5

cards.html missing

Describe the bug
run analysis, view report, click indicators of exposure breakdown, "Full IOE list" in the bottom links to cards.html which is nowhere to be seen

System information

  • Python version: 3.10.11
  • Browser: edge

Url encoding breaks links with parameters

Describe the bug
For links using parameters, the url encoding breaks the parameter parsing and thus returns a 404 error.

Additional context
It affects all page using parameters. For example : html/users_to_computers.html%3Fnode%3D4285
which comes from : html/group_anomaly_acl_details_<object_name>.html

Bug - Split objects into types

[144/145] [+]From cache : Paths between two global admins belonging to different tenants - 0 objects
[145/145] [+]From cache : Paths between tenants admin and domain admins - 0 objects
[+]Requests finished !
[+]Computing domains objects
[+]Generate paths to objects that can GPLink GPOs on OUs
[+]Split objects into types...
Traceback (most recent call last):
File "/workspace/ctools/AD_Tools/AD_Miner/.venv/bin/AD-miner", line 6, in
sys.exit(main())
File "/workspace/ctools/AD_Tools/AD_Miner/ad_miner/main.py", line 182, in main
domains = Domains(arguments, neo4j)
File "/workspace/ctools/AD_Tools/AD_Miner/ad_miner/sources/modules/domains.py", line 243, in init
self.generatePathToDa()
File "/workspace/ctools/AD_Tools/AD_Miner/ad_miner/sources/modules/domains.py", line 666, in generatePathToDa
self.ou_to_domain_admin[path.nodes[-1].domain].append(path)
KeyError: 'ADTEST.ROOT.NET'

Add shortest compromission paths weighted by exploitability

Goals:

  • Compute shortest compromission paths not by bounce count but by exploitation difficulty.

Main challenges:

To implement:

  • Implement a request to check Graph Data Science plugin installation and version.
  • Add configuration file with exploitability rating of every bloodhound edges.
  • Give default exploitability rating for every node.
  • Add a warning when unknown edge types are encountered.
  • Implement an automatic switch between normal mode and weighted graph mode.
  • Implement automatic graph projection and old projection drop.
  • Find a way to identify edges types in Dijkstra's results (maybe with negligible identifier in the cost property) and correct them in post-processing.
  • Adjust exploitability for all edges (including AD Miner edges)
  • Implement a max-cost for gds.shortestPath.dijkstra.stream in the cypher request
  • Implement properties in gds create graph parameter (it has to be modified by the python code)

TypeError in krb_pwd_last_set

Describe the bug
On a fresh kali VM and AD-Miner installation through pipx we fail with the error underneath.

Terminal Output

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/kali/tools/AD_Miner-1.2.0/ad_miner/__main__.py", line 189, in main
    rating_dic = rating(users, domains, computers, objects, azure, arguments)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/kali/tools/AD_Miner-1.2.0/ad_miner/sources/modules/rating.py", line 35, in rating
    max([dict["pass_last_change"] for dict in users.users_krb_pwd_last_set], default=None),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: '>' not supported between instances of 'int' and 'NoneType'

Screenshots
If applicable, add screenshots to help explain your problem.

image

System information

  • OS kali-linux-2024.1
  • Python version 3.11

Potential Solution

def rating(users, domains, computers, objects, azure, arguments):
    d["on_premise"][
        time_since(
            max((dict["pass_last_change"] for dict in users.users_krb_pwd_last_set if dict["pass_last_change"] is not None), default=None),
            age=1 * 365,
            criticity=2,
        )
    ].append("krb_last_change")
    # The rest of your function remains unchanged.

def create_dico_data(data, arguments, domains, computers, users, objects, azure, dico_rating_color):
    dico_data = {
        # Other initializations
        "krb_last_change": max([dict["pass_last_change"] for dict in users.users_krb_pwd_last_set if dict["pass_last_change"] is not None], default=0),
        # Continue with other data points
    }
    return dico_data

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.