A collector for adding MSSQL attack paths to BloodHound with OpenGraph by Chris Thompson at SpecterOps. Available as both a PowerShell script and a cross-platform Go binary (with concurrent collection, SOCKS5 proxy support, and streaming output).
Introductory blog posts: - https://specterops.io/blog/2025/08/04/adding-mssql-to-bloodhound-with-opengraph/ - https://specterops.io/blog/2026/01/20/updates-to-the-mssqlhound-opengraph-collector-for-bloodhound/ - https://specterops.io/blog/2026/04/23/mssqlhound-now-available-in-go/
Please hit me up on the BloodHound Slack (@Mayyhem), Twitter (@_Mayyhem), or open an issue if you have any questions I can help with!
# 1) Download the source
git clone https://github.com/SpecterOps/MSSQLHound.git
cd MSSQLHound
# 2) Build the binary (Go 1.25+)
go build -o mssqlhound ./cmd/mssqlhound
On Windows, use .\mssqlhound.exe instead of ./mssqlhound.
Run MSSQLHound with a few common collection patterns:
# Use Windows integrated authentication to query Active Directory for MSSQLSvc SPNs and collect from all discovered MSSQL server instances, ten at a time
./mssqlhound -w 10
# Collect from a specific MSSQL server instance using SQL login credentials
./mssqlhound -t sql.contoso.com -u sa -p password
# Collect through a SOCKS proxy using specified domain controller IP for DNS and LDAP resolution and collect from all discovered MSSQL server instances, 20 at a time
./mssqlhound -u "CONTOSO\sqlaudit" -p "password" -d contoso.com --dc 10.2.10.100 -w 20 --verbose --proxy 127.0.0.1:9050
# Collect from all domain computers using Windows MSSQL login credentials, 25 at a time, then upload schema and results to BloodHound
./mssqlhound -u "CONTOSO\sqlaudit" -p "password" -d contoso.com -w 25 --scan-all-computers -B '<token-id>:<token-key>@https://contoso.bloodhoundenterprise.io'
MSSQL_CoerceAndRelayToMSSQLMSSQL_AddMemberMSSQL_AlterMSSQL_AlterAnyAppRoleMSSQL_AlterAnyDBRoleMSSQL_AlterAnyLoginMSSQL_AlterAnyServerRoleMSSQL_ChangeOwnerMSSQL_ChangePasswordMSSQL_ConnectMSSQL_ConnectAnyDatabaseMSSQL_ContainsMSSQL_ControlMSSQL_ControlDBMSSQL_ControlServerMSSQL_ExecuteAsMSSQL_ExecuteAsOwnerMSSQL_ExecuteOnHostMSSQL_GetAdminTGSMSSQL_GetTGSMSSQL_GrantAnyDBPermissionMSSQL_GrantAnyPermissionMSSQL_HasDBScopedCredMSSQL_HasLoginMSSQL_HasMappedCredMSSQL_HasProxyCredMSSQL_HostForMSSQL_ImpersonateMSSQL_ImpersonateAnyLoginMSSQL_IsMappedToMSSQL_IsTrustedByMSSQL_LinkedAsAdminMSSQL_LinkedToMSSQL_MemberOfMSSQL_OwnsMSSQL_ServiceAccountForMSSQL_TakeOwnershipCollects BloodHound OpenGraph compatible data from one or more MSSQL servers into individual temporary files, then zips them in the current directory
- Example: mssql-bloodhound-20250724-115610.zip
-k): krb5-user package on Linux (sudo apt install krb5-user)CONNECT SQL (default for new logins)VIEW ANY DATABASE (default for new logins)VIEW ANY DEFINITION permission or ##MS_DefinitionReader## role membership (available in versions 2022+)VIEW SERVER PERFORMANCE STATE permission or ##MSS_ServerPerformanceStateReader## role membership (available in versions 2022+) or local Administrators group privileges on the target (fallback for WMI collection)CONNECT ANY DATABASE server permission (available in versions 2014+) or ##MS_DatabaseConnector## role membership (available in versions 2022+) or login maps to a database user with CONNECT on individual databasesmsdb database user with db_datareader role or with SELECT permission on:msdb.dbo.sysproxiesmsdb.dbo.sysproxyloginmsdb.dbo.sysproxysubsystemmsdb.dbo.syssubsystemsThis section documents every network connection, authentication event, subprocess, query, and file artifact produced by MSSQLHound so operators can make informed decisions about detection risk.
All TCP connections support SOCKS5 proxy tunneling (--proxy). TLS connections use InsecureSkipVerify=true and cap at TLS 1.2.
| Protocol | Port | Transport | Target | Purpose | Conditions |
|---|---|---|---|---|---|
| TDS (SQL Server) | 1433/tcp (default, configurable) | TCP with optional TLS | Each SQL Server being enumerated | SQL authentication and query execution | Always (core functionality) |
| SQL Browser | 1434/udp | UDP | SQL Server host | Named instance port resolution | Only for named instances without an explicit port. Not proxied through SOCKS5. |
| LDAPS | 636/tcp | TLS | Domain controller | SPN enumeration, principal/SID resolution, computer enumeration | First LDAP method attempted |
| LDAP + StartTLS | 389/tcp | TCP upgraded to TLS | Domain controller | Same as LDAPS | Fallback if LDAPS fails |
| Plain LDAP | 389/tcp | TCP (unencrypted) | Domain controller | Same as LDAPS | Final LDAP fallback |
| DNS | 53/udp | UDP | --dns-resolver or --dc |
SRV records (_ldap._tcp.<domain>), A records, reverse DNS (PTR) |
When domain resolution is needed |
| WinRM | 5985/tcp (HTTP) or 5986/tcp (HTTPS) | HTTP/HTTPS | SQL Server host | Remote PowerShell for EPA configuration | Only test-epa-matrix subcommand |
| WMI/DCOM | 135/tcp + dynamic RPC | TCP | SQL Server host | Enumerate local group members (Win32_GroupUser) |
Windows only. Fails gracefully on other platforms. |
| Mode | Description |
|---|---|
| TDS 8.0 (strict) | Full TLS before any TDS traffic. Uses ALPN tds/8.0. |
| TLS-in-TDS | TLS negotiated inside the TDS PRELOGIN handshake. |
| Force Encryption | Server-mandated encryption after PRELOGIN exchange. |
| Filter | Purpose |
|---|---|
(servicePrincipalName=MSSQLSvc/*) |
Find all MSSQL SPNs in the domain |
(servicePrincipalName=MSSQLSvc/<host>*) (short + FQDN) |
Look up SPNs for a specific server |
(&(objectCategory=computer)(objectClass=computer)) |
Enumerate all domain computers (--scan-all-computers) |
(objectSid=<sid>) |
Resolve a SID to an AD principal |
(sAMAccountName=<name>) |
Resolve an account name to an AD principal |
(&(objectClass=computer)(sAMAccountName=<name>$)) |
Resolve a computer account by name |
All LDAP searches use subtree scope with 1000-result paging.
Each authentication below generates log entries on the target system.
| Event | Target | Method | Details | Conditions |
|---|---|---|---|---|
| SQL Server login | SQL Server | SQL auth (username/password in TDS LOGIN7) | Logged as a login event in SQL Server audit logs | When -u/-p supplied |
| SQL Server login | SQL Server | Windows auth (NTLM SSPI in TDS LOGIN7: Negotiate → Challenge → Authenticate) | Includes Channel Binding Token (CBT) when TLS is active. Logged as a login event in SQL Server audit logs. | When using domain credentials |
| LDAP bind | Domain controller | GSSAPI/SSPI (Kerberos) | Uses current user's Windows security context | Windows only, when no explicit LDAP credentials |
| LDAP bind | Domain controller | NTLM or Simple bind (UPN, DN, or DOMAIN\user) | Logged as an authentication event on the DC | When --ldap-user/--ldap-password supplied or SQL credentials reused |
| WinRM login | SQL Server host | NTLM or Basic auth | Logged as a Windows authentication event | Only test-epa-matrix subcommand |
| WMI/DCOM login | SQL Server host | Current user's Windows credentials | Logged as a DCOM authentication event | Windows only, during local group enumeration |
MSSQLHound does not spawn local powershell.exe processes as collection fallbacks. The only PowerShell command constructed by the Go binary is sent through WinRM for the EPA matrix workflow.
| Executable | Arguments | Purpose | Conditions |
|---|---|---|---|
powershell.exe |
-NoProfile -NonInteractive -EncodedCommand <base64> |
Remote PowerShell via WinRM: EPA registry configuration and SQL service restart on target host | Only test-epa-matrix subcommand. Executes on the remote target via WinRM. |
All queries are read-only. No data is written to any target server.
| Query | Purpose |
|---|---|
SELECT SERVERPROPERTY('ServerName'), SERVERPROPERTY('MachineName'), SERVERPROPERTY('InstanceName'), SERVERPROPERTY('ProductVersion'), SERVERPROPERTY('Edition'), ... |
Server name, version, edition |
$ claude mcp add MSSQLHound \
-- python -m otcore.mcp_server <graph>