# 25、SQLServer数据库加固

> Microsoft SQL Server 数据库等保三级安全加固手册（SQL Server加固），覆盖 2012~2022 Windows 与 Linux 双部署：sa 改名禁用与 sysadmin 收敛、CHECK_POLICY/CHECK_EXPIRATION 口令策略与 Linux 差异、登录审核与 18456 失败登录、LOGON 触发器、xp_cmdshell/Ole Automation/CLR strict security 高危能力关闭、guest 账户 REVOKE CONNECT、强制加密 Force Encryption 与 HideInstance、mssql-conf TLS 设置、TDE 与 Always Encrypted、SQL Server Audit 审计组配置与留存、msdb.dbo.backupset 备份核查与 RESTORE VERIFYONLY、生命周期与 ESU 口径，每节附核查命令、SSMS 界面路径与预期现象。

---

LLMS index: [llms.txt](/wikis/llms.txt)

---

> 定位：SQL Server 2012~2022 等保三级安全加固手册：按 00~11 编号分节覆盖官方补丁管理、sa 与 sysadmin 账户治理、口令复杂度与有效期、登录失败处理与登录审核、权限最小化与高危能力关闭、网络与传输加密（含 TDE）、SQL Server Audit 审计、备份恢复、剩余信息保护、Windows/Linux 双平台差异与版本生命周期，每节附核查命令、SSMS 界面路径、PowerShell/CMD 口径与测评项对照表。
>
> 适用版本：SQL Server 2012 / 2014 / 2016 / 2019 / 2022（2017 命令与 2019 同代，差异见 11 节速查表；Windows 与 Linux 双部署，平台差异集中写在 09 节）。
> 配套测评：[05、SQL Server数据库测评](../../../gradeProtection/系统管理软件平台/05sql-server数据库测评/)、[05-SQL Server 测评命令单](../../../gradeProtection/系统管理软件平台/数据库测评命令/05-sql-server/)。
>
> 使用说明：
>
> - 本文为**加固操作手册**：所有变更都会修改实例配置，可能中断业务连接、需要重启 SQL Server 服务或引发客户端重连，实施前必须完成变更审批、确认业务窗口、备份原配置（实例配置导出、注册表关键项、master/msdb 等系统库备份与业务数据备份），并准备**可执行的回滚预案**。
> - 先在测试环境或灰度实例验证，确认无业务影响后再批量推广；每完成一项立即用文中「核查方法」命令或界面复核生效——配置已下发不等于策略已生效（如登录审核与 Force Encryption 均需**重启 SQL Server 服务**、CHECK_POLICY 需 Windows/域侧账户策略配合）。
> - 示例中的登录名、口令、路径、端口均为演示值（如 `PleaseChange@123`、`E:\SQLAudit\`、`1433`），现场须替换为符合本单位口令策略与网络规划的真实值，**严禁直接沿用文中示例口令**；对外发布或归档时须对内网地址与账户信息脱敏。
> - 命令不存在、视图或参数与本文不一致时，先用 `select @@version;` 与 `serverproperty('ProductLevel')` 确认版本与补丁级别，再查阅对应版本官方文档换用等效命令；**版本差异不得直接作为「无法整改」的结论**，须给出替代措施并评估其实际效果。
> - 涉及 sa 禁用、sysadmin 收敛、登录触发器、强制加密与端口收敛的变更存在锁死自身的风险：务必先创建并验证一条替代管理员通道（另一 sysadmin 账户、Windows 身份验证账户或专用管理员连接 DAC）后再实施。
> - 加固完成后按「16、安全评估加固记录表3.0」逐项留痕（整改前后回显、操作人、时间、验证结论、回退情况），并纳入复测；测评判定口径以 GB/T 28448-2019 与《高风险判定指引》为准，本文的「加固要点」不构成最终测评结论。
>
> 不适用标识说明：
>
> - 使用 `【不适用】` 明确标记现场可判定为不适用的控制点，并写明判定依据与承载该能力的上位组件。
> - 依据 GB/T 28448-2019「按测评对象实际承载功能与数据处理范围判定」原则：控制能力由堡垒机、数据库审计系统、域控制器、日志审计系统或云托管平台（RDS/Azure SQL）承载时，应注明测评单元边界后判定不适用或转由上位组件核查，不得机械按缺失判不符合。
> - 产品版本确实不提供该能力（如 Express/Web 版不含 TDE、Linux 平台无 Windows 密码策略 API）时，须核查替代措施并按替代措施的实际效果定档，不得直接判不适用；已停止官方支持的版本应同时提出升级或 ESU 补偿控制建议。

## 测评项对照表

| 控制点（GB/T 22239-2019 安全计算环境-数据库） | 对应章节 |
| --- | --- |
| 身份鉴别：口令复杂度/有效期 | 01、02、03 |
| 身份鉴别：登录失败处理 | 03 |
| 身份鉴别：远程管理防窃听 | 05 |
| 访问控制：账户最小化、默认账户治理 | 01、04 |
| 安全审计：审计覆盖、留存与保护 | 03、06 |
| 入侵防范：高危能力关闭、端口与服务收敛、补丁管理 | 00、04、05 |
| 数据完整性/数据保密性 | 05 |
| 数据备份恢复 | 07 |
| 剩余信息保护 | 08 |

## 00 关注官方安全更新公告

> **对应控制点**：GB/T 22239-2019 8.1.4.4 入侵防范 a)~f)（最小安装、端口与服务收敛、危险能力关闭、漏洞与补丁管理）
>
> **加固要点**：建立版本与补丁台账，跟踪 SQL Server 更新中心与 MSRC 安全公告，按变更窗口安装最新累积更新（CU）或 GDR 安全更新；SQL Server 2012/2014 已终止扩展支持、2016 于 2026-07-14 到期（10 节），到期版本须提出升级或 ESU 计划；同一主机按最小化原则只保留业务所需的实例、组件与服务（SQL Server Agent、SQL Server Browser、Launchpad 等不用即禁用），实例不得同时承载无关业务；监听端口经主机防火墙与边界策略双重限制到应用服务器与运维堡垒机，禁止对办公终端区或互联网全开放。
>
> **验证方法**：`select @@version;` 与 `SERVERPROPERTY` 版本属性回显（对照更新中心的最新 CU/GDR 构建号）、补丁安装与变更记录、漏洞扫描报告、实例与 Windows 服务清单截图、防火墙与边界策略。

<div class="alert alert-warning" role="alert"><div class="h4 alert-heading" role="heading">高风险提示</div>


数据库监听 `0.0.0.0` 且 1433 端口经边界策略直接对互联网或办公终端区开放，同时存在弱口令或默认口令时，按《高风险判定指引》可直接判高风险；已停止官方安全更新且未订阅 ESU 的版本（2012、2014、2026-07 后的 2016）承载重要业务，按高风险线索记录并提出升级/补偿控制建议。

判定口径详见 [22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)。

</div>


官方更新公告与构建对照：SQL Server 更新中心 https://learn.microsoft.com/en-us/troubleshoot/sql/releases/download-and-install-latest-updates （全量构建表亦可用 aka.ms/sqlserverbuilds 的 Excel 下载）；安全公告 https://www.msrc.microsoft.com/update-guide 。

**核查方法**

```sql
select @@version;                                        -- 版本、构建号与系统信息一行串
select
  serverproperty('ProductVersion')         as ProductVersion,       -- 15.0.4480.2 形式
  serverproperty('ProductLevel')           as ProductLevel,         -- RTM / SP1 / SP2 / SP3
  serverproperty('ProductUpdateLevel')     as ProductUpdateLevel,   -- CU32 / NULL
  serverproperty('ProductUpdateReference') as ProductUpdateReference, -- 对应 KB 号
  serverproperty('Edition')                as Edition;              -- Standard / Enterprise...
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">ProductVersion  ProductLevel  ProductUpdateLevel  ProductUpdateReference  Edition
</span></span><span class="line"><span class="cl">--------------  ------------  ------------------  ----------------------  ---------------
</span></span><span class="line"><span class="cl">15.0.4480.2     RTM           CU32                KB5102335               Enterprise Edition (64-bit)
</span></span></code></pre></div>
</details>


SSMS 口径：对象资源管理器右键实例 > 属性 > 常规页，查看版本与操作系统信息。
PowerShell/CMD 口径（服务与补丁清单）：

```powershell
Get-Service MSSQLSERVER,SQLSERVERAGENT,SQLBrowser | Format-Table Name,Status,StartType
Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 10 HotFixID,InstalledOn
```

- 预期现象：实例处于受支持版本且为官方渠道可查的最新 CU 或 GDR 构建；无已停止支持的版本承载核心业务；无关 Windows 服务已禁用。

## 01 sa 账户与 sysadmin 角色治理

> **对应控制点**：GB/T 22239-2019 8.1.4.1 身份鉴别 a)d)（账户标识唯一、组合鉴别）、8.1.4.2 访问控制 a)c)（账户与权限及时回收、默认账户治理）
>
> **加固要点**：Windows 身份验证是默认模式且官方明确比 SQL Server 身份验证更安全（口令不进连接串、复用 Windows/AD 的密码与锁定策略、支持 Kerberos），三级系统应优先使用 Windows/AD 认证并为运维、应用分别建域账户组；确需混合模式时逐项说明业务理由，且 sa 必须**改名或禁用**（`sa` 是公开的默认账户、长期是口令猜测目标，官方明确"除非应用要求否则不要启用"）；sysadmin 固定服务器角色成员最小化并实名登记，`CONTROL SERVER` 权限持有者与 sysadmin 同级一并核查；数据库运行账户保持安装默认的虚拟账户（`NT SERVICE\MSSQLSERVER`）或改用组托管服务账户 gMSA（2014 起），不以域管理员或本地管理员运行；`NT SERVICE\MSSQLSERVER`、`NT AUTHORITY\SYSTEM` 等内置服务 SID 登录是安装过程默认授予 sysadmin 的系统内部账户，知悉台账即可，不得随意删除。
>
> **验证方法**：认证模式回显（`serverproperty('IsIntegratedSecurityOnly')`，1=仅 Windows 认证）、sa 状态与改名结果、sysadmin 成员清单与账号台账比对、服务运行账户回显（`Get-CimInstance Win32_Service`）、三权分立分工说明（系统管理员/安全保密管理员/安全审计员分持不同账户）。

<div class="alert alert-warning" role="alert"><div class="h4 alert-heading" role="heading">高风险提示</div>


sa 使用空口令、弱口令或口令长期未更换，或沿用安装默认口令的管理账户对全网乃至互联网开放且无来源限制，按《高风险判定指引》可直接判高风险；sysadmin 由多个共享账户或离职人员持有、无变更记录时，按高风险线索记录。

判定口径详见 [22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)。

</div>


**核查方法**

```sql
-- 认证模式：1 = 仅 Windows 认证，0 = 混合模式
select serverproperty('IsIntegratedSecurityOnly') as WindowsAuthOnly;

-- 登录清单与 sa 状态
select name, type_desc, is_disabled, create_date, modify_date
from sys.server_principals
where type in ('S','U','K');                 -- SQL_LOGIN / WINDOWS_LOGIN / CERTIFICATE_MAPPED 之外先看主体

-- sysadmin 角色成员（联查）
select roles.name as ServerRole, members.name as MemberName, members.type_desc
from sys.server_role_members as srm
join sys.server_principals as roles
  on srm.role_principal_id = roles.principal_id
join sys.server_principals as members
  on srm.member_principal_id = members.principal_id
where roles.name = 'sysadmin';

-- 与 sysadmin 等级的 CONTROL SERVER 授权（固定服务器角色权限不在此视图，需另行核对角色成员）
select pr.name, pe.state_desc, pe.permission_name
from sys.server_principals as pr
join sys.server_permissions as pe
  on pe.grantee_principal_id = pr.principal_id
where pe.permission_name = 'CONTROL SERVER';

exec sp_helpsrvrolemember 'sysadmin';        -- 交叉核对
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">WindowsAuthOnly
</span></span><span class="line"><span class="cl">---------------
</span></span><span class="line"><span class="cl">0
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ServerRole  MemberName            type_desc
</span></span><span class="line"><span class="cl">----------  --------------------  ---------------
</span></span><span class="line"><span class="cl">sysadmin    sa                    SQL_LOGIN
</span></span><span class="line"><span class="cl">sysadmin    NT SERVICE\MSSQLSERVER  WINDOWS_LOGIN
</span></span><span class="line"><span class="cl">sysadmin    CONTOSO\dba_admin     WINDOWS_LOGIN
</span></span></code></pre></div>
</details>


SSMS 口径：安全性 > 登录名，查看 sa 是否改名/禁用（图标带红色向下箭头为禁用）；右键实例 > 属性 > 安全性页查看认证模式；右键 sysadmin 角色 > 属性查看成员。
PowerShell/CMD 口径（运行账户）：

```powershell
Get-CimInstance Win32_Service -Filter "Name='MSSQLSERVER'" | Select-Object Name,StartName,State
```

**加固操作**（先创建并验证替代管理员通道，再实施；建议维护窗口）

```sql
-- 1) 改名并强化 sa（改名需 CONTROL SERVER 权限；sa 属 sysadmin 成员）
ALTER LOGIN sa WITH NAME = [svc_sa_maint];
ALTER LOGIN [svc_sa_maint] WITH PASSWORD = N'PleaseChange@123',
  CHECK_POLICY = ON, CHECK_EXPIRATION = ON;

-- 2) 或直接禁用 sa（推荐：Windows 认证模式下安装时 sa 本就默认禁用）
ALTER LOGIN sa DISABLE;

-- 3) sysadmin 收敛：移除多余成员
ALTER SERVER ROLE sysadmin DROP MEMBER [old_dba];

-- 4) 混合模式下按需建独立管理账户并纳入策略
CREATE LOGIN [contoso\secadmin] FROM WINDOWS;
ALTER SERVER ROLE securityadmin ADD MEMBER [contoso\secadmin];
```

- 预期现象：`IsIntegratedSecurityOnly` 与设计一致；sa 已改名或禁用且口令受策略约束；sysadmin 成员仅剩实名运维账户与系统内部服务 SID（`NT SERVICE\MSSQLSERVER`、`NT SERVICE\SQLSERVERAGENT`、`NT AUTHORITY\SYSTEM` 等安装默认项）；服务以虚拟账户/gMSA 运行。

## 02 口令复杂度与有效期（CHECK_POLICY / CHECK_EXPIRATION）

> **对应控制点**：GB/T 22239-2019 8.1.4.1 身份鉴别 a)（身份鉴别信息具有复杂度要求并定期更换）
>
> **加固要点**：SQL Server 自身不内建复杂度校验，而是通过 `CHECK_POLICY`/`CHECK_EXPIRATION` 两个开关调用 Windows 密码策略机制（依赖 `NetValidatePasswordPolicy` API）：`CHECK_POLICY` 复用 Windows 本地/域策略的复杂度（至少 8 位、四类字符中三类、不含账户名、拒绝 `password`/`admin`/`sa` 等弱口令）与密码历史，并同步启用账户锁定策略；`CHECK_EXPIRATION` 复用最长使用期限，到期后账户禁用。两个开关**逐登录账户**配置，且必须核查最高权限 SQL 认证账户是否同受约束；`MUST_CHANGE` 强制下次登录改口令（要求两开关同时 ON）。**重要差异**：`NetValidatePasswordPolicy` 仅 Windows 提供，SQL Server on Linux 上两开关实际不生效，须以账户创建流程约束 + 周期性改口令制度 + （2025 起）`mssql.conf` 自定义口令策略替代，并如实记录（见 09 节）。
>
> **验证方法**：`sys.sql_logins.is_policy_checked/is_expiration_checked` 全量回显（仅含 SQL 认证登录）、`LOGINPROPERTY` 的 BadPasswordCount/PasswordLastSetTime/IsExpired 抽查、Windows 本地或域密码策略截图（`secpol.msc` 账户策略）、一次弱口令设置被拒的实测记录。

<div class="alert alert-warning" role="alert"><div class="h4 alert-heading" role="heading">高风险提示</div>


数据库管理账户存在弱口令、空口令或口令永不过期，且 SQL 认证端口对非运维网段开放、可被在线口令猜测时，按《高风险判定指引》可直接判高风险；仅在新建账户时默认勾选策略而未对存量账户复核，属高频「已整改但无效」情形，复测必须以 `is_policy_checked=1` 全量结果为准。

判定口径详见 [22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)。

</div>


**核查方法**

```sql
select name,
       is_disabled,
       is_policy_checked      as 强制密码策略,
       is_expiration_checked  as 强制密码过期,
       loginproperty(name,'PasswordLastSetTime') as PasswordLastSetTime,
       loginproperty(name,'IsExpired')           as IsExpired,
       loginproperty(name,'IsLocked')            as IsLocked,
       loginproperty(name,'BadPasswordCount')    as BadPasswordCount,
       modify_date
from sys.sql_logins;
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">name       is_disabled 强制密码策略 强制密码过期 PasswordLastSetTime    IsExpired IsLocked BadPasswordCount
</span></span><span class="line"><span class="cl">---------- ----------- ------------ ------------ ---------------------- --------- -------- ----------------
</span></span><span class="line"><span class="cl">sa              1          1             0       2026-03-12 09:41:02     0         0        0
</span></span><span class="line"><span class="cl">appuser         0          1             1       2026-05-08 15:20:33     0         0        0
</span></span><span class="line"><span class="cl">report          0          0             0       2025-11-27 10:05:17     0         0        3
</span></span></code></pre></div>
</details>


SSMS 口径：安全性 > 登录名 > 右键登录名 > 属性 > 常规页，勾选项「强制实施密码策略」「强制密码过期」「用户在下次登录时必须更改密码」即对应上述三值。
PowerShell/CMD 口径（核对底层 Windows 策略是否成立）：

```powershell
secedit /export /cfg C:\temp\secpol.cfg; Select-String -Path C:\temp\secpol.cfg -Pattern "PasswordHistorySize|MinimumPasswordLength|MaximumPasswordAge"
# 或图形界面运行 secpol.msc > 账户策略 > 密码策略
```

**加固操作**（口令修改属变更操作，批量执行建议维护窗口）

```sql
-- 存量 SQL 认证登录逐个开启策略与过期
ALTER LOGIN [appuser]  WITH CHECK_POLICY = ON, CHECK_EXPIRATION = ON;
ALTER LOGIN [report]   WITH CHECK_POLICY = ON, CHECK_EXPIRATION = ON;

-- 重设口令并要求下次登录必须更改（MUST_CHANGE 要求两开关均为 ON）
ALTER LOGIN [report] WITH PASSWORD = N'PleaseChange@123' MUST_CHANGE;

-- 解锁被锁定的登录（改口令并解锁；不改口令解锁可先 OFF 再 ON CHECK_POLICY，慎用）
-- ALTER LOGIN [appuser] WITH PASSWORD = N'NewStrong@123' UNLOCK;
```

- 说明：`CHECK_POLICY` 由 OFF 改 ON 时会初始化密码历史并同步启用账户锁定策略；由 ON 改 OFF 会同时关闭过期检查并清空历史——**不要为了绕过复杂度报错把开关关掉**。
- Linux 平台：两开关不生效（无 Windows 策略 API），替代措施与 `mssql.conf` 的 `passwordpolicy.*`（2025 起）见 09 节。

## 03 登录失败处理与登录审核

> **对应控制点**：GB/T 22239-2019 8.1.4.1 身份鉴别 b)（登录失败处理、限制非法登录次数）、8.1.4.3 安全审计 a)b)（审计覆盖到每个用户、记录登录事件）
>
> **加固要点**：SQL Server 数据库侧**没有**「失败 N 次即锁定」的独立配置项：锁定阈值、锁定时长与计数重置取自 Windows 本地或域的**账户锁定策略**，并经 02 节的 `CHECK_POLICY=ON` 关联到各 SQL 认证登录生效——因此本项须数据库侧开关与 Windows/域策略**同时成立**；无法使用 Windows 策略的环境（Linux 部署）可用登录触发器（LOGON trigger）做会话级限制、配合登录审计与告警实现替代。登录审核用 SSMS 服务器属性「登录审核」开启（**没有**对应的 `sp_configure 'audit level'` 选项，该设置由 SSMS 写入实例配置、需重启生效），失败登录以错误 18456 记入 SQL Server 错误日志；更完整的失败/成功登录与口令变更审计用 SQL Server Audit 的 `FAILED_LOGIN_GROUP` 等审计组（见 06 节）。SQL Server 无原生的会话空闲超时参数（`remote login timeout`/`remote query timeout` 只约束跨实例远程连接），空闲退出须依赖客户端、连接池或堡垒机会话策略并在报告说明。
>
> **验证方法**：Windows/域账户锁定策略截图（锁定阈值/时长/重置计数）、SQL 认证登录 `is_policy_checked=1` 清单、SSMS 登录审核档位截图（重启后生效）、错误日志中 18456 失败记录样例（含时间、账户、来源 IP）、LOGON 触发器定义与实测记录、`LOGINPROPERTY('BadPasswordCount')` 巡检回显。

<div class="alert alert-warning" role="alert"><div class="h4 alert-heading" role="heading">高风险提示</div>


数据库管理入口无任何登录失败处理措施（SQL 认证账户未开 `CHECK_POLICY` 且 Windows/域侧也无锁定策略）且对全网或互联网开放、可被无限次口令猜测时，按高风险线索记录；登录审核为「无」且未配置 SQL Server Audit，失败登录完全不可溯源时，同时并入审计不符合项判定。

判定口径详见 [22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)。

</div>


**核查方法**

```sql
-- 失败计数与锁定状态（需 CHECK_POLICY=ON 且 Windows 锁定策略成立才有实际锁定效果）
select name,
       loginproperty(name,'BadPasswordCount') as BadPasswordCount,
       loginproperty(name,'BadPasswordTime')  as BadPasswordTime,
       loginproperty(name,'LockoutTime')      as LockoutTime,
       loginproperty(name,'IsLocked')         as IsLocked
from sys.sql_logins;

-- 登录审核无 sp_configure 选项；在 sys.configurations 中也不存在 audit level：
select name, value_in_use from sys.configurations where name like '%audit%';   -- 仅 default trace enabled / c2 audit mode

-- 错误日志中的 18456 失败登录（错误日志用 SSMS 查看，见下）
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">name    BadPasswordCount BadPasswordTime           LockoutTime  IsLocked
</span></span><span class="line"><span class="cl">------  ---------------- ------------------------- ------------  --------
</span></span><span class="line"><span class="cl">report  2                2026-08-21 14:33:01.123   NULL         0
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">name                  value_in_use
</span></span><span class="line"><span class="cl">--------------------  ------------
</span></span><span class="line"><span class="cl">default trace enabled 1
</span></span><span class="line"><span class="cl">c2 audit mode         0
</span></span></code></pre></div>
</details>


SSMS 口径：对象资源管理器 > 管理 > SQL Server 日志 > 双击当前日志，筛选「Logon」来源查看 `Error: 18456, Severity: 14, State: 8` 与 `Login failed for user '<u>'. [CLIENT: <ip>]`；登录审核档位在右键实例 > 属性 > 安全性页 > 「登录审核」区（无/仅失败的登录/仅成功的登录/失败的登录和成功的登录）。
PowerShell/CMD 口径（Windows 事件日志与应用日志中的登录事件）：

```powershell
Get-WinEvent -FilterHashtable @{LogName='Application';ProviderName='MSSQLSERVER'} -MaxEvents 200 |
  Where-Object {$_.Message -match '18456'} | Select-Object TimeCreated,Message -First 10
```

**加固操作**

1. Windows/域侧锁定策略（由主机或域管理员实施，三级建议阈值 5 次、锁定 30 分钟起步）：`secpol.msc` > 账户策略 > 账户锁定策略；域环境在组策略「计算机配置 > 策略 > Windows 设置 > 安全设置 > 账户锁定策略」配置并 `gpupdate /force`。确认每个 SQL 认证登录 `CHECK_POLICY=ON`（02 节）。
2. SSMS 开启登录审核（**需重启 SQL Server 服务，安排维护窗口**）：右键实例 > 属性 > 安全性 > 登录审核选「失败的登录」（运维期可临时选「失败的登录和成功的登录」，注意日志量）> 确定 > 右键实例 > 重启。
3. 替代/增强：LOGON 登录触发器（官方文档样例为按并发会话数拒绝，按现场需求改造）：

```sql
USE master;
GO
CREATE TRIGGER connection_limit_trigger ON ALL SERVER
WITH EXECUTE AS N'sa_audit'
FOR LOGON
AS BEGIN
    IF ORIGINAL_LOGIN() = N' suspect_user'
       AND (SELECT COUNT(*) FROM sys.dm_exec_sessions
            WHERE is_user_process = 1 AND original_login_name = N' suspect_user') > 3
        ROLLBACK;
END;
-- 紧急通道：触发器可能阻断包括 sysadmin 在内的全部登录，
-- 官方口径为经专用管理员连接（DAC）连入后禁用：
-- DISABLE TRIGGER connection_limit_trigger ON ALL SERVER;
```

- 说明：SQL Server 无原生「失败 N 次锁定」参数，判定时按「数据库开关 + Windows/域锁定策略 + 审计告警」组合认定登录失败处理能力；仅配开关而 OS/域侧无阈值时，如实按部分符合记录并整改 OS/域侧。

## 04 权限最小化与高危能力关闭

> **对应控制点**：GB/T 22239-2019 8.1.4.2 访问控制 a)d)f)（默认账户清理、按需授权、特权能力收敛）
>
> **加固要点**：固定服务器角色（sysadmin、securityadmin、serveradmin、setupadmin、processadmin、diskadmin、dbcreator、bulkadmin）成员逐一最小化，`CONTROL SERVER` 授权与 sysadmin 等级一并核查；业务库内 `db_owner`/`db_securityadmin` 成员收敛、一库一账户按对象授权，`public` 角色上的多余权限逐项回收；高危面收敛：`xp_cmdshell` 与 `Ole Automation Procedures` 新安装默认关闭（必须保持，确需开启的评估必要性、限定账户并按任务时限开关）、`clr strict security` 自 2017 起默认开启（未签名 CLR 程序集一律按 UNSAFE 拒载，2016 及更早为可选高级选项，建议显式开启）、`cross db ownership chaining` 实例级保持关闭（确有跨库链需求的库用 `ALTER DATABASE ... SET CROSS_DB_OWNERSHIP_CHAINING ON` 单库开启）、guest 用户在每个用户库禁用（`REVOKE CONNECT FROM GUEST`；`master`/`tempdb` 的 guest 不可禁用，禁用 `msdb` 的 guest 会破坏 SQL Server Agent/数据库邮件，须谨慎）、Database Mail 的 `sp_send_dbmail` 仅授予 `msdb` 库 `DatabaseMailUserRole` 必要成员。
>
> **验证方法**：固定服务器角色成员清单与台账比对（01 节命令）、高危参数回显（`sp_configure` 四项）、`is_db_chaining_on` 全库清单、各用户库 guest 状态回显、`db_owner` 成员清单、DatabaseMailUserRole 成员清单。

<div class="alert alert-warning" role="alert"><div class="h4 alert-heading" role="heading">高风险提示</div>


`xp_cmdshell` 开启且无授权与用途控制（或允许普通业务账户调用），可被 SQL 注入后直接执行操作系统命令，按《高风险判定指引》可直接判不符合并需评估业务必要性；业务账户持有 `db_owner`/`CONTROL SERVER` 且无审批记录时，按高风险线索记录。

判定口径详见 [22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)。

</div>


**核查方法**

```sql
-- 高危能力开关（value_in_use=1 为当前生效开启）
select name, cast(value_in_use as int) as value_in_use
from sys.configurations
where name in (N'xp_cmdshell', N'Ole Automation Procedures',
               N'clr strict security', N'cross db ownership chaining');

-- 各库跨库所有权链状态
select name, is_db_chaining_on from sys.databases;

-- 各用户库 guest 是否可连接（CONNECT 权限状态）
select db_name() as [db], dp.name,
       permission_name, state_desc
from sys.database_permissions pe
join sys.database_principals dp on dp.principal_id = pe.grantee_principal_id
where dp.name = 'guest' and pe.permission_name = 'CONNECT';

-- db_owner 成员（逐库执行）
select members.name from sys.database_role_members drm
join sys.database_principals roles   on drm.role_principal_id   = roles.principal_id
join sys.database_principals members on drm.member_principal_id = members.principal_id
where roles.name = 'db_owner';
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">name                          value_in_use
</span></span><span class="line"><span class="cl">----------------------------- ------------
</span></span><span class="line"><span class="cl">Ole Automation Procedures               0
</span></span><span class="line"><span class="cl">xp_cmdshell                             0
</span></span><span class="line"><span class="cl">clr strict security                     1
</span></span><span class="line"><span class="cl">cross db ownership chaining             0
</span></span></code></pre></div>
</details>


SSMS 口径：右键实例 > 面积配置（方面/「Facets」）查看外围应用配置；安全性 > 登录名与各库 > 安全性 > 用户，核对角色成员与 guest 图标（禁用带红色向下箭头）；服务器属性 > 权限页查看 CONTROL SERVER 授权。
PowerShell/CMD 口径（口令类/高危作业排查示例）：

```powershell
# 检索作业/脚本中的明文口令与 xp_cmdshell 调用痕迹（配合 08 节）
sqlcmd -S localhost -E -Q "select job.name, s.step_name from msdb.dbo.sysjobs job join msdb.dbo.sysjobsteps s on s.job_id=job.job_id where s.command like '%xp_cmdshell%' or s.command like '%PASSWORD=%'"
```

**加固操作**

```sql
-- 1) 关闭高危能力（均为高级选项，改后须 RECONFIGURE）
EXECUTE sp_configure 'show advanced options', 1; RECONFIGURE;
EXECUTE sp_configure 'xp_cmdshell', 0;              RECONFIGURE;
EXECUTE sp_configure 'Ole Automation Procedures', 0; RECONFIGURE;
EXECUTE sp_configure 'cross db ownership chaining', 0; RECONFIGURE;
EXECUTE sp_configure 'show advanced options', 0; RECONFIGURE;

-- 2) 单库确需跨库所有权链时（替代实例级开启）
ALTER DATABASE [AppDB] SET CROSS_DB_OWNERSHIP_CHAINING ON;   -- 恢复默认改 OFF

-- 3) 禁用 guest（逐个用户库执行；master/tempdb 除外，msdb 谨慎——会影响 SQL Server Agent/数据库邮件）
USE [AppDB];
GO
REVOKE CONNECT FROM GUEST;
GO

-- 4) 收敛 db_owner（2012 起 ADD/DROP MEMBER 语法）
USE [AppDB];
GO
ALTER ROLE db_owner DROP MEMBER [report_rw];
GO
```

- 预期现象：四项高危配置 `value_in_use` 均为 0（`clr strict security` 为 1）；除业务确需的单库外 `is_db_chaining_on` 全 0；用户库 guest 无 CONNECT 权限；`db_owner` 仅剩实名运维账户。
- 说明：`clr strict security` 2017+ 默认为 1（高级选项）；2016 及更早默认 0，显式 `sp_configure 'clr strict security', 1` 开启后未签名程序集将拒载，启用前先与开发确认 CLR 程序集签名情况。

## 05 网络与传输加密（端口收敛、Force Encryption 与 TDE）

> **对应控制点**：GB/T 22239-2019 8.1.4.1 身份鉴别 c)（远程管理防窃听）、8.1.4.7 数据完整性 a)、8.1.4.8 数据保密性 a)b)、8.1.2.2 通信传输 a)b)
>
> **加固要点**：网络收敛——默认实例监听 TCP 1433，命名实例默认动态端口，均应在配置管理器改静态端口并由防火墙限定来源（官方同时提醒：改端口只是增加干扰，端口扫描仍可发现，**不能替代来源限制**）；命名实例可设 `HideInstance` 让 SQL Server Browser 不对外通告（对新建连接立即生效，隐藏后连接串必须带静态端口）；传输加密——客户端与服务端之间应**强制**加密：配置管理器在「证书」页选定受信任 CA 签发、CN/FQDN 匹配、私钥对服务账户可读的服务器证书，再在「标志」页把 Force Encryption 设为 Yes 并**重启 SQL Server 服务**；未配置证书时登录包（凭据）始终加密但业务数据包为明文，自签回退证书不防服务端仿冒。TLS 协议版本在 Windows 上由 SChannel（操作系统层）决定，须按 Windows 主机层加固禁用 TLS 1.0/1.1；SQL Server 2022 起配置管理器额外提供「强制严格加密」（TDS 8.0）选项。存储保密性——启用透明数据加密（TDE）加密数据与日志文件（受版本/edition 限制，见 11 节），TDE 证书与私钥必须单独备份否则备份不可恢复；字段级高敏数据可用 Always Encrypted（应用侧加密、各版本均支持）。
>
> **验证方法**：`sys.dm_exec_connections.encrypt_option`（官方验证查询）确认存量连接实际加密、Force Encryption 配置回显与配置管理器截图、证书有效期与私钥权限截图、监听端口与防火墙策略（`netstat -ano`/`Get-NetTCPConnection`）、`sys.databases.is_encrypted` 与 `sys.dm_database_encryption_keys.encryption_state`（3=已加密）、隐藏实例与 Browser 服务状态。

<div class="alert alert-warning" role="alert"><div class="h4 alert-heading" role="heading">高风险提示</div>


承载敏感数据（个人身份信息、鉴别信息、业务核心数据）的数据库通信全程明文（Force Encryption 为 No 且客户端未启用加密，`encrypt_option=FALSE` 的业务连接长期存在），鉴别信息与数据可被链路嗅探还原时，按《高风险判定指引》可直接判高风险。

判定口径详见 [22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)。

</div>


**核查方法**

```sql
-- 实际连接是否加密（官方验证查询；TRUE=已加密）
select distinct encrypt_option
from sys.dm_exec_connections
where net_transport <> 'Shared memory';

-- 明细：来源、协议、加密与认证方式
select session_id, net_transport, encrypt_option, auth_scheme, client_net_address, local_tcp_port
from sys.dm_exec_connections
where net_transport <> 'Shared memory';

-- TDE 状态（is_encrypted=1 为已开启；实际进度以 DMV 为准，3=已加密）
select name, is_encrypted from sys.databases;
select db_name(database_id) as database_name, encryption_state, percent_complete
from sys.dm_database_encryption_keys;
```

SSMS 口径：SQL Server 配置管理器 > SQL Server 网络配置 > <实例> 的协议 > 属性：「证书」页查看所选证书、「标志」页查看 ForceEncryption/HideInstance；TCP/IP 属性 > IP 地址页查看 IPAll 的 TCP 动态端口与 TCP 端口。
PowerShell/CMD 口径：

```powershell
Get-NetTCPConnection -State Listen | Where-Object {$_.LocalPort -in 1433,1434} |
  Select-Object LocalAddress,LocalPort,OwningProcess
# ForceEncryption 与证书指纹存于注册表（只读核查；实例 ID 形如 MSSQL15.MSSQLSERVER，按版本为 12~16）
Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQLServer\SuperSocketNetLib' |
  Select-Object ForceEncryption,Certificate
```

**加固操作**（端口、隐藏实例与 Force Encryption 均涉及服务重启或连接方式变更，安排维护窗口）

1. 端口收敛与隐藏实例：配置管理器 > 协议 > TCP/IP 属性 > IP 地址页，清空「TCP 动态端口」、在「TCP 端口」填固定端口 > 重启服务；命名实例在「标志」页把 HideInstance 设为 Yes（对新建连接立即生效）并在连接串中使用 `host,port`。同步在主机防火墙仅放行应用与运维网段。
2. 强制加密（两步缺一不可）：
   - 证书：将满足「服务器身份验证 EKU、使用者 CN/FQDN 匹配、私钥可导出」的证书装入本机「个人」存储；2019+ 可直接在配置管理器「证书」页导入，服务账户须对该证书私钥有读取权限（否则服务启动失败）；2017 及更早用 MMC 导入并在「证书」页下拉选择。
   - 强制：配置管理器 > 协议属性 > 标志页 Force Encryption = Yes > 重启 SQL Server 服务。2022+ 可选择 Force Strict Encryption（TDS 8.0），启用前确认全部客户端驱动支持。
3. TDE（示例库 AppDB，ALGORITHM 建议 AES_256；加密扫描期间限制维护操作，安排窗口）：

```sql
USE master;
GO
CREATE MASTER KEY ENCRYPTION BY PASSWORD = N'PleaseChange@MasterKey';
GO
CREATE CERTIFICATE MyServerCert WITH SUBJECT = 'TDE DEK Certificate';
GO
BACKUP CERTIFICATE MyServerCert TO FILE = N'E:\SQLBackup\MyServerCert.cer'
  WITH PRIVATE KEY ( FILE = N'E:\SQLBackup\MyServerCert.pvk',
                     ENCRYPTION BY PASSWORD = N'PleaseChange@Pvk' );   -- 异地妥善保管！
GO
USE [AppDB];
GO
CREATE DATABASE ENCRYPTION KEY WITH ALGORITHM = AES_256 ENCRYPTION BY SERVER CERTIFICATE MyServerCert;
GO
ALTER DATABASE [AppDB] SET ENCRYPTION ON;
GO
```

4. Linux 部署的等价操作（mssql-conf）见 09 节。
- 预期现象：`encrypt_option` 全 TRUE；配置管理器 ForceEncryption=Yes 且证书为受信任 CA 签发；核心库 `is_encrypted=1` 且 `encryption_state=3`；TDE 证书与私钥有异地备份登记；监听端口仅业务/运维网段可达。

## 06 审计与日志（SQL Server Audit）

> **对应控制点**：GB/T 22239-2019 8.1.4.3 安全审计 a)~d)（审计覆盖到每个用户、记录含日期时间/用户/事件类型/是否成功、记录受保护并定期备份、审计进程受保护）
>
> **加固要点**：以 **SQL Server Audit** 为主体审计能力（2008+，各版本均支持）：`CREATE SERVER AUDIT` 定义审计对象与落盘目标（二进制文件 / Windows 应用程序日志 / 安全日志，安全日志须额外配置 `auditpol` 的 application generated 子类与服务账户「生成安全审核」权限），`CREATE SERVER AUDIT SPECIFICATION` 挂接审计组；审计对象创建后默认禁用，须 `ALTER SERVER AUDIT ... WITH (STATE = ON)` 启用。审计组覆盖建议：登录类 `FAILED_LOGIN_GROUP`/`SUCCESSFUL_LOGIN_GROUP`/`LOGOUT_GROUP`、账户与权限变更 `SERVER_PRINCIPAL_CHANGE_GROUP`/`SERVER_ROLE_MEMBER_CHANGE_GROUP`/`LOGIN_CHANGE_PASSWORD_GROUP`/`SERVER_PERMISSION_CHANGE_GROUP`、对象与库变更 `SERVER_OBJECT_CHANGE_GROUP`/`DATABASE_CHANGE_GROUP`/`DATABASE_OBJECT_CHANGE_GROUP`、审计自身变更 `AUDIT_CHANGE_GROUP`（防篡改自证）等，核心库再加数据库级规范覆盖敏感表 DML。仅依赖登录审核（03 节）或默认跟踪（default trace enabled）不构成完整符合；`c2 audit mode` 已弃用（还易写满全量跟踪影响性能），保持 0 并不作为符合证据。审计文件用 `MAXSIZE`/`MAX_ROLLOVER_FILES` 轮转并折算留存容量（不少于 6 个月），审计目录 ACL 仅审计员与系统可读，错误日志+审计文件+Windows 事件日志统一外送日志审计系统集中留存；主机侧配置 NTP/域时间同步保证日志时间一致。
>
> **验证方法**：`sys.server_audits`（is_state_enabled=1）与 `sys.server_file_audits`（type=FL 路径、max_file_size、max_rollover_files）回显、服务器/数据库审计规范配置截图、`sys.fn_get_audit_file` 导出的审计记录样例（含时间、用户、语句、结果）、审计文件权限与集中外送配置、留存容量折算说明、审计配置变更被记录的自证样例。

<div class="alert alert-warning" role="alert"><div class="h4 alert-heading" role="heading">高风险提示</div>


数据库未启用任何审计（`sys.server_audits` 为空、登录审核为「无」、亦无数据库审计系统等等效替代），或审计记录可由系统管理员账户自行关闭与删除、留存不足 6 个月，安全事件无法溯源时按高风险线索记录（多与访问控制、剩余信息保护不符合项合并判定）。

判定口径详见 [22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)。

</div>


**核查方法**

```sql
-- 审计对象与状态
select name, type_desc, is_state_enabled, on_failure_desc, create_date
from sys.server_audits;

-- 文件型审计的落盘路径与轮转参数
select name, type_desc, is_state_enabled, log_file_path, max_file_size, max_rollover_files
from sys.server_file_audits;

-- 审计规范覆盖的审计组（服务器级）
select sas.name as spec_name, sa.name as audit_name, sas.is_state_enabled
from sys.server_audit_specifications sas
left join sys.server_audits sa on sa.audit_guid = sas.audit_guid;

-- 审计记录样例（文件型；路径与 sys.server_file_audits.log_file_path 一致）
select event_time, session_server_principal_name, action_id, statement
from sys.fn_get_audit_file(N'E:\SQLAudit\Audit-*.sqlaudit', default, default)
order by event_time desc;
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">name      type_desc  is_state_enabled on_failure_desc  log_file_path      max_file_size max_rollover_files
</span></span><span class="line"><span class="cl">--------- ---------- ---------------- ---------------- ------------------ ------------- ------------------
</span></span><span class="line"><span class="cl">SQLAudit1 FILE       1                CONTINUE         E:\SQLAudit\       512           26
</span></span></code></pre></div>
</details>


SSMS 口径：对象资源管理器 > 安全性 > 审计 与 服务器审核规范（库内为 数据库 > 安全性 > 数据库审核规范），双击查看目标、启用状态与审计动作组；安全性 > 审计 > 右键 > 「查看审计日志」直接读取记录。
PowerShell/CMD 口径（外送与本地留存核查示例）：

```powershell
Get-ChildItem E:\SQLAudit -Filter *.sqlaudit | Sort-Object LastWriteTime -Descending |
  Select-Object -First 5 Name,Length,LastWriteTime
Get-Acl E:\SQLAudit | Format-List   # 审计目录 ACL
```

**加固操作**（审计规范修改需先停用再改，切换过程安排窗口）

```sql
USE master;
GO
-- 1) 审计对象：文件目标 + 轮转 + 失败继续（如要求审计不可中断可用 ON_FAILURE = FAIL_OPERATION）
CREATE SERVER AUDIT [SQLAudit1]
  TO FILE ( FILEPATH = N'E:\SQLAudit\', MAXSIZE = 512 MB, MAX_ROLLOVER_FILES = 26 )
  WITH ( QUEUE_DELAY = 1000, ON_FAILURE = CONTINUE );
GO
-- 留存折算：512MB × (26+1) ≈ 13GB，结合事件量换算保留时长，不足 6 个月则加大 MAXSIZE 或外送集中存储

-- 2) 服务器级审计规范：登录、账户/权限变更、审计自身变更
CREATE SERVER AUDIT SPECIFICATION [ServerAuditSpec]
  FOR SERVER AUDIT [SQLAudit1]
  ADD (FAILED_LOGIN_GROUP),
  ADD (SUCCESSFUL_LOGIN_GROUP),
  ADD (LOGOUT_GROUP),
  ADD (SERVER_PRINCIPAL_CHANGE_GROUP),
  ADD (SERVER_ROLE_MEMBER_CHANGE_GROUP),
  ADD (LOGIN_CHANGE_PASSWORD_GROUP),
  ADD (SERVER_PERMISSION_CHANGE_GROUP),
  ADD (SERVER_OBJECT_CHANGE_GROUP),
  ADD (DATABASE_CHANGE_GROUP),
  ADD (AUDIT_CHANGE_GROUP)
  WITH (STATE = ON);
GO
ALTER SERVER AUDIT [SQLAudit1] WITH (STATE = ON);
GO

-- 3) 核心库数据库级规范：对象变更 + 敏感表 DML（示例）
USE [AppDB];
GO
CREATE DATABASE AUDIT SPECIFICATION [AppDB_Audit]
  FOR SERVER AUDIT [SQLAudit1]
  ADD (DATABASE_OBJECT_CHANGE_GROUP),
  ADD (SELECT, INSERT, UPDATE, DELETE, EXECUTE ON SCHEMA::dbo BY public)
  WITH (STATE = ON);
GO
```

- 预期现象：`sys.server_audits.is_state_enabled=1` 且规范含上述审计组；`sys.fn_get_audit_file` 能取到含时间/账户/语句的记录；审计配置自身的修改在审计文件中出现（`AUDIT_CHANGE_GROUP` 自证）；审计文件 ACL 收敛且已接入日志审计系统。
- 说明：写入 Windows 安全日志为目标时需先完成系统侧配置（`auditpol /set /subcategory:"application generated" /success:enable /failure:enable`、授予服务账户「生成安全审核」权限、EventLog\Security 注册表权限），并注意安全日志写满（事件 1104）会丢审计记录，一般不建议作为首选目标。

## 07 数据备份恢复

> **对应控制点**：GB/T 22239-2019 8.1.4.9 数据备份恢复 a)~c)（本地备份恢复、异地实时备份、热冗余）
>
> **加固要点**：核心库采用 FULL 恢复模式并建立**实际执行**的「每日完整 + 周期日志（或差异）」备份链，备份文件与主数据分机/分盘存放并异地留存（三级要求异地实时备份或热冗余，可用 Always On 可用性组、日志传送或复制实现，ESU/许可受限时可按业务评估 Basic AG 与日志传送组合）；备份同样要保护：备份文件 ACL 收敛、启用备份校验（`WITH CHECKSUSM` 写入）与备份加密（受版本/edition 限制，见 11 节，2022 页 Enterprise/Standard 为 Yes）、TDE 库的证书与 master 密钥**单独备份**且与备份文件分离存放（否则备份不可恢复）；每半年至少一次恢复演练并留存记录，RTO/RPO 与业务要求匹配。仅有备份脚本而无恢复验证不判符合。
>
> **验证方法**：`msdb.dbo.backupset` 备份历史（type：D=完整、I=差异、L=日志）与最近成功时间、备份任务/维护计划截图、`sys.databases.recovery_model_desc`、备份文件清单与存放位置、异地/热冗余拓扑（AG/日志传送状态）、恢复演练记录、TDE 证书备份登记（`sys.certificates.pvt_key_last_backup_date`）。

<div class="alert alert-warning" role="alert"><div class="h4 alert-heading" role="heading">高风险提示</div>


核心业务数据库无任何备份，或备份与主数据同机同盘存放、从未做过恢复演练导致备份实际不可用，一旦数据被破坏或遭勒索加密即无法恢复，按《高风险判定指引》可直接判高风险；TDE 库的加密证书无私钥备份时，备份恢复同样不可用，一并按高风险线索记录。

判定口径详见 [22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)。

</div>


**核查方法**

```sql
-- 备份历史（近 30 天；type D/I/L）
select database_name, type, backup_start_date, backup_finish_date,
       has_backup_checksums, key_algorithm
from msdb.dbo.backupset
where backup_start_date > dateadd(day, -30, sysdatetime())
order by database_name, backup_start_date desc;

-- 恢复模式
select name, recovery_model_desc from sys.databases;

-- TDE 证书私钥是否已备份（NULL=从未备份，高危信号）
select c.name as certificate_name, c.pvt_key_last_backup_date,
       db_name(dek.database_id) as encrypted_database
from sys.certificates as c
join sys.dm_database_encryption_keys as dek
  on c.thumbprint = dek.encryptor_thumbprint;
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">database_name type backup_start_date      backup_finish_date      has_backup_checksums
</span></span><span class="line"><span class="cl">------------- ---- ----------------------- ----------------------- --------------------
</span></span><span class="line"><span class="cl">AppDB         L    2026-09-01 13:00:04.552 2026-09-01 13:00:44.201 1
</span></span><span class="line"><span class="cl">AppDB         D    2026-09-01 01:00:03.210 2026-09-01 01:12:44.102 1
</span></span></code></pre></div>
</details>


SSMS 口径：对象资源管理器 > 管理 > 维护计划 / SQL Server 代理 > 作业，核对备份任务与计划；库右键 > 属性 > 选项页查看恢复模式。
PowerShell/CMD 口径：

```powershell
Get-ChildItem 'E:\SQLBackup' -Filter *.bak | Sort-Object LastWriteTime -Descending |
  Select-Object -First 10 Name,Length,LastWriteTime     # 备份产物时效与存放
```

**加固操作**（备份与校验产生明显 IO 与日志压力，安排低峰维护窗口）

```sql
-- 完整 + 校验和 + 压缩（写明校验标志便于复核）
BACKUP DATABASE [AppDB]
TO DISK = N'E:\SQLBackup\AppDB_Full.bak'
WITH CHECKSUM, COMPRESSION, INIT;

-- 备份集有效性验证（只读，不还原）
RESTORE VERIFYONLY FROM DISK = N'E:\SQLBackup\AppDB_Full.bak' WITH CHECKSUM;

-- TDE 证书与 master 密钥备份（恢复密钥留存异地）
BACKUP CERTIFICATE MyServerCert TO FILE = N'E:\SQLBackup\MyServerCert.cer'
  WITH PRIVATE KEY ( FILE = N'E:\SQLBackup\MyServerCert.pvk', ENCRYPTION BY PASSWORD = N'PleaseChange@Pvk' );
USE master;
BACKUP MASTER KEY TO FILE = N'E:\SQLBackup\master.key'
  ENCRYPTION BY PASSWORD = N'PleaseChange@MkBackup';
```

- 预期现象：`backupset` 显示周期性完整+日志组合且 `has_backup_checksums=1`；`RESTORE VERIFYONLY` 返回成功消息；演练记录（时间、参与人、恢复耗时、数据一致性结论）齐全；TDE 证书/主密钥备份异地登记。

## 08 剩余信息保护

> **对应控制点**：GB/T 22239-2019 8.1.4.10 剩余信息保护 a)b)（鉴别信息与敏感数据所在存储空间释放前清除）
>
> **加固要点**：鉴别信息不以明文形式残留在脚本、历史、配置与日志中：旧版口令变更过程 `sp_password` 已弃用（官方弃用清单映射到 `ALTER LOGIN`，性能计数器亦提示「Use ALTER LOGIN instead」），存量维护脚本、SQL 作业步骤与自建口令轮换程序统一改用 `ALTER LOGIN ... WITH PASSWORD`（自动作业走受限凭据而非明文口令）；连接字符串中的口令按应用层口径收敛（集成认证优先、口令入密钥管理/加密配置而非配置文件与代码库、离职人员凭据及时吊销）；SQL Server 管理主机上不落口令历史文件，运维终端历史命令定期清理；含敏感数据的库文件、备份与导出中间文件在释放/销毁前以介质清理制度+磁盘加密（BitLocker/BitLocker To Go）或 TDE 兜底，错误转储（dump）目录 ACL 收敛并按周期清理。
>
> **验证方法**：脚本/作业/历史文件明文口令检索结果（应为空）、连接串与配置文件抽样检查记录、口令变更方式确认（无 `sp_password` 调用）、介质清理与销毁制度及记录、磁盘加密/TDE 状态回显、dump 目录权限与清理记录。

<div class="alert alert-warning" role="alert"><div class="h4 alert-heading" role="heading">高风险提示</div>


维护脚本、代码仓库或客户端历史文件中存在数据库明文口令，其他本地账户或离职人员可直接读取时，按高风险线索记录；已停用账户的凭据仍保留在连接串中可自动重连时，一并向访问控制项归并记录。

判定口径详见 [22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)。

</div>


**核查方法**

```powershell
# 明文口令检索（运维脚本/作业/历史；命中即整改）
Get-ChildItem D:\DBA_Scripts -Include *.sql,*.ps1,*.cmd,*.ini -Recurse |
  Select-String -Pattern "PASSWORD\s*=|PWD\s*=" -List | Select-Object Path,LineNumber
# 口令变更方式核查：作业步骤中不应出现 sp_password
sqlcmd -S localhost -E -Q "select job.name, s.step_name from msdb.dbo.sysjobs job join msdb.dbo.sysjobsteps s on s.job_id=job.job_id where s.command like '%sp_password%'"
```

SSMS 口径：SQL Server 代理 > 作业 > 双击作业 > 步骤页，检查命令文本是否内嵌明文口令；安全性 > 凭据，核对凭据对象用途。
CMD 口径（错误转储目录核查示例）：`dir "C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\LOG\*.mdmp" /o-d`。

**加固操作**

```sql
-- 口令变更统一改用 ALTER LOGIN（含 MUST_CHANGE 强制改口令，见 02 节）
ALTER LOGIN [appuser] WITH PASSWORD = N'NewStrong@123' OLD_PASSWORD = N'OldWeak@123';
```

1. 清理脚本/作业中的明文口令：SQL Agent 作业改用 Proxy 账户与凭据对象执行操作系统级步骤；批处理调用改用 `-E`（Windows 集成认证）。
2. 运维终端清理 PowerShell/命令历史与临时凭证文件；会话工具关闭本地明文日志。
3. 报废/重分配的库文件、备份介质按介质清理制度执行清零销毁并留记录；新盘与库文件所在卷启用 BitLocker（或依赖 TDE）后再承载业务。

## 09 Windows/Linux 双平台差异

> **对应控制点**：GB/T 22239-2019 8.1.4.4 入侵防范 a)~f)（按部署形态等效落实）；本节为平台差异说明，不单独出判定结论
>
> **加固要点**：Linux 部署下无 SQL Server 配置管理器与 SSMS 服务器属性页，网络/TLS/端口等实例级配置统一走 `mssql-conf` 工具（`/opt/mssql/bin/mssql-conf set <项>`，写入 `/var/opt/mssql/mssql.conf`，改后 `systemctl restart mssql-server` 生效）；TLS 设置项为 `network.tlscert`/`network.tlskey`/`network.tlsprotocols`/`network.tlsciphers`/`network.forceencryption`（证书文件建议 `chown mssql:mssql` 并 `chmod 400`）；**口令策略差异必须如实说明**：`CHECK_POLICY`/`CHECK_EXPIRATION` 依赖的 `NetValidatePasswordPolicy` API 仅 Windows 提供，Linux 上两开关不生效，SQL Server 2025 起提供 `mssql.conf` 的 `passwordpolicy.passwordminimumlength/passwordhistorylength/passwordminimumage/passwordmaximumage` 自定义口令策略，更低版本须以创建流程约束+定期改口令制度替代；服务与日志路径差异：服务名 `mssql-server`（`systemctl status/enable`），数据默认 `/var/opt/mssql/data`、日志 `/var/opt/mssql/log`，运行账户为 `mssql`，数据与备份目录权限收敛到 `mssql` 账户（0770 以内）。
>
> **验证方法**：`select @@version` 输出含 "on Linux"；`systemctl status mssql-server` 服务状态；`cat /var/opt/mssql/mssql.conf` 或 `mssql-conf list` 回显（未列出项即默认值）；`ss -tlnp | grep 1433` 监听与 `ls -ld /var/opt/mssql/data` 目录权限；TLS 生效情况用 `sys.dm_exec_connections.encrypt_option` 同 05 节。

**核查方法**

```bash
systemctl status mssql-server --no-pager
sudo cat /var/opt/mssql/mssql.conf
sudo /opt/mssql/bin/mssql-conf list
ss -tlnp | grep -E '1433|mssql'
```

**加固操作**（重启 mssql-server 生效，安排维护窗口）

```bash
# TLS：证书与私钥 + 仅允许 TLS 1.2 + 强制加密
sudo /opt/mssql/bin/mssql-conf set network.tlscert /etc/ssl/certs/mssql.pem
sudo /opt/mssql/bin/mssql-conf set network.tlskey /etc/ssl/private/mssql.key
sudo /opt/mssql/bin/mssql-conf set network.tlsprotocols 1.2
sudo /opt/mssql/bin/mssql-conf set network.forceencryption 1
sudo chown mssql:mssql /etc/ssl/certs/mssql.pem /etc/ssl/private/mssql.key
sudo chmod 400 /etc/ssl/certs/mssql.pem /etc/ssl/private/mssql.key
sudo systemctl restart mssql-server

# 端口收敛（默认 1433，改后客户端用 host,port 连接）
sudo /opt/mssql/bin/mssql-conf set network.tcpport 14330
```

- 预期现象：重启后 `mssql.conf` 出现上述设置；`sys.dm_exec_connections.encrypt_option` 全 TRUE；非 1.2 客户端被拒绝；口令策略差异在测评报告中作为部署形态差异说明并给出替代措施证据。

## 10 版本支持与生命周期

> **对应控制点**：GB/T 22239-2019 8.1.4.4 入侵防范 d)~f)（漏洞修补与版本治理）
>
> **加固要点**：SQL Server 每版本至少 10 年支持（5 年主流 + 5 年扩展，扩展期仅安全更新）。截至 2026-09：**2012** 扩展支持已于 2022-07-12 结束；**2014** 已于 2024-07-09 结束（ESU 至 2027-07-08）；**2016** 于 2026-07-14 结束扩展支持（ESU 至 2029-07-17，已进入 ESU 期）；**2019** 扩展支持至 2030 年、**2022** 至 2033 年（官方 End of Support 总览页口径），仍在支持期内但须保持最新 CU/GDR。已 EOL 版本的标准路径为就地升级或迁移；无法立即升级时可订阅 ESU（仅 Critical 级安全更新、最多 3 年，通常需软件保障或订阅许可），并在报告中作为过渡性补偿措施记录，不得作为长期方案。
>
> **验证方法**：版本台账与 00 节 `SERVERPROPERTY` 回显比对官方生命周期页；ESU 订阅与安装记录（如有）；升级/迁移计划与排期。

| 版本 | 扩展支持截止 | 状态（2026-09） | 处置 |
| --- | --- | --- | --- |
| SQL Server 2012 | 2022-07-12 | 已停止支持 | 升级/迁移；无 ESU 可购则限期替换 |
| SQL Server 2014 | 2024-07-09 | 已停止支持（ESU 至 2027-07-08） | 升级/迁移或 ESU 过渡 |
| SQL Server 2016 | 2026-07-14 | 刚到期（ESU 至 2029-07-17） | 尽快升级，过渡期订阅 ESU |
| SQL Server 2019 | 2030 年（总览页口径） | 支持中 | 保持最新 CU/GDR |
| SQL Server 2022 | 2033 年（总览页口径） | 支持中 | 保持最新 CU/GDR；可评估 TDS 8.0 严格加密 |

- 预期现象：台账与官方页一致；无超期未处置版本；ESU/升级计划经审批并留痕。

## 11 版本差异速查（2012 ~ 2022）

| 事项 | 2012/2014/2016 | 2017/2019 | 2022 |
| --- | --- | --- | --- |
| `CHECK_POLICY` 默认值 | ON（`CHECK_EXPIRATION` 默认 OFF，需显式开启） | 同 | 同 |
| 失败锁定 | 无原生参数，随 CHECK_POLICY 关联 Windows/域锁定策略 | 同 | 同 |
| `xp_cmdshell`/`Ole Automation Procedures` | 新安装默认 0 | 同 | 同 |
| `clr strict security` | 默认 0（高级选项，建议显式开 1） | 默认 1（未签名 CLR 程序集拒载） | 同 2017 |
| TDE/备份加密版本支持 | 以对应版本 Editions 官方页为准（Express/Web 不含 TDE） | 同 | 官方 2022 页：TDE 与备份加密 Enterprise/Standard 为 Yes，Web/Express 为 No |
| TDS 8.0 强制严格加密 | 不支持 | 不支持 | 配置管理器新增 Force Strict Encryption（Linux 为 `network.forcestrict`，2025 起） |
| 审计组 BATCH_STARTED/COMPLETED_GROUP | 不支持 | 服务器级 2022+，数据库级 2019+ | 均支持 |
| Linux 口令策略 | 不生效（无 Windows 策略 API） | 同 | 同；2025 起可用 `mssql.conf` `passwordpolicy.*` |
| 生命周期 | 2012 已 EOL、2014 已 EOL、2016 2026-07-14 到期 | 2017 扩展支持至 2027 年 | 2019 至 2030 年、2022 至 2033 年 |

## 参考依据

- GB/T 22239-2019《信息安全技术 网络安全等级保护基本要求》（8.1.4 安全计算环境各控制点（数据库管理系统自身安全）；涉客户端与服务端通信时另含 8.1.2 安全通信网络）：[http://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=BAFB47E8874764186BDB7865E8344DAF](http://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=BAFB47E8874764186BDB7865E8344DAF)
- GB/T 28448-2019《信息安全技术 网络安全等级保护测评要求》（测评对象边界认定、单元测评实施与结果判定）：[http://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=7E736CDF4502B6FF1258DD250AA3EC8C](http://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=7E736CDF4502B6FF1258DD250AA3EC8C)
- 《网络安全等级保护测评高风险判定指引》（中关村信息安全测评联盟团体标准）——高风险情形判定口径，站内对照表：[22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)
- Microsoft Learn 官方文档（以下页面均已实际核对，版本差异处已在正文与 11 节标注）：
  - ALTER LOGIN（ENABLE/DISABLE、NAME=、PASSWORD/MUST_CHANGE、CHECK_POLICY 默认 ON/CHECK_EXPIRATION 默认 OFF）：https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-login-transact-sql?view=sql-server-ver16
  - Password Policy（CHECK_POLICY 复杂度/历史/锁定联动、NetValidatePasswordPolicy 依赖）：https://learn.microsoft.com/en-us/sql/relational-databases/security/password-policy?view=sql-server-ver16
  - Choose an Authentication Mode（Windows 认证更安全、sa 默认禁用）：https://learn.microsoft.com/en-us/sql/relational-databases/security/choose-an-authentication-mode?view=sql-server-ver16
  - SERVERPROPERTY（ProductLevel/ProductUpdateLevel/IsIntegratedSecurityOnly）：https://learn.microsoft.com/en-us/sql/t-sql/functions/serverproperty-transact-sql?view=sql-server-ver16
  - sys.sql_logins（is_policy_checked/is_expiration_checked）：https://learn.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-sql-logins-transact-sql?view=sql-server-ver16
  - MSSQLSERVER_18456（登录失败错误与 State 对照）：https://learn.microsoft.com/en-us/sql/relational-databases/errors-events/mssqlserver-18456-database-engine-error?view=sql-server-ver16
  - Logon triggers（ON ALL SERVER FOR LOGON 样例与 DAC 恢复口径）：https://learn.microsoft.com/en-us/sql/relational-databases/triggers/logon-triggers?view=sql-server-ver16
  - Configure Login Auditing（SSMS 登录审核，需重启）：https://learn.microsoft.com/en-us/ssms/configure-login-auditing-sql-server-management-studio
  - CREATE SERVER AUDIT / SQL Server Audit 审计组（FAILED_LOGIN_GROUP 等）：https://learn.microsoft.com/en-us/sql/t-sql/statements/create-server-audit-transact-sql?view=sql-server-ver16 、https://learn.microsoft.com/en-us/sql/relational-databases/security/auditing/sql-server-audit-action-groups-and-actions?view=sql-server-ver16
  - sys.server_audits / sys.server_file_audits：https://learn.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-server-audits-transact-sql?view=sql-server-ver16 、https://learn.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-server-file-audits-transact-sql?view=sql-server-ver16
  - 审计写入安全日志的前置配置：https://learn.microsoft.com/en-us/sql/relational-databases/security/auditing/write-sql-server-audit-events-to-the-security-log?view=sql-server-ver16
  - xp_cmdshell / Ole Automation Procedures / cross db ownership chaining / clr strict security（均为默认关闭或默认开启口径）：https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/xp-cmdshell-server-configuration-option?view=sql-server-ver16 、https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/ole-automation-procedures-server-configuration-option?view=sql-server-ver16 、https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/cross-db-ownership-chaining-server-configuration-option?view=sql-server-ver16 、https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/clr-strict-security?view=sql-server-ver16
  - guest 用户禁用（REVOKE CONNECT FROM GUEST）：https://learn.microsoft.com/en-us/sql/relational-databases/policy-based-management/guest-permissions-on-user-databases?view=sql-server-ver17 、https://learn.microsoft.com/en-us/troubleshoot/sql/database-engine/security/error-disable-guest-user
  - sp_password 弃用（改用 ALTER LOGIN）：https://learn.microsoft.com/en-us/sql/database-engine/deprecated-database-engine-features-in-sql-server-2017?view=sql-server-ver17
  - 配置 SQL Server 加密（Force Encryption、证书要求、encrypt_option 验证查询）：https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/configure-sql-server-encryption?view=sql-server-ver16
  - 配置 TCP 端口 / 隐藏实例（HideInstance）：https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/configure-a-server-to-listen-on-a-specific-tcp-port?view=sql-server-ver16 、https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/hide-an-instance-of-sql-server-database-engine?view=sql-server-ver16
  - 透明数据加密 TDE（DEK/证书备份/monitoring DMV）：https://learn.microsoft.com/en-us/sql/relational-databases/security/encryption/transparent-data-encryption?view=sql-server-ver16
  - Windows 服务账户与 gMSA（NT SERVICE\MSSQLSERVER、最低权限原则）：https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/configure-windows-service-accounts-and-permissions?view=sql-server-ver16
  - mssql-conf（network.forceencryption/tlsprotocols/tlscert/tcpport、Linux 口令策略差异）：https://learn.microsoft.com/en-us/sql/linux/configure/mssql-conf?view=sql-server-ver16
  - backupset / RESTORE VERIFYONLY：https://learn.microsoft.com/en-us/sql/relational-databases/system-tables/backupset-transact-sql?view=sql-server-ver16 、https://learn.microsoft.com/en-us/sql/t-sql/statements/restore-statements-verifyonly-transact-sql?view=sql-server-ver16
  - Editions and Supported Features of SQL Server 2022（TDE/备份加密/审计按版本支持矩阵）：https://learn.microsoft.com/en-us/sql/sql-server/editions-and-components-of-sql-server-2022?view=sql-server-ver16
  - 生命周期与 ESU：https://learn.microsoft.com/en-us/sql/sql-server/end-of-support/sql-server-end-of-support-overview 、https://learn.microsoft.com/en-us/sql/sql-server/end-of-support/extended-security-updates-frequently-asked-questions 、https://learn.microsoft.com/en-us/lifecycle/products/sql-server-2016
  - SQL Server 更新中心与版本构建表：https://learn.microsoft.com/en-us/troubleshoot/sql/releases/download-and-install-latest-updates
  - sys.server_role_members / sys.server_permissions / ALTER ROLE：https://learn.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-server-role-members-transact-sql?view=sql-server-ver16 、https://learn.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-server-permissions-transact-sql?view=sql-server-ver16 、https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-role-transact-sql?view=sql-server-ver16
- 命令核验说明：本文命令已于 2026-09 对照 Microsoft Learn（learn.microsoft.com，覆盖 SQL Server 2012~2022 差异）官方文档核验，六处须留意：① SQL Server 无 `sp_configure 'audit level'` 选项，登录审核的唯一官方设置入口是 SSMS 服务器属性「安全性 > 登录审核」且需重启生效（文档现迁移至 SSMS 文档库），失败登录锁定亦无数据库侧 N 次参数，阈值取自 Windows/域账户锁定策略并经 `CHECK_POLICY=ON` 关联生效，Linux 上因无 `NetValidatePasswordPolicy` API 复杂度与过期开关均不生效（2025 起可用 mssql.conf 的 `passwordpolicy.*`）；② `xp_instance_regwrite`/`xp_readerrorlog` 为未收录进官方 T-SQL 参考的扩展过程，本文变更与核查均未采用，Force Encryption 核查改用官方文档提供的 `sys.dm_exec_connections.encrypt_option` 查询与配置管理器界面，注册表 `SuperSocketNetLib` 键仅作只读核对；③ Linux 的 mssql-conf TLS 设置项实名为 `network.forceencryption`/`network.tlsprotocols`/`network.tlscert`/`network.tlskey`/`network.tcpport`（非 `network.tls...` 缩写），改后须 `systemctl restart mssql-server`；④ TDE 与备份加密受 edition 限制，官方 2022 页显示 TDE 行 Enterprise/Standard 为 Yes、Web/Express 为 No，低版本须以对应版本 Editions 页为准，启用 TDE 后证书与私钥必须立即备份否则备份不可恢复；⑤ `clr strict security` 自 2017 起默认 1，2016 及更早为高级选项默认 0，显式开启将拒载未签名程序集，须先与开发核对程序集签名；⑥ `ALTER ROLE ... ADD/DROP MEMBER` 为 2012 起语法，2012 之前版本用 `sp_droprolemember`；`ALTER SERVER ROLE ... DROP MEMBER` 用于服务器角色；`MUST_CHANGE` 要求 `CHECK_POLICY` 与 `CHECK_EXPIRATION` 同时为 ON，否则语句失败。

## 关联文章

- 本板块相关篇：[12、MySQL数据库加固](../12mysql数据库加固/)、[24、Oracle数据库加固](../24oracle数据库加固/)
- 配套测评：[05、SQL Server数据库测评](../../../gradeProtection/系统管理软件平台/05sql-server数据库测评/)
- 测评命令单：[05-SQL Server测评命令](../../../gradeProtection/系统管理软件平台/数据库测评命令/05-sql-server/)
- 板块目录：[系统管理软件·平台](/wikis/docs/reinforce/%E7%B3%BB%E7%BB%9F%E7%AE%A1%E7%90%86%E8%BD%AF%E4%BB%B6%E5%B9%B3%E5%8F%B0/)
- 数据库服务器 Windows 主机层加固（配套，TLS 与账户锁定策略）：[05、Windows操作系统安全加固](../../服务器/05windows操作系统安全加固/)
- 通用加固方案：[17、加固方案总纲](../../其他系统或设备/17网络设备安全设备服务器数据库和应用系统的加固方案/)
- 取证记录模板：[16、安全评估加固记录表3.0](../../其他系统或设备/16安全评估加固记录表3.0/)
- 高风险判定口径：[22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)
