SQL Server 安全加固的核心是收敛四条攻击面:认证面、网络面、权限面与数据面。默认安装的实例往往保留了启用的 sa 账号、允许混合认证、把 1433 端口暴露在整个内网,甚至留着 xp_cmdshell 这类可直接落地系统命令的扩展存储过程。本文给出一套可在 SQL Server 2016 及以上版本直接执行的加固流程,每一步都附 T-SQL 语句与验证方法。
适用场景
- 生产环境运行 SQL Server 2016/2017/2019/2022,长期使用默认配置,sa 账号仍处于启用状态。
- 数据库端口对内网全网段开放,应用连接串里直接用 sa 或高权限账号。
- 需要满足等保测评或客户安全审计要求,被要求提供身份鉴别、访问控制、数据加密与安全审计四类证据。
- 已做全量备份且验证过还原流程,具备变更窗口。
前置条件
- 具备 sysadmin 固定服务器角色成员权限,建议使用 Windows 域账号登录而非 sa。
- 安装 sqlcmd 或 SQL Server Management Studio(SSMS)。
- 已完成一次完整备份并确认可还原,加固过程中涉及认证方式变更,必须留退路。
- 掌握应用的连接账号清单,避免禁用错账号导致业务中断。
原理说明
SQL Server 的默认配置面向「开箱可用」,而不是「默认安全」。四类风险分别对应四个层面。
认证面的风险来自 sa 账号与混合认证模式。sa 是实例级最高权限账号且用户名固定,一旦密码被爆破或从配置文件中泄露,攻击者直接拿到 sysadmin。改用 Windows 集成认证后,实例内不再存在可远程猜解的固定账号。
网络面的风险来自端口暴露与传输明文。SQL Server 默认监听 1433 并通过 UDP 1434 的 SQL Browser 服务广播实例信息,扫描器一条 UDP 请求就能拿到实例名与版本。传输层默认不加密,内网嗅探即可还原查询内容。
权限面的风险来自 public 角色的过度授权。xp_cmdshell、OLE Automation、xp_regread 等扩展过程若保留默认执行权限,任何能连接数据库的账号都可能借此执行操作系统命令。这是从数据库权限升级到主机权限最常被利用的路径。
数据面的风险来自静态数据与备份文件未加密。数据库文件(.mdf/.ldf)与备份文件(.bak)被复制走即可在任意实例还原读取,TDE 透明加密与备份加密是应对这两个场景的手段。
操作步骤
1. 认证面:禁用 sa 并切换到 Windows 认证
-- 先重命名再禁用,避免脚本被复用猜解
ALTER LOGIN sa WITH NAME = [disabled_sa];
ALTER LOGIN [disabled_sa] DISABLE;
-- 确认当前实例是否只允许 Windows 认证(1 = 仅集成认证)
SELECT SERVERPROPERTY('IsIntegratedSecurityOnly') AS IsIntegratedOnly;
-- 若需切换为仅 Windows 认证(改后必须重启实例)
EXEC xp_instance_regwrite
N'HKEY_LOCAL_MACHINE',
N'Software\Microsoft\MSSQLServer\MSSQLServer',
N'LoginMode', REG_DWORD, 1;
切换认证模式后务必重启 SQL Server 服务生效,重启前先确认已有应用改用 Windows 账号连接,否则应用会立刻连不上。
2. 认证面:强制密码策略并清理多余登录名
-- 对仍在使用 SQL 认证的业务账号强制密码复杂度与过期策略
ALTER LOGIN [appuser] WITH CHECK_POLICY = ON;
ALTER LOGIN [appuser] WITH CHECK_EXPIRATION = ON;
-- 列出所有可登录的服务器主体,逐条核对是否必需
SELECT name, type_desc, is_disabled, create_date
FROM sys.server_principals
WHERE type IN ('S','U','G') AND name NOT LIKE '##%'
ORDER BY create_date;
-- 禁用不再使用的账号(不要直接删除,保留可追溯性)
ALTER LOGIN [old_user] DISABLE;
3. 权限面:回收 public 角色高危权限
-- 关闭高级选项才能修改 xp_cmdshell
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
-- 禁用 xp_cmdshell 与 OLE 自动化
EXEC sp_configure 'xp_cmdshell', 0;
RECONFIGURE;
EXEC sp_configure 'Ole Automation Procedures', 0;
RECONFIGURE;
-- 收紧危险扩展过程的执行权限
REVOKE EXECUTE ON xp_regread FROM public;
REVOKE EXECUTE ON xp_regwrite FROM public;
REVOKE EXECUTE ON xp_dirtree FROM public;
REVOKE EXECUTE ON xp_fileexist FROM public;
-- 关闭 CLR 集成与跨库所有权链(除非业务明确依赖)
EXEC sp_configure 'clr enabled', 0;
RECONFIGURE;
EXEC sp_configure 'cross db ownership chaining', 0;
RECONFIGURE;
核心原则是遵循最小权限:应用账号只授予对应业务库的 db_datareader 与 db_datawriter,需要执行存储过程时单独授予具体过程,绝不加入 db_owner 或 sysadmin。
4. 网络面:收敛端口并启用传输加密
# 用 netsh 查看当前监听状态
netsh advfirewall firewall show rule name=all | findstr /i "1433"
# 只放行应用服务器网段,其余全部拒绝
netsh advfirewall firewall add rule name="SQL-APPONLY" dir=in action=allow ^
protocol=TCP localport=1433 remoteip=10.10.20.0/24
netsh advfirewall firewall add rule name="SQL-BLOCK" dir=in action=block ^
protocol=TCP localport=1433
顺序很重要:先加允许规则再加全局拒绝规则,Windows 防火墙按「阻止优先、更具体优先」匹配。
同时在 SQL Server Configuration Manager 中:把 TCP Port 从 1433 改为自定义端口(如 51433);TCP Dynamic Ports 清空;Force Encryption 设为 Yes 并绑定服务器证书;考虑停止 SQL Browser 服务(UDP 1434),因为它会向任何查询者泄露实例名与端口。
5. 数据面:启用 TDE 透明加密
USE master;
-- 1) 主密钥(口令单独保管,丢失将无法恢复所有证书)
CREATE MASTER KEY ENCRYPTION BY PASSWORD = '强口令_单独保存';
GO
-- 2) 服务主密钥加密的 TDE 证书
CREATE CERTIFICATE TdeCert_Sec
WITH SUBJECT = 'TDE Certificate for production';
GO
USE AppDb;
-- 3) 数据库加密密钥
CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_256
ENCRYPTION BY SERVER CERTIFICATE TdeCert_Sec;
GO
ALTER DATABASE AppDb SET ENCRYPTION ON;
GO
关键提醒:服务器证书与服务主密钥必须立即备份到异地。只备份数据库文件而丢了证书,还原到新实例后数据将永久无法解密。
-- 备份证书与私钥(私钥口令与主密钥口令分开保管)
BACKUP CERTIFICATE TdeCert_Sec
TO FILE = 'D:\SecureBackup\TdeCert_Sec.cer'
WITH PRIVATE KEY (
FILE = 'D:\SecureBackup\TdeCert_Sec.pvk',
ENCRYPTION BY PASSWORD = '独立强口令'
);
6. 数据面与审计:备份加密与登录审计
-- 备份时启用加密与校验
BACKUP CERTIFICATE BackupCert_Sec
WITH SUBJECT = 'Certificate for encrypted backup';
BACKUP DATABASE AppDb
TO DISK = 'D:\bak\AppDb_full.bak'
WITH ENCRYPTION (ALGORITHM = AES_256, SERVER CERTIFICATE = BackupCert_Sec),
COMPRESSION, CHECKSUM, STATS = 10;
-- 服务器级审计,记录登录成功与失败
CREATE SERVER AUDIT SecAudit
TO FILE (FILEPATH = 'D:\Audit\', MAXSIZE = 512 MB, MAX_ROLLOVER_FILES = 10,
RESERVE_DISK_SPACE = OFF)
WITH (ON_FAILURE = CONTINUE,
QUEUE_DELAY = 1000);
ALTER SERVER AUDIT SecAudit WITH (STATE = ON);
CREATE SERVER AUDIT SPECIFICATION SecAuditSpec
FOR SERVER AUDIT SecAudit
ADD (FAILED_LOGIN_GROUP),
ADD (SUCCESSFUL_LOGIN_GROUP),
ADD (SERVER_ROLE_MEMBER_CHANGE_GROUP),
ADD (DATABASE_PERMISSION_CHANGE_GROUP)
WITH (STATE = ON);
配置验证
-- 1. 确认 sa 已禁用
SELECT name, is_disabled FROM sys.server_principals WHERE sid = 0x01;
-- 2. 确认认证模式为仅 Windows
SELECT SERVERPROPERTY('IsIntegratedSecurityOnly') AS IsIntegratedOnly,
SERVERPROPERTY('ProductVersion') AS Ver;
-- 3. 确认危险扩展过程已关闭
SELECT name, value_in_use FROM sys.configurations
WHERE name IN ('xp_cmdshell','Ole Automation Procedures','clr enabled');
-- 4. 确认 TDE 已启用且为加密状态
SELECT DB_NAME(database_id) AS db, encryption_state_desc, key_algorithm
FROM sys.dm_database_encryption_keys;
-- 5. 确认审计已开启
SELECT name, is_state_enabled FROM sys.server_audits;
# 6. 从外部做端口探测,确认只放行了应用网段
nmap -Pn -p 1433,1434 --script ms-sql-info 10.10.30.10
# 7. 检查 SQL Browser 是否仍在应答实例信息
nmap -Pn -sU -p 1434 10.10.30.10
第 6 条命令若从非应用网段发起,应当显示 1433 为 filtered 而非 open;第 7 条应显示 1434 关闭或 filtered。这两项是等保测评中网络访问控制最直接的取证方式。
常见问题
FAQ 1:改了端口之后,客户端连不上数据库怎么办?
按三步排查。第一,连接串必须写成「服务器地址,端口号」的形式,例如 10.10.30.10,51433,逗号是英文半角;第二,如果应用只写了实例名而没有端口,客户端会依赖 UDP 1434 的 SQL Browser 服务做解析,而此时该服务已被停止,解析必然失败,解决办法是改回「地址,端口」写法;第三,检查 Windows 防火墙与上游网络设备是否放行了新端口,用 telnet 或 Test-NetConnection 从应用服务器验证端口连通性。
FAQ 2:TDE 加密后,备份文件拿到测试环境还原时报「找不到证书」,怎么处理?
这是 TDE 最常见的运维事故。数据库加密密钥由服务器证书保护,证书又由服务主密钥保护,三层都只存在于原实例。正确做法是在生产实例执行 BACKUP CERTIFICATE … WITH PRIVATE KEY,把 .cer 与 .pvk 两个文件连同私钥口令一起异地保存;还原时先在测试实例执行 CREATE MASTER KEY 与 CREATE CERTIFICATE FROM FILE,再还原数据库。加固完成后建议立刻做一次「导出证书 → 新实例还原 → 验证可读」的完整演练,不要等到真需要恢复时才发现证书没备份。
FAQ 3:业务依赖 xp_cmdshell 调用外部程序,禁用会不会影响运行?
先评估替代方案再动手。常见替代有两种:一是把外部调用改为 SQL Server 代理作业(SQL Server Agent Job),由代理服务以专用低权限账号执行,权限边界更清晰且留下执行历史;二是改为应用层直接调用,把系统交互从数据库剥离出去。如果短期无法改造,退而求其次是保留 xp_cmdshell 但严格收权:REVOKE EXECUTE ON xp_cmdshell FROM public,只对单一专用代理登录名授权,并在审计规范中加入对应审计项,确保每次调用都有记录。
总结
SQL Server 加固的优先级顺序是「先认证、再权限、后网络、最后加密」。认证与权限的改动成本最低、收益最高,禁用 sa 与回收 public 角色高危权限可以在一个变更窗口内完成;网络收敛需要与应用团队确认连接方式;TDE 涉及证书管理,实施前必须先演练还原流程。四条面全部收敛后,这个实例对外呈现的攻击面从「一个可被猜解的固定超级账号 + 全网开放端口 + 可执行系统命令的扩展过程」压缩为「仅应用网段可达的自定义端口 + Windows 认证 + 最小权限账号 + 加密传输与静态数据」,这才是符合等保与安全审计要求的基线状态。