MSSQL Empty SA → xp_cmdshell

Classic Microsoft SQL Server attack path: SQL authentication with a blank (or default-weak) sa password, then OS command execution via the xp_cmdshell extended stored procedure under the SQL Server service account. Still appears on internal assessments of legacy Windows estates — including hosts that scanners report as “weak password” when the finding is actually no password. 1

Why it matters

  • sa with SQL auth and an empty password is remote authentication with the highest SQL privilege tier (sysadmin-class control once logged in).
  • xp_cmdshell turns that into host RCE: the spawned Windows process runs as the SQL Server service account, which is often highly privileged on the box. 2
  • Chain fits the same “defaults and legacy surface” theme as ntlm-relay-attacks and windows-server-2012-r2-security-assessment: old configuration survives because nothing forces change until an assessor or attacker looks.

Historical note: blank sa was a default/install-time footgun for years (e.g. CVE-2000-1209 era SQL Server 7/2000/MSDE). Modern installs prompt for a password and disable xp_cmdshell by default — but mixed-mode SQL auth + forgotten/empty sa still shows up on long-lived internal servers.

Detect

CheckHow
Port / instanceTCP 1433 (default); also UDP 1434 SQL Browser for named instances
Empty saNmap NSE: nmap -p 1433 --script ms-sql-empty-password --script-args mssql.instance-all <target> — success looks like sa:<empty> => Login Success 3
Broader NSE bundlems-sql-info, ms-sql-empty-password, ms-sql-xp-cmdshell, ms-sql-ntlm-info, ms-sql-config (needs creds for several)
Auth modeMixed mode (SQL + Windows) is a prerequisite for SQL logins like sa; Windows-only auth closes this path for SQL passwords
Scanner nuance”Weak password” findings sometimes collapse empty and weak into one bucket — read the raw scanner evidence before scoping

Confirm

Only after a successful SQL login (and only within ROE):

  1. Confirm identity/role: SELECT SYSTEM_USER, IS_SRVROLEMEMBER('sysadmin');
  2. Check whether xp_cmdshell is enabled: SELECT * FROM sys.configurations WHERE name = 'xp_cmdshell'; (run_value 1 = on)
  3. If disabled but you are sysadmin, Microsoft documents enable via sp_configure (show advanced options → xp_cmdshell → RECONFIGURE). Prefer documenting the capability and residual risk over enabling it on a client host without explicit approval.
  4. If enabled: EXEC xp_cmdshell 'whoami'; — proves OS execution context (service account). 4
  5. Who else can run it (non-sysadmin): EXEC sp_helprotect 'xp_cmdshell'; in master.

Assessment friction: modern Linux clients (OpenSSL 3.x default SECLEVEL, Python builds that dropped legacy ciphers) often fail the TLS handshake before authentication. That is not a negative for empty-password — it is a client/server cipher mismatch. See legacy-tls-assessment-friction. Do not mark the finding false just because Impacket/pymssql/sqlcmd on a current Kali failed to connect.

Remediate

ControlDetail
Password / disable saSet a unique strong password for sa, or disable the login if unused; prefer Windows auth and named least-privilege SQL logins
Auth modePrefer Windows Authentication only where applications allow; mixed mode expands password-spray and empty-password surface
xp_cmdshell offLeave disabled (default). Microsoft: new code should not use it; if a legacy app requires it, enable only for the task duration 5
NetworkRestrict 1433/1434 to app tiers; no flat access from user VLANs or the open internet
MonitoringAlert on sa logins, failed SQL auth bursts, and xp_cmdshell / sp_configure usage (audit tools often flag enablement)
Service accountRun SQL Server as a least-privilege domain/Managed Service Account so a cmdshell breakout is not instant Domain Admin

Sources

Footnotes

  1. 2013 — Default configuration check for Microsoft SQL Server - Taking advantage of quiet days in holidays

  2. xp_cmdshell (Transact-SQL)

  3. 2013 — Default configuration check for Microsoft SQL Server - Taking advantage of quiet days in holidays

  4. xp_cmdshell (Transact-SQL)

  5. xp_cmdshell (Transact-SQL)