Database Security trong SQL Server
1. Security Overview
SQL Server Security Layers
Security Layers
Authentication
Windows Auth
SQL Server Auth
Mixed Mode
Authorization
Roles
Permissions
Schema Permissions
Encryption
TDE
Column Encryption
Always Encrypted
Auditing
SQL Server Audit
Change Tracking
2. Authentication
2.1 Windows Authentication (Recommended)
SQL
1-- Windows Authentication dùng Active Directory2-- More secure: No passwords stored in SQL Server3-- Single sign-on: Use Windows credentials45-- Create login from Windows user/group6CREATE LOGIN [DOMAIN\UserName] FROM WINDOWS;7CREATE LOGIN [DOMAIN\DBAGroup] FROM WINDOWS;89-- Check current authentication mode10SELECT SERVERPROPERTY('IsIntegratedSecurityOnly') AS WindowsAuthOnly;11-- 1 = Windows only, 0 = Mixed mode2.2 SQL Server Authentication
SQL
1-- SQL Auth: Username/password stored in SQL Server2-- Required for non-Windows clients34-- Create SQL login5CREATE LOGIN AppUser 6WITH PASSWORD = 'StrongP@ssw0rd!',7 DEFAULT_DATABASE = AdventureWorks2019,8 CHECK_POLICY = ON, -- Enforce Windows password policy9 CHECK_EXPIRATION = ON; -- Password expires1011-- Change password12ALTER LOGIN AppUser WITH PASSWORD = 'NewStrongP@ssw0rd!';1314-- Disable/Enable login15ALTER LOGIN AppUser DISABLE;16ALTER LOGIN AppUser ENABLE;1718-- Lock account after failed attempts (via policy)19ALTER LOGIN AppUser WITH CHECK_POLICY = ON;2.3 Login vs User
Text
1┌─────────────────────────────────────────────────────┐2│ SQL Server │3│ ┌──────────────┐ │4│ │ LOGIN │ ← Server-level (can connect) │5│ └──────────────┘ │6│ │ │7│ ▼ │8│ ┌──────────────────────────────────────────────┐ │9│ │ Database │ │10│ │ ┌──────────┐ │ │11│ │ │ USER │ ← Database-level (permissions) │ │12│ │ └──────────┘ │ │13│ └──────────────────────────────────────────────┘ │14└─────────────────────────────────────────────────────┘SQL
1-- 1. Create Server Login2CREATE LOGIN AppLogin WITH PASSWORD = 'P@ssw0rd123!';34-- 2. Create Database User mapped to Login5USE AdventureWorks2019;6CREATE USER AppUser FOR LOGIN AppLogin;78-- Or create without login (contained database)9CREATE USER ContainedUser WITH PASSWORD = 'P@ssw0rd123!';3. Authorization - Roles & Permissions
3.1 Server Roles (Fixed)
| Role | Description |
|---|---|
| sysadmin | Full access to everything |
| serveradmin | Server configuration |
| securityadmin | Manage logins |
| processadmin | Kill processes |
| setupadmin | Linked servers |
| bulkadmin | BULK INSERT |
| diskadmin | Disk files |
| dbcreator | Create databases |
| public | Default role (everyone) |
SQL
1-- Add login to server role2ALTER SERVER ROLE sysadmin ADD MEMBER [DOMAIN\DBAUser];3ALTER SERVER ROLE dbcreator ADD MEMBER DevLead;45-- Check server role membership6SELECT 7 sp.name AS LoginName,8 sp.type_desc,9 sr.name AS ServerRole10FROM sys.server_principals sp11JOIN sys.server_role_members srm ON sp.principal_id = srm.member_principal_id12JOIN sys.server_principals sr ON srm.role_principal_id = sr.principal_id;3.2 Database Roles (Fixed)
| Role | Description |
|---|---|
| db_owner | Full access to database |
| db_accessadmin | Add/remove users |
| db_securityadmin | Manage permissions |
| db_ddladmin | Run DDL commands |
| db_datawriter | INSERT, UPDATE, DELETE |
| db_datareader | SELECT all tables |
| db_backupoperator | Backup database |
| db_denydatawriter | Cannot modify data |
| db_denydatareader | Cannot read data |
SQL
1-- Add user to database role2ALTER ROLE db_datareader ADD MEMBER AppUser;3ALTER ROLE db_datawriter ADD MEMBER AppUser;45-- Check database role membership6SELECT 7 dp.name AS UserName,8 dp.type_desc,9 r.name AS RoleName10FROM sys.database_principals dp11JOIN sys.database_role_members drm ON dp.principal_id = drm.member_principal_id12JOIN sys.database_principals r ON drm.role_principal_id = r.principal_id;3.3 Custom Database Roles
SQL
1-- Create custom role2CREATE ROLE SalesReporting;34-- Grant permissions to role5GRANT SELECT ON SCHEMA::Sales TO SalesReporting;6GRANT EXECUTE ON Sales.usp_GetOrders TO SalesReporting;78-- Add users to custom role9ALTER ROLE SalesReporting ADD MEMBER ReportUser;10ALTER ROLE SalesReporting ADD MEMBER AnalystUser;1112-- Remove user from role13ALTER ROLE SalesReporting DROP MEMBER OldUser;1415-- Drop role16DROP ROLE SalesReporting;4. Permission Management
4.1 GRANT, DENY, REVOKE
SQL
1-- GRANT: Give permission2GRANT SELECT ON Sales.Customer TO AppUser;3GRANT INSERT, UPDATE ON Sales.[Order] TO AppUser;4GRANT EXECUTE ON Sales.usp_CreateOrder TO AppUser;56-- DENY: Explicitly block (overrides GRANT)7DENY DELETE ON Sales.Customer TO AppUser;89-- REVOKE: Remove permission (neither GRANT nor DENY)10REVOKE SELECT ON Sales.Customer FROM AppUser;1112-- Permission hierarchy13-- DENY > GRANT > REVOKE (no permission)4.2 Schema-Level Permissions
SQL
1-- Grant access to all objects in schema2GRANT SELECT ON SCHEMA::Sales TO ReportingRole;3GRANT EXECUTE ON SCHEMA::Sales TO AppRole;45-- More specific6GRANT SELECT, INSERT, UPDATE ON SCHEMA::Sales TO AppRole;7DENY DELETE ON SCHEMA::Sales TO AppRole;4.3 Object-Level Permissions
SQL
1-- Table permissions2GRANT SELECT (CustomerID, FirstName, LastName) ON Customer.Customer TO LimitedUser;3-- Only specific columns!45-- View permissions6GRANT SELECT ON Sales.vw_OrderSummary TO ReportingUser;78-- Stored procedure permissions9GRANT EXECUTE ON Sales.usp_GetOrders TO AppUser;1011-- With GRANT option (user can grant to others)12GRANT SELECT ON Sales.Customer TO TeamLead WITH GRANT OPTION;4.4 View Effective Permissions
SQL
1-- Check user's permissions2SELECT * FROM fn_my_permissions(NULL, 'DATABASE');3SELECT * FROM fn_my_permissions('Sales.Customer', 'OBJECT');45-- Check specific user's permissions6EXECUTE AS USER = 'AppUser';7SELECT * FROM fn_my_permissions('Sales.Customer', 'OBJECT');8REVERT;910-- All permissions for a user11SELECT 12 dp.name AS UserName,13 o.name AS ObjectName,14 p.permission_name,15 p.state_desc16FROM sys.database_permissions p17JOIN sys.database_principals dp ON p.grantee_principal_id = dp.principal_id18LEFT JOIN sys.objects o ON p.major_id = o.object_id19WHERE dp.name = 'AppUser';5. Row-Level Security (RLS)
SQL
1-- Create security predicate function2CREATE FUNCTION Security.fn_CustomerFilter(@CustomerID INT)3RETURNS TABLE4WITH SCHEMABINDING5AS6RETURN 7 SELECT 1 AS Result8 WHERE @CustomerID = (9 SELECT CustomerID 10 FROM Customer.Customer 11 WHERE Email = USER_NAME()12 )13 OR USER_NAME() = 'dbo'; -- Admin sees all14GO1516-- Create security policy17CREATE SECURITY POLICY CustomerPolicy18ADD FILTER PREDICATE Security.fn_CustomerFilter(CustomerID) 19ON Sales.[Order]20WITH (STATE = ON);2122-- Now each user only sees their own orders23-- User 'customer1@email.com' sees only their orders6. Data Encryption
6.1 Transparent Data Encryption (TDE)
SQL
1-- TDE encrypts data at rest (on disk)2-- Automatic, transparent to applications34-- 1. Create master key5USE master;6CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'MasterKeyP@ssw0rd!';78-- 2. Create certificate9CREATE CERTIFICATE TDECert WITH SUBJECT = 'TDE Certificate';1011-- 3. Create database encryption key12USE AdventureWorks2019;13CREATE DATABASE ENCRYPTION KEY14WITH ALGORITHM = AES_25615ENCRYPTION BY SERVER CERTIFICATE TDECert;1617-- 4. Enable encryption18ALTER DATABASE AdventureWorks2019 SET ENCRYPTION ON;1920-- Check encryption status21SELECT 22 db.name,23 db.is_encrypted,24 dek.encryption_state,25 dek.percent_complete26FROM sys.databases db27LEFT JOIN sys.dm_database_encryption_keys dek ON db.database_id = dek.database_id;6.2 Column-Level Encryption
SQL
1-- Encrypt specific columns23-- 1. Create symmetric key4CREATE SYMMETRIC KEY SSN_Key5WITH ALGORITHM = AES_2566ENCRYPTION BY PASSWORD = 'SymKeyP@ssw0rd!';78-- 2. Create table with encrypted column9CREATE TABLE HR.EmployeeSensitive (10 EmployeeID INT PRIMARY KEY,11 SSN VARBINARY(256), -- Encrypted data stored as binary12 Salary VARBINARY(256)13);1415-- 3. Insert encrypted data16OPEN SYMMETRIC KEY SSN_Key DECRYPTION BY PASSWORD = 'SymKeyP@ssw0rd!';1718INSERT INTO HR.EmployeeSensitive (EmployeeID, SSN, Salary)19VALUES (20 1,21 EncryptByKey(Key_GUID('SSN_Key'), '123-45-6789'),22 EncryptByKey(Key_GUID('SSN_Key'), '75000')23);2425CLOSE SYMMETRIC KEY SSN_Key;2627-- 4. Read decrypted data28OPEN SYMMETRIC KEY SSN_Key DECRYPTION BY PASSWORD = 'SymKeyP@ssw0rd!';2930SELECT 31 EmployeeID,32 CONVERT(VARCHAR(20), DecryptByKey(SSN)) AS SSN,33 CONVERT(VARCHAR(20), DecryptByKey(Salary)) AS Salary34FROM HR.EmployeeSensitive;3536CLOSE SYMMETRIC KEY SSN_Key;6.3 Always Encrypted (Client-Side)
SQL
1-- Always Encrypted: Keys stored outside SQL Server2-- Data encrypted/decrypted by client application3-- SQL Server never sees plaintext45-- Create column master key (references key in Windows Certificate Store or Azure Key Vault)6CREATE COLUMN MASTER KEY CMK_Auto7WITH (8 KEY_STORE_PROVIDER_NAME = 'MSSQL_CERTIFICATE_STORE',9 KEY_PATH = 'CurrentUser/My/Certificate_Thumbprint'10);1112-- Create column encryption key13CREATE COLUMN ENCRYPTION KEY CEK_Auto14WITH VALUES (15 COLUMN_MASTER_KEY = CMK_Auto,16 ALGORITHM = 'RSA_OAEP',17 ENCRYPTED_VALUE = 0x...18);1920-- Create table with encrypted columns21CREATE TABLE HR.EmployeeSecure (22 EmployeeID INT PRIMARY KEY,23 SSN VARCHAR(11) ENCRYPTED WITH (24 COLUMN_ENCRYPTION_KEY = CEK_Auto,25 ENCRYPTION_TYPE = DETERMINISTIC, -- Can be used in WHERE26 ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'27 ),28 Salary INT ENCRYPTED WITH (29 COLUMN_ENCRYPTION_KEY = CEK_Auto,30 ENCRYPTION_TYPE = RANDOMIZED, -- More secure, cannot search31 ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'32 )33);7. SQL Injection Prevention
7.1 What is SQL Injection?
SQL
1-- Vulnerable code (DO NOT DO THIS!)2DECLARE @sql NVARCHAR(500);3SET @sql = 'SELECT * FROM Users WHERE Username = ''' + @UserInput + '''';4EXEC(@sql);56-- If @UserInput = "admin'; DROP TABLE Users; --"7-- Becomes: SELECT * FROM Users WHERE Username = 'admin'; DROP TABLE Users; --'8-- TABLE DROPPED!7.2 Prevention Techniques
SQL
1-- 1. Use Parameterized Queries / Stored Procedures2CREATE PROCEDURE usp_GetUser3 @Username NVARCHAR(50)4AS5BEGIN6 SELECT * FROM Users WHERE Username = @Username;7 -- Parameter is treated as data, not code!8END;910-- 2. If dynamic SQL is necessary, use sp_executesql with parameters11DECLARE @sql NVARCHAR(500);12SET @sql = N'SELECT * FROM Users WHERE Username = @User';1314EXEC sp_executesql @sql, 15 N'@User NVARCHAR(50)', 16 @User = @UserInput; -- Parameterized!1718-- 3. Use QUOTENAME for identifiers19DECLARE @TableName NVARCHAR(128) = 'Users';20SET @sql = N'SELECT * FROM ' + QUOTENAME(@TableName);21-- QUOTENAME escapes special characters2223-- 4. Validate and whitelist inputs24IF @TableName NOT IN ('Users', 'Products', 'Orders')25BEGIN26 RAISERROR('Invalid table name', 16, 1);27 RETURN;28END8. Auditing
8.1 SQL Server Audit
SQL
1-- Create server audit2CREATE SERVER AUDIT SecurityAudit3TO FILE (FILEPATH = 'C:\SQLAudit\', MAXSIZE = 100MB)4WITH (ON_FAILURE = CONTINUE);56ALTER SERVER AUDIT SecurityAudit WITH (STATE = ON);78-- Create database audit specification9USE AdventureWorks2019;1011CREATE DATABASE AUDIT SPECIFICATION SalesAudit12FOR SERVER AUDIT SecurityAudit13ADD (SELECT, INSERT, UPDATE, DELETE ON Sales.[Order] BY public),14ADD (EXECUTE ON SCHEMA::Sales BY public)15WITH (STATE = ON);1617-- View audit logs18SELECT 19 event_time,20 action_id,21 succeeded,22 session_server_principal_name,23 database_name,24 schema_name,25 object_name,26 statement27FROM sys.fn_get_audit_file('C:\SQLAudit\*.sqlaudit', NULL, NULL);8.2 Change Data Capture (CDC)
SQL
1-- Enable CDC for database2EXEC sys.sp_cdc_enable_db;34-- Enable CDC for table5EXEC sys.sp_cdc_enable_table6 @source_schema = 'Sales',7 @source_name = 'Order',8 @role_name = 'cdc_Admin',9 @capture_instance = 'Sales_Order',10 @supports_net_changes = 1;1112-- Query changes13SELECT * FROM cdc.fn_cdc_get_all_changes_Sales_Order(14 @from_lsn, @to_lsn, 'all'15);9. Security Best Practices
9.1 Principle of Least Privilege
SQL
1-- ❌ Bad: Give full access2ALTER ROLE db_owner ADD MEMBER AppUser;34-- ✅ Good: Only necessary permissions5CREATE ROLE AppRole;6GRANT SELECT ON SCHEMA::Sales TO AppRole;7GRANT INSERT, UPDATE ON Sales.[Order] TO AppRole;8GRANT EXECUTE ON Sales.usp_CreateOrder TO AppRole;9ALTER ROLE AppRole ADD MEMBER AppUser;9.2 Security Checklist
markdown
1## SQL Server Security Checklist2 3### Authentication4- [ ] Use Windows Authentication when possible5- [ ] Strong password policy for SQL logins6- [ ] Disable SA account or rename it7- [ ] Remove unnecessary logins8 9### Authorization10- [ ] Use custom roles instead of db_owner11- [ ] Grant minimum required permissions12- [ ] Use schema-level permissions13- [ ] Regular permission reviews14 15### Encryption16- [ ] Enable TDE for production databases17- [ ] Encrypt sensitive columns18- [ ] Encrypt backups19- [ ] Secure connection strings20 21### Auditing22- [ ] Enable SQL Server Audit23- [ ] Monitor login failures24- [ ] Track sensitive data access25- [ ] Regular audit log reviews26 27### Network28- [ ] Firewall rules (limit access)29- [ ] Use encrypted connections (TLS)30- [ ] Disable unnecessary protocols31- [ ] Hide SQL Server instance32 33### Application34- [ ] Parameterized queries only35- [ ] No dynamic SQL with user input36- [ ] Input validation37- [ ] Error message handling (don't expose details)10. AdventureWorks Security Setup Example
SQL
1-- Example: Setup roles for AdventureWorks application23-- 1. Create roles4CREATE ROLE SalesRole;5CREATE ROLE HRRole;6CREATE ROLE ReportingRole;78-- 2. Sales permissions9GRANT SELECT, INSERT, UPDATE ON SCHEMA::Sales TO SalesRole;10GRANT SELECT ON SCHEMA::Production TO SalesRole;11GRANT EXECUTE ON SCHEMA::Sales TO SalesRole;12DENY DELETE ON SCHEMA::Sales TO SalesRole;1314-- 3. HR permissions15GRANT SELECT, INSERT, UPDATE ON SCHEMA::HumanResources TO HRRole;16GRANT SELECT ON SCHEMA::Person TO HRRole;17DENY SELECT ON HumanResources.EmployeePayHistory TO SalesRole;1819-- 4. Reporting permissions (read-only)20GRANT SELECT ON SCHEMA::Sales TO ReportingRole;21GRANT SELECT ON SCHEMA::Production TO ReportingRole;22GRANT SELECT ON SCHEMA::Person TO ReportingRole;2324-- 5. Create users and assign roles25CREATE USER SalesApp FOR LOGIN SalesAppLogin;26CREATE USER HRApp FOR LOGIN HRAppLogin;27CREATE USER ReportService FOR LOGIN ReportServiceLogin;2829ALTER ROLE SalesRole ADD MEMBER SalesApp;30ALTER ROLE HRRole ADD MEMBER HRApp;31ALTER ROLE ReportingRole ADD MEMBER ReportService;Tiếp theo
Bài tiếp theo: Complete Project - áp dụng tất cả kiến thức để thiết kế database hoàn chỉnh cho một dự án thực tế!
