Haxoris Wiki

Password Spraying Internal Services

How Password Spraying Internal Services works

Password spraying tries one likely password against many accounts, staying below the lockout threshold so no account trips its counter. The one password is predictable: a season and year (Autumn2025), a company name and suffix (Contoso2025!), or a value known reused from a breach. It is offered to every internal service that accepts domain credentials - SMB and LDAP on the domain controllers, RDP and RD Gateways, the VPN portal, OWA and EWS webmail, and internal SSO or ADFS.

The attacker gains a valid domain credential with no prior access and no exploit, then reuses it wherever single-factor authentication is accepted. It survives because lockout counts are kept per account, not per password: one attempt against each of a thousand accounts locks nobody, while a single reused password walks in on the handful of users who chose it. The failures scatter as ordinary typos across the estate unless something is watching for the horizontal pattern. The domain lockout and complexity settings themselves belong to the Weak Password Policies page in the Active Directory section; here the concern is the service exposure and the spray mechanics against it.

Password Spraying Internal Services in practice

Read the effective lockout policy before sending one attempt

This is the safety gate. The threshold and observation window decide how many attempts a schedule can make without locking anyone, so read them from an authorised low-privilege account first.

# Authorised low-priv account: read the effective account policy from the DC
nxc smb dc01.lab.internal -u <TEST_USER> -p <TEST_PW> --pass-pol

# Fine-grained password policies (PSOs) can override the default per group, so
# confirm the resultant policy on the OU your target accounts actually sit in.

Build a spray schedule that cannot lock an account

Turn the policy into a plan with a margin, then hold to it. The rule is one password per observation window with a gap longer than the window, never two.

Effective policy (from --pass-pol):
  Lockout threshold        : 5 bad attempts
  Observation window       : 30 minutes
  Reset / lockout duration : 30 minutes

Safe spray plan:
  Attempts per account per window : 1   (threshold 5, margin of 4)
  Passwords per round             : 1   (Autumn2025)
  Gap between rounds              : 35 min  (longer than the window)
  Accounts per round              : the whole user list, one attempt each

Never: two passwords in one window, or a retry after a transient error,
either of which stacks toward the threshold and locks a real user.

Enumerate a clean user list, then spray one password per round

Build the target list from the directory, not by guessing, so the spray only touches live enabled accounts and never a disabled honeypot. Then send exactly one password.

# Pull enabled samAccountNames with an authorised read-only bind
nxc ldap dc01.lab.internal -u <TEST_USER> -p <TEST_PW> --users \
  | awk 'NR>1 {print $5}' | sort -u > /tmp/users.txt
# drop disabled and already-locked accounts before spraying

# One password, one attempt per account, this round only. --no-bruteforce keeps
# it a spray (each user gets the single password, not a wordlist).
nxc smb dc01.lab.internal -u /tmp/users.txt -p 'Autumn2025' \
  --no-bruteforce --continue-on-success | tee /tmp/spray-r1.txt
grep '\[+\]' /tmp/spray-r1.txt

The same one-password round runs against the other surfaces as an HTTP POST to the VPN or OWA login, or through the RD Gateway. A password found here is only useful where a second factor does not stand in the way, which is the subject of the Missing MFA On Remote Access page.

Confirm the detection signal the spray should have raised

State what the defence should have caught, so the finding names a monitoring gap and not only a weak password.

What the SOC should see from one round (single source, tight time cluster):
  Security 4625  logon failure, many distinct Target User Names
  Security 4771  Kerberos pre-auth failure, failure code 0x18
  same Source Network Address, ~1 failure per account, one password epoch

The pattern is breadth: many users, one source, one window. A per-account
lockout alert never fires here by design, so a detection keyed only on
lockouts is blind to the entire technique.

How to fix and prevent Password Spraying Internal Services

  1. Enforce MFA on every credential-accepting service
    • A found password is inert if the service demands a second factor. Which remote paths enforce it and which do not belongs to the Missing MFA On Remote Access page.
  2. Alert on breadth, not on single-account lockouts
    • A spray never trips one account’s counter, so key the detection on many distinct accounts failing from one source in one window.
  3. Ban weak, seasonal and company-derived passwords
    • Deploy a password filter with a banned-list covering Season plus Year, CompanyName plus Year and known-breach reuse. The policy plumbing sits on the domain password policy page.
  4. Shrink the sprayable surface
    • Retire single-factor reachable endpoints - basic-auth OWA and EWS, standalone RDP, legacy VPN portals - so there is simply less to spray.
  5. Throttle and smart-lockout at the gateway
    • Add per-source rate limiting and extranet smart lockout so many one-attempt logins from one origin are slowed and flagged without locking the real users out.

Last updated

References