Coder Social home page Coder Social logo

olivierh59500 / ad-control-paths Goto Github PK

View Code? Open in Web Editor NEW

This project forked from anssi-fr/ad-control-paths

0.0 2.0 0.0 984 KB

Active Directory Control Paths auditing and graphing tools

Home Page: https://www.sstic.org/2014/presentation/chemins_de_controle_active_directory/

License: Other

PowerShell 3.61% C 87.10% Ruby 9.29%

ad-control-paths's Introduction

Active Directory Control Paths

An example of control paths graph

Control paths in Active Directory are an aggregation of "control relations" between entities of the domain (users, computers, groups, GPO, containers, etc.) which 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 ?".

The topic has been presented during a talk at the French conference SSTIC-2014. Our slides and paper can be found here: https://www.sstic.org/2014/presentation/chemins_de_controle_active_directory/.

This repository contains tools that can be used to generate such graphs.


CHANGES

New control paths are added in v1.2.2: RoDC and LAPS.

Major 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. Some 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).

A few false positives were fixed and new control paths were added, so running it again on already tested ADs might be a good idea.


  1. Install / Prerequisites
  2. Usage context
  3. Dump data into CSV files
  4. Import CSV files in graph database
  5. Query graph database
  6. Visualize graphs
  7. Known issues
  8. Authors

1. INSTALL / PREREQUISITES

Note:

  • Dump step runs on Windows only (tested on Windows 7 and later).
  • Import, Query and Visualize steps can run on the same machine or on anything supporting Neo4j, Java and Ruby. They have been tested on Windows and Linux.

Building steps (or just download the latest pre-compiled, signed binaries from the Github release tab):

  • Build the 3 solutions in the subfolders of /Dump/Src/ with an up-to-date Visual Studio (Community version works). Targets must be:
    • Release/x64 for AceFilter
    • Release/x64 for ControlRelationProviders
    • RelADCP/x64 for DirectoryCrawler.

Installation steps :

  1. Install a Java JRE from https://java.com/en/download/manual.jsp or from your distribution.

  2. Install Neo4j: download neo4j community edition and extract the zip/tar archive (not the installer). Do not start the Neo4j server before importing your data.

  3. Install Ruby from https://rubyinstaller.org/downloads/ or from your distribution.

  4. Install the neography gem. In an elevated prompt or with sudo:

gem install neography

Tested software versions (anything more recent should be ok)

  • Windows 7+
  • Linux distributions: Ubuntu 14.04 and Debian 8
  • Java: 1.7 & 1.8
  • Neo4j: 3.0
  • Ruby: 2.2
  • Neography: 1.8.0

2. USAGE CONTEXT

Note: None of these tools need to run on a domain controller.

Generating control paths graphs for your domain takes the 4 following steps:

  1. Dump data from the LDAP directory and the SYSVOL and analyze it to form control relationships.
  2. Import these relations into a graph-oriented database (Neo4j).
  3. Query that database to export various nodes lists, control paths, or create JSON files representing control paths graphs.
  4. Visualize graphs created from those JSON files.

Global process schema of generation of control paths

The 3 last steps are always performed in the same way, but the first step (data dumping) can be carried out in different contexts:

  1. Live access to the domain, using a simple domain user account.
  2. Live access to the domain, using a domain administrator account.
  3. Offline, using a copy of a ntds.dit file and a robocopy of the SYSVOL preserving security attributes.

A 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. If one is available, an administrator account can thus be used to ensure that no element is inaccessible.

If no access to the domain is given, control graphs can be realized from offline copies of the ntds.dit and SYSVOL:

  1. 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):

     dsamain.exe -allowNonAdminAccess -dbpath <ntds.dit path> -ldapPort 1234
    
  2. 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):

     robocopy.exe \\<DC ip or host>\sysvol\<domain dns name>\Policies <destination path> /W:1 /R:1 /COPY:DATSO /E /TEE /LOG:<logfile.log>
    

    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). You then need to use the SeBackupPrivilege to process this local robocopy (dumping tools have a use backup privilege option that you must use).

3. DUMP DATA INTO CSV FILES

Note: The Dump.ps1 script configures the outputDir to be a NTFS compressed folder. Flat unicode CSVs files can take quite a lot of disk space otherwise.

Use the powershell script Dump\Dump.ps1 to dump data from the LDAP directory and SYSVOL. The simplest example is:

.\Dump.ps1
    -outputDir        <output directory>
    -domainController <DC ip or host>
	    -domainDnsName    <domain FQDN>
    -sysvolPath       <sysvol 'Policies' folder path>
  • -domainController can be an real domain controller, or a machine exposing the LDAP directory from a re-mounted ntds.dit using dsamain.
  • -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.

This produces some .csv and .log files as follow:

<outputDir>
    |- yyyymmdd_domainfqdn\Logs\*.log                                    # Log files
    |- yyyymmdd_domainfqdn\Ldap\*.csv                                    # Unfiltered dumped information
    \- yyyymmdd_domainfqdn\Relations\*.csv                               # "Control relations" files, which will be imported into the graph database

Other options

  • -help: show usage.

  • -user and -password: use explicit authentication (by default implicit authentication is used). The username can be specified in the form DOMAIN\username, which can be useful to dump a remote domain accessible through a trust. If you don't want your password to appear in the command line but still use explicit authentication use the following runas command, then launch the Dump.ps1 script without -user and -password options:

      C:\> runas /netonly /user:DOM\username cmd.exe
    
  • -logLevel: change log and output verbosity (possible values are ALL, DBG, INFO (default), WARN, ERR, SUCC and NONE).

  • -ldapOnly and -sysvolOnly: dump only data from the LDAP directory (respectively from the SYSVOL).

  • -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.

  • -useBackupPriv: use backup privilege to access -sysvolPath, which is needed when using a robocopy. You must use an administrator account to use this option.

  • -generateCmdOnly: generate the list of commands to use to dump the data, instead of executing these commands. This can be useful on systems where the powershell's execution-policy doesn't allow unsigned scripts to be executed, or on which powershell is not installed in a tested version (v2.0 and later).

  • -fromExistingDumps: skip the LDAP request step and work from files found in the Ldap\ folder.

4. IMPORT CSV FILES INTO A GRAPH DATABASE

You can now import the Relations CSV files along with the AD objects into your Neo4j graph database. This step can be done fully offline. You may need admin permissions to start/stop Neo4j.

  1. Stop the Neo4j server if it is started:

     $env:NEO4J\bin\neo4j stop
    
  2. Import CSV files in a new graph database adcp.db:

  • Set an environment variable for convenience: $env:DUMP = "PATH_TO\yyyymmdd_domainfqdn"

  • In neo4j folder:

.\bin\neo4j-import --into data\databases\adcp.db --id-type string  `
--nodes $env:DUMP\Ldap\all_nodes.csv  `
--relationships $((dir $env:DUMP\relations\*.csv -exclude *.deny.csv) -join ',') `
--input-encoding UTF-16LE --multiline-fields=true

Headers-related errors will be raised and can be ignored. It is still a good idea to have a look at the bad.log file.

  1. Modify Neo4j default configuration file: conf/neo4j.conf

     uncomment and set dbms.active_database=adcp.db
    
  2. Start the Neo4j server:

     .\bin\neo4j install-service -Verbose
     .\bin\neo4j start -Verbose
    
  3. Change the default password for the Neo4j REST interface. Navigate to http://localhost:7474 (the web interface should be running). Enter the default username and password (neo4j for both), then enter secret as your new password (Hardcoded in the Query script, can be changed with the --password flag). By default, Neo4j only listens to local connections.

5. QUERYING THE GRAPH DATABASE

The Query/query.rb program allows you to query the created Neo4j database.

Basic query to get a graph and paths of all nodes able to take control of the Domain Admins group:

ruby query.rb --quick

(though you should use --denyacefile if you have a non-empty deny relations file).

Automatic full audit mode (long)

The "automatic mode" will create graphs, paths, and nodes lists for a predefined list of builtin targets:

ruby query.rb --full --denyacefile $env:DUMP\relations\*.deny.csv
    [+] running in automatic-mode, lang=en, outdir=out
    [+] control graph for cn=domain admins,cn=users,dc=
    [+] found 13 control nodes, max depth is 5
    [+] control graph with 13 nodes and 12 links
    [+] found 13 control nodes, max depth is 5
    [+] control graph with 13 nodes and 13 links
    [+] found 13 control nodes, max depth is 5
    [...]

The default output directory is out and contains the following generated files:

./out
   |- *.json         # JSON files containing a graph that can then be visualized
   |- *_nodes.txt    # Lists of nodes existing in the above graphs
   \- *_paths.txt    # Lists of paths existing in the above graphs

The default target are search with their english DN. You can choose another language with the --lang option. For now, only en and fr are supported.

6. VISUALIZE GRAPHS

ADCP uses the OVALI frontend to display JSON data files as graphs.

  1. Quickstart: Open Visualize/index.html with a web brower (Chrome/Chromium is preferred). Open one of the generated json files.

7. OTHER QUERYING EXAMPLES

The Query/query.rb program can also search paths for non-predefined targets, as illustrated in the following examples:

  1. Search for nodes (prints node names and their id ; a node's id can be used instead of its DN in every command):

     $ ./query.rb --search 'admins'
         cn=domain admins,cn=users,dc=dom2012r2,dc=local [5]
         cn=enterprise admins,cn=users,dc=dom2012r2,dc=local [6]
         cn=adminsdholder,cn=system,dc=dom2012r2,dc=local [40]
         cn=schema admins,cn=users,dc=dom2012r2,dc=local [166]
         cn=dnsadmins,cn=users,dc=dom2012r2,dc=local [185]
    

Note: the argument is interpreted as a Java regular expression, enclosed in .* (so that domain admins will match the full DN). As a consequence, certain special characters (such as {, found in GPO DN) have a meaning for the regexp engine. You should manually escape these characters, and search for cn=\\{ to match those DN.

  1. Get more informations about a node:

     $ ./query.rb --info 'domain admins'
     [...]
     cn=domain admins,cn=users,dc=dom2012r2,dc=local [5]
         type: ["group"]
         directly controlling 245 node(s)
         directly controlled by 6 node(s)
    
  2. Search for nodes controlling another node. We can choose to output results to a file or to stdout (the -- stops option processing, so domain admins is our target, and not the output file):

     $ ./query.rb --nodes -- 'domain admins'
         [+] control nodes to node number 5
         [+] found 13 control nodes, max depth is 5
         cn=domain admins,cn=users,dc=dom2012r2,dc=local
         cn=system,cn=wellknown security principals,cn=configuration,dc=dom2012r2,dc=local
         cn=administrators,cn=builtin,dc=dom2012r2,dc=local
         cn=enterprise admins,cn=users,dc=dom2012r2,dc=local
         cn=users,dc=dom2012r2,dc=local
         cn=administrator,cn=users,dc=dom2012r2,dc=local
         cn=builtin,dc=dom2012r2,dc=local
         dc=dom2012r2,dc=local
         cn=domain controllers,cn=users,dc=dom2012r2,dc=local
         cn={31b2f340-016d-11d2-945f-00c04fb984f9},cn=policies,cn=system,dc=dom2012r2,dc=local
         cn=creator owner,cn=wellknown security principals,cn=configuration,dc=dom2012r2,dc=local
         cn=policies,cn=system,dc=dom2012r2,dc=local
         cn=system,dc=dom2012r2,dc=local
    
  3. We can filter the previous result, for example by limiting ourselves to nodes with the "user" type:

     $ ./query.rb --nodes /tmp/hitlist.txt --nodetype user 'domain admins'
         [+] control nodes with type user to node number 5
         [+] found 13 control nodes, max depth is 5
    
     $ cat /tmp/hitlist.txt
         cn=administrator,cn=users,dc=dom2012r2,dc=local
    
  4. Search for control paths to our node. We will print all the shortest possible paths to domain admins into /tmp/paths.txt:

     $ ./query.rb --path /tmp/paths.txt --type short 'domain admins'
         [+] short control paths to node number 5
         [+] found 13 control nodes, max depth is 5
         [+] found 38 paths
    
     $ head -3 /tmp/paths.txt
         cn=domain admins,cn=users,dc=dom2012r2,dc=local
         cn=system,cn=wellknown security principals,cn=configuration,dc=dom2012r2,dc=local stand_right_write_dac cn=domain admins,cn=users,dc=dom2012r2,dc=local
         cn=system,cn=wellknown security principals,cn=configuration,dc=dom2012r2,dc=local stand_right_write_owner cn=domain admins,cn=users,dc=dom2012r2,dc=local
    
  5. Create the full control graph for our node, and save it to /tmp/fullgraph.json:

     $ ./query.rb --graph /tmp/fullgraph.json --type full 'domain admins'
         [+] full control graph to node number 5
         [+] found 13 control nodes, max depth is 5
         [+] control graph with 13 nodes and 59 links
    
  6. By default, we search for paths to a node (i.e who can control a node). We can also try to search for paths from a node (i.e what resources are controlled by this node). Be careful however, as some powerful nodes (such as domain admins) control everything in the domain. This can lead to never-ending queries. You can limit the maximum search depth with the --maxdepth option.

     $ ./query.rb --path --direction from --type short 'cn=guest,cn=users,dc=dom2012r2,dc=local'
         [+] short control paths from node number 135
         [+] found 2 control nodes, max depth is 1
         [+] found 2 paths
         cn=guest,cn=users,dc=dom2012r2,dc=local
         cn=guests,cn=builtin,dc=dom2012r2,dc=local  group_member cn=guest,cn=users,dc=dom2012r2,dc=local
    
  7. See ./query.rb --help for a full list of possible options.

8. AUTHORS

Geraud de Drouas - ANSSI - 2015-2016

Lucas Bouillot, Emmanuel Gras - ANSSI - 2014

ad-control-paths's People

Contributors

pcapillon avatar gdedrouas avatar

Watchers

James Cloos avatar Olivier Houte avatar

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.