Most SQL Server security problems aren't exotic. They're a login with far more rights than it needs, a connection traveling in clear text, or a table anyone with access can read top to bottom. You close most of the real risk by getting a few fundamentals right before reaching for the advanced features — so that's where this starts.
The same principle that drives good performance work applies here: diagnosis before prescription. Know what access exists and how data moves before you start hardening. You can't protect what you haven't mapped.
Authentication and role-based access — who gets in, and what they can do
Security starts at the door. Prefer Windows authentication or Microsoft Entra ID (in Azure SQL) over SQL Server logins wherever you can — it hands identity to a system already built to manage it, with lockout, expiry, and central control. Where SQL logins are unavoidable, enforce the password policy (CHECK_POLICY and CHECK_EXPIRATION), and disable or rename the built-in sa account rather than leaving a known target with a password on it.
Getting someone in the door is only half of it. The other half is role-based access built on least privilege — everyone gets exactly the rights their job needs, and nothing spare:
- Grant through roles, not to individual users — custom database roles for each function, so access is consistent and easy to review.
- Keep the powerful memberships small.
sysadmin,db_owner, andCONTROL SERVERshould be rare and deliberate, not a convenience handed out to make an error message go away. - Scope grants to the schema or object, not the whole database, and give applications their own least-privileged accounts instead of a shared high-privilege one.
- Practice separation of duties — the account that runs the application isn't the account that administers it.
The test is simple: if a login were compromised tomorrow, how much could it touch? Least privilege is the difference between an incident and a catastrophe.
Network — narrowing the front door and encrypting the path
Once you've decided who gets in, control how they connect. Two things matter most here.
Force connection encryption (SSL/TLS). Data moving between the application and SQL Server should never travel in clear text. Install a valid certificate, force encryption at the instance, and require it on the client side too — Encrypt=true with TrustServerCertificate=false, so clients actually validate the certificate instead of trusting anything that answers. Standardize on TLS 1.2 or 1.3 and disable the legacy protocols at the OS. (SQL Server 2022 adds strict encryption over TDS 8.0 for an even stronger posture.) If you run Availability Groups, mirroring, or replication, remember those endpoints are encrypted separately — don't leave them behind.
Shrink the network surface. The instance shouldn't be reachable from anywhere it doesn't need to be:
- Firewall the database off from general network access; expose it only to the hosts that legitimately talk to it.
- Consider a non-default port and hiding the instance to cut down on opportunistic scanning.
- In the cloud, keep SQL off the public internet entirely — private endpoints or VNet integration in Azure, tight security groups and private subnets on AWS RDS. Port 1433 open to the world is an invitation, not a configuration.
In-database protection — guarding the data once someone's inside
Authentication and network controls keep the wrong people out. But not everyone with legitimate access should see everything, and that's what in-database protection is for — controlling exposure at the row, column, and data level.
- Row-Level Security (RLS) filters which rows a user can see based on who they are — enforced by the engine through a security policy and an inline function, so a shared table can serve many tenants or departments while each one only ever reads its own rows, without every query having to remember a
WHEREclause. - Dynamic Data Masking (DDM) obscures sensitive values — showing
XXXX-1234instead of a full card number — for users who don't need the real thing. It's useful for keeping casual eyes off sensitive fields, but be honest about what it is: obfuscation at display time, not a security boundary. A user with ad-hoc query access can infer around it, and Microsoft says as much, so treat DDM as one layer, not the whole answer. - Data classification and sensitivity labels come first, really. Before you can protect regulated data, you have to know where it lives. Discovering and labeling the columns that hold PII, financial, or health data turns "we think it's secure" into a map you can act on — and it's what auditors ask for.
Together these move protection closer to the data itself, so a broad grant or an over-curious user doesn't automatically mean full exposure. For the strongest column-level protection — hiding data even from the DBA — see encryption at rest in part three.
Continue the series: Part 2 — Auditing and Threat Detection → · Part 3 — Encryption at Rest →
If you'd rather have a senior DBA review and harden your environment, that's what I do. See SQL Server DBA services, review real client results, or get in touch.
References
- Configure SQL Server for encrypting connections (forced TLS) — Microsoft Learn. Configure SQL Server Database Engine for encrypting connections
- SQL Server security best practices — Microsoft Learn. SQL Server security best practices
- Row-Level Security — Microsoft Learn. Row-level security
- Dynamic Data Masking — Microsoft Learn. Dynamic data masking
- Microsoft Entra authentication for SQL Server — Microsoft Learn. Microsoft Entra authentication for SQL Server