{"id":13628494,"url":"https://github.com/ANSSI-FR/AD-control-paths","last_synced_at":"2025-04-17T04:31:49.380Z","repository":{"id":18394459,"uuid":"21575698","full_name":"ANSSI-FR/AD-control-paths","owner":"ANSSI-FR","description":"Active Directory Control Paths auditing and graphing tools","archived":true,"fork":false,"pushed_at":"2020-12-17T19:43:04.000Z","size":1211,"stargazers_count":662,"open_issues_count":5,"forks_count":101,"subscribers_count":65,"default_branch":"master","last_synced_at":"2025-04-02T06:36:28.502Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://www.sstic.org/2014/presentation/chemins_de_controle_active_directory/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ANSSI-FR.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-07-07T15:26:43.000Z","updated_at":"2025-03-14T23:59:43.000Z","dependencies_parsed_at":"2022-07-09T09:46:15.013Z","dependency_job_id":null,"html_url":"https://github.com/ANSSI-FR/AD-control-paths","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ANSSI-FR%2FAD-control-paths","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ANSSI-FR%2FAD-control-paths/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ANSSI-FR%2FAD-control-paths/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ANSSI-FR%2FAD-control-paths/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ANSSI-FR","download_url":"https://codeload.github.com/ANSSI-FR/AD-control-paths/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249315939,"owners_count":21249860,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T22:00:53.000Z","updated_at":"2025-04-17T04:31:48.716Z","avatar_url":"https://github.com/ANSSI-FR.png","language":"C","readme":"# Active Directory Control Paths\n\n## \"Who Can Read the CEO's Emails Edition\"\n![An example of control paths graph](graph-example.png \"An example of control paths graph\")\n\nControl paths in Active Directory are an aggregation of \"control relations\" between entities of the domain (users, computers, groups, GPO, containers, etc.)\nwhich can be visualized as graphs (such as above) and whose purpose is to answer questions like *\"Who can get 'Domain Admins' privileges ?\"* or *\"What resources can a user control ?\"* and even *\"Who can read the CEO's emails ?\"*.\n\n---\n## CHANGES\nNew workflow for all steps, automating neo4j setup and import.\n\nBasic Cypher querying through Neo4j REST API, increasing performance\n\nNew control paths are added : Kerberos delegation, SCCM dumping utilities for local admins and sessions control paths\n\nAdding EXCHANGE permissions in v1.3 \"Who Can Read the CEO's Emails Edition\".\nPermissions extracted from AD Users, Mailbox/DB descriptors, RBAC and MAPI folders.\n\nBetter resume features, nodes clustering (through OVALI) in v1.2.3.\n\nNew control paths are added in v1.2.2: RoDC and LAPS.\n\nMajor code changes take place in v1.2, as it is now able to dump and analyze very large Active Directories without hogging too much RAM.\nSome very large ADs with over 1M objects and 150M ACEs have been processed in a reasonable amount of time (a few hours on a laptop, consuming less than 1GB RAM).\n\nA few false positives were fixed and new control paths were added, so running it again on already tested ADs might be a good idea.\n\n---\n## QUICK START\n- Download and extract the latest binary release from the Github Releases tab on a Windows machine.\n- Skip to part 3 (Dump step)\n\n---\n## TABLE OF CONTENT\n1. Install / Prerequisites\n2. Usage context\n3. Dump data into CSV files\n4. Import CSV files in graph database\n5. Query graph database\n6. Visualize graphs\n7. Other Querying Examples\n8. Authors\n\n## 1. INSTALL / PREREQUISITES\n\n### Note\n\n- **Dump** step runs on Windows only (tested on Windows 7 and later).\n- **Import**, **Query** and **Visualize** steps can run on the same machine or on anything supporting Java and Neo4J. They have been tested on Windows and Linux.\n\n### Building\n\n - Follow the instructions in BUILDING.md.\n\n### Prerequisites\n\n0. Download Zulu JDK 8 (https://cdn.azul.com/zulu/bin/zulu8.36.0.1-ca-jdk8.0.202-win_x64.zip) and put the zip in `Dump/ADCP`\n\n0. Download Neo4j 3.4.1 (https://neo4j.com/artifact.php?name=neo4j-community-3.5.3-windows.zip) and put the zip in `Dump/ADCP`\n\n0. Install EWS Managed API (if dumping Exchange permissions) from https://go.microsoft.com/fwlink/?LinkId=255472\n\n## 2. USAGE CONTEXT\n\n**Note:** None of these tools need to run on a domain controller.\n\nGenerating control paths graphs for your domain takes the 4 following steps:\n\n0. **Dump** data from LDAP directory, SYSVOL and EWS.\n0. **Prepare**  run analyzers to form control relationships.\n0. **Import** these relations into a graph-oriented database (Neo4j).\n0. **Query** that database to export various nodes lists, control paths, or **create JSON files** representing control paths graphs.\n0. **Visualize** graphs created from those JSON files.\n\n![Global process schema of generation of control paths](global-schema.png \"Global process schema of generation of control paths\")\n\nThe 3 last steps are always performed in the same way, but the first step (data dumping) can be carried out in different contexts:\n\n0. Live access to the domain, using a simple domain user account.\n0. Live access to the domain, using a domain administrator account.\n0. Offline, using a copy of a `ntds.dit` file and a robocopy of the SYSVOL preserving security attributes.\n\nA simple domain user account is enough to dump a large majority of the control relations, but access to a few LDAP containers and GPO folders on the SYSVOL can be denied.\nIf one is available, an administrator account can thus be used to ensure that no element is inaccessible.\n\nIf no access to the domain is given, control graphs can be realized from offline copies of the `ntds.dit` and SYSVOL:\n\n0. A copied `ntds.dit` file can be re-mounted to expose its directory through LDAP with the `dsamain` utility (available on a Windows server machine having the AD-DS or AD-LDS role, or with the \"Active Directory Domain Services Tools\" installed):\n\n        dsamain.exe -allowNonAdminAccess -dbpath \u003cntds.dit path\u003e -ldapPort 1234\n\n0. A robocopy of the SYSVOL share preserving security attributes can be done with the `robocopy` utility (the destination folder must be on an NTFS volume):\n\n        robocopy.exe \\\\\u003cDC ip or host\u003e\\sysvol\\\u003cdomain dns name\u003e\\Policies \u003cdestination path\u003e /W:1 /R:1 /COPY:DATSO /E /TEE /LOG:\u003clogfile.log\u003e\n\n    **Note**: to preserve security attributes on the copied files you need the `SeRestorePrivilege` on the local computer you're running the robocopy on (that is, you need to run these commands as local administrator).\n    You then need to use the `SeBackupPrivilege` to process this local robocopy (dumping tools have a `use backup privilege` option that you must use).\n\n## 3. DUMP DATA INTO CSV FILES\n\nUse the powershell module in `Dump`. You must be in the `Dump` folder (important).\nThe simplest example is:\n\n    Import-Module .\\ADCP\n    Get-ADCPDump\n        -outputDir        \u003coutput directory\u003e\n        -domainController \u003cDC ip or host\u003e\n        -domainDnsName    \u003cdomain FQDN\u003e\n\nOr with Exchange-related data:\n\n    Import-Module .\\ADCP\n    $creds = Get-Credential\n    Get-ADCPDump\n        -outputDir          \u003coutput directory\u003e\n        -domainController   \u003cDC ip or host\u003e\n        -domainDnsName      \u003cdomain FQDN\u003e\n        -exchangeServer     \u003cexchange host\u003e\n        -exchangeCredential $creds\n\n- `-domainController` can be an real domain controller, or a machine exposing the LDAP directory from a re-mounted `ntds.dit` using `dsamain`.\n\nThis produces some `.csv` and `.log` files as follow:\n\n    \u003coutputDir\u003e\n        |- yyyymmdd_domainfqdn\\Logs\\*.log                                    # Log files\n        |- yyyymmdd_domainfqdn\\Ldap\\*.csv                                    # Unfiltered dumped information\n        \\- yyyymmdd_domainfqdn\\Relations\\*.csv                               # \"Control relations\" files, which will be imported into the graph database\n        \n\n### Other options\n\n- `-Credential` : use explicit authentication (by default implicit authentication is used). `Credential` is a Powershell credential object, use `Get-Credential` to built it .\n    If you don't want your password to appear in the command line but still use explicit authentication use the following `runas` command, then use the module without `-Credential` option:\n\n        C:\\\u003e runas /netonly /user:DOM\\username powershell.exe\n- `-sysvolPath` can be a network path (example `\\\\192.168.25.123\\sysvol\\domain.local\\Policies`) or a path to a local robocopy of this folder. Defaults to `\\\\domainController\\sysvol\\domainDnsName\\Policies`.\n- `-exchangeServer`, `-ExchangeCredential`: explicit authentication for EWS on a CAS Exchange server. \n  Use an Exchange Trusted Subsystem member account with an active mailbox, but NOT DA/EA/Org Mgmgt because of some Deny ACEs.\n  \n- `-logLevel`: change log and output verbosity (possible values are `ALL`, `DBG`, `INFO` (default), `WARN`, `ERR`, `SUCC` and `NONE`).\n- `-ldapOnly` and `-sysvolOnly`: dump only data from the LDAP directory (respectively from the SYSVOL).\n- `-ldapPort`: change ldap port (default is `389`). This can be useful for a copied `ntds.dit` re-mounted with `dsamain` since it allows you to use a non standard ldap port.\n- `-useBackupPriv`: use backup privilege to access `-sysvolPath`, which is needed when using a robocopy. You must use an administrator account to use this option.\n- `-forceOverwrite`: overwrite any previous dump files from the same-day, same-target folder\n\n**Warning:** Accessing the Sysvol share from a non-domain machine can be blocked by UNC Paths hardening, which is a client-side parameter enabled by default since Windows 10. Disable it like this:\nSet-ItemProperty -Path HKLM:\\Software\\Policies\\Microsoft\\Windows\\NetworkProvider\\HardenedPaths -Name \"\\\\*\\SYSVOL\" -Value \"RequireMutualAuthentication=0\"\n\n** Note:** The only binary needed in this step is `DirectoryCrawler.exe`.\n\n## 4. PREPARE THE DATA\nThis action can be performed offline.\n\nTo computer relations, use the ADCP module (like in 3.)\n\n    Import-Module .\\ADCP\n    Prepare-ADCPDump\n        -inputDir         \u003cinput directory\u003e\n        -domainDnsName    \u003cdomain FQDN\u003e\n\n\n## 5. IMPORT CSV FILES INTO A GRAPH DATABASE\n\nYou can now import the Relations CSV files along with the AD objects into your Neo4j graph database. This step can be done fully offline. Use the ADCP module:\n\n    Import-Module .\\ADCP\n    $instance = Import-ADCPDump\n        -inputDir         \u003cinput directory\u003e\n        -domainDnsName    \u003cdomain FQDN\u003e\n    # Launch Neo4J\n    $instance | Start-ADCPInstance\n\nTo perform these step manually (or in Linux):\n0. Stop the Neo4j server if it is started:\n```\n    .\\bin\\neo4j stop\n```\n0. Import CSV files in a new graph database adcp.db:\n\n- Set an environment variable to the dump folder for convenience:\n```\n    $env:DUMP = \"PATH_TO\\yyyymmdd_domainfqdn\\\" \n```\n- In neo4j folder (you can copy/paste this):\n```\n    .\\bin\\neo4j-import --into data/databases/adcp.db --id-type string  `\n    --nodes $env:DUMP\\Ldap\\all_nodes.csv  `\n    --relationships $((dir $env:DUMP\\relations\\*.csv -exclude *.deny.csv) -join ',') `\n    --input-encoding UTF-16LE --multiline-fields=true --legacy-style-quoting=false\n```\n\nHeaders-related errors will be raised and can be ignored. It is still a good idea to have a look at the bad.log file.\n\n0. Restart the Neo4j server if it is stopped:\n```\n    .\\bin\\neo4j start\n````\n\n\n\n**Note:** All the previous steps (2, 3, 4) can be piped in Powershell:\n\n    Import-Module .\\ADCP\n    Get-ADCPDump\n        -outputDir        \u003coutput directory\u003e\n        -domainController \u003cDC ip or host\u003e\n        -domainDnsName    \u003cdomain FQDN\u003e |\n    Prepare-ADCPDump |\n    Import-ADCPDump |\n    Start-ADCPInstance\n\n## 6. QUERY THE GRAPH DATABASE\n\nThe `Query/Query.ps1` script is used to query the created Neo4j database. \nUse the -neo4jPort parameter if Start-ADCPInstance binded to something else than the default 7474/TCP (see console).\n\t\n### Basic query to get a graph and paths of all nodes able to take control of the \"Domain Admins\" group:\n```\n    .\\Query.ps1 -quick\n```    \n   \n### To search for a node from its DN or an email address and get a graph to it (useful if AD is not in English):\n```\n    .\\Query.ps1 -search \"cn=administrateurs,\"\n```\n``` \n    .\\Query.ps1 -search \"ceo@domain.local\"\n``` \n  (This will return a node id number)\n```  \n    .\\Query.ps1 -graph \u003cnode id number\u003e -outFile \u003cJSON filename\u003e\n```    \n  (This produces a json graph file, which you can visualize, see part 6)\n\n  \n### Progressively increase the ShortestPath algorithm Depth parameter as you visualize and adjust the graph\n```\n    .\\Query.ps1 -graph \u003cnode id number\u003e -maxDepth 15 -outFile \u003cJSON filename\u003e\n```    \n\n## 7. VISUALIZE GRAPHS\n\nADCP uses the [OVALI](https://github.com/ANSSI-FR/OVALI) frontend to display\nJSON data files as graphs.\n\n0. Quick Start\nOpen Visualize/index.html with a web brower (Chrome/Chromium is preferred).\nOpen one of the generated json files.\n\nFor better visibility, you might want to:\n- right click -\u003e cluster some similar nodes\n- setup hierarchical viewing with the menu on the left, especially for email nodes as this will flatten Exchange RBAC nodes\n- disable physics if the graph does not stabilize\n- remove unwanted relationships or nodes with right click -\u003e \"Cypher delete to clipboard\" and paste into http://localhost:7474 then relaunch the query.\n\n\n## 8. AUTHORS\n\nJean-Baptiste Galet - ANSSI - 2017-2018\n\nGeraud de Drouas - ANSSI - 2015-2018\n\nLucas Bouillot, Emmanuel Gras - ANSSI - 2014\nPresented at the French conference SSTIC-2014. Slides and paper can be found here:\n[https://www.sstic.org/2014/presentation/chemins\\_de\\_controle\\_active\\_directory/](https://www.sstic.org/2014/presentation/chemins_de_controle_active_directory/).\n","funding_links":[],"categories":["Uncategorized","C","C (286)","[🔓 security](https://github.com/stars/ketsapiwiq/lists/unlock-security)","威胁情报","Operating Systems","Windows-based defenses"],"sub_categories":["Uncategorized","威胁狩猎","Windows","Active Directory"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FANSSI-FR%2FAD-control-paths","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FANSSI-FR%2FAD-control-paths","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FANSSI-FR%2FAD-control-paths/lists"}