SQL Server数据库加固22项核查表与巡检落地指南
发布时间:2026/10/31 2:58:39 锦皓数字建站

简介《Sql Server数据库系统加固规范》面向数据库管理员、安全运维与等保合规人员围绕SQL Server账号管理、认证授权、日志配置、通信协议及服务器设备安全等场景提供可落地的安全检查与加固参考。压缩包共1个doc文件约1.73MB以条目化规范文档形式组织。文档按SHG-Mssql编号拆分控制项逐条给出实施目的、问题影响、系统当前状态、参考配置步骤、回退方案、判断依据、实施风险与重要等级便于读者快速对照现状开展基线核查、整改加固和自查取证。内容覆盖账号权限最小化、密码策略与有效期、登录失败锁定、双因素认证、操作日志记录、SSL/TLS传输加密、访问限制以及防毒软件安装和定期安全检查更新等要求。已有245人学习适合作为SQL Server安全加固、日常巡检与合规检查的案头参考。1. 数据库加固清单不是抄一遍就行一份 22 项核查表能省下多少排查时间上周帮朋友看一台跑了多年的 SQL Server登录日志里 sa 账号的失败尝试一天几百次xp_cmdshell还开着网络协议里 Named Pipes 和 TCP/IP 一起监听——问题不是出在某个高深配置上而是基础加固清单从来没落地过。这份《SQL Server 数据库系统加固规范》就是干这个的把账号管理、认证授权、日志配置、通信协议、设备其他安全要求拆成 22 条带编号的核查项SHG-Mssql-01-01-01 到 04-01-02每条都写明实施目的、当前状态怎么查、操作步骤、回退方案和风险等级。它适合谁手上管着几台到几十台 SQL Server、要做等保自查或内网基线整改的 DBA 和运维以及需要给团队一份可执行 checklist 的负责人。不适合想找自动化加固脚本的人它是人工核查型规范落地靠一条条执行。2. 账号与认证授权六条核查项怎么逐条落地账号这块是整个规范里风险等级最高、也最容易翻车的部分。六条核查项01-01-01 至 01-01-06覆盖了账号独立、无效账号清理、启动账号权限、权限最小化、角色管理和空密码排查每一条都对应一个真实攻击面。理解它们的共同逻辑比逐条背命令更重要核心是“谁能连进来”和“连进来能干什么”这两件事都要收紧。2.1 账号独立与无效账号清理的执行顺序规范里 01-01-01 要求按用户分配账号避免共享01-01-02 要求删除或锁定无效账号。这两条有先后依赖——先清理僵尸账号再给真实用户建独立账号否则你会在一堆废弃账号里建新号越理越乱。第一步永远是盘点不是动手。规范给的查法是use master后查syslogins这个系统表在老版本里能直接看到密码哈希字段新版2005 之后已经换成sys.sql_logins和sys.server_principals照抄会报错。我一般用下面这组查询做盘点兼容性更好-- 盘点所有登录名、类型、是否启用、创建时间 SELECT name, type_desc, is_disabled, create_date, modify_date FROM sys.server_principals WHERE type IN (S,U,G) -- SSQL登录 UWindows登录 GWindows组 ORDER BY create_date; -- 单独看 SQL 登录的密码策略状态2005 才有 SELECT name, is_policy_checked, is_expiration_checked FROM sys.sql_logins;type_desc里SQL_LOGIN是数据库内建的账号WINDOWS_LOGIN是域/本地账号WINDOWS_GROUP是组——组账号最容易变成“谁都能用”的共享入口盘点时要重点看。create_date帮你识别哪些是装机时留下的、业务早没了的老账号。查出来之后删除用DROP LOGIN 账号名不确定就先ALTER LOGIN 账号名 DISABLE锁掉观察一周没人喊再删这是血泪经验直接删掉某个报表账号第二天凌晨跑批全挂的事我见过不止一次。建独立账号时规范给的sp_addlogin是 2000 时代的写法新版照样能用但不推荐用CREATE LOGIN更清晰-- 为不同业务/人员建立独立登录密码走强口令 CREATE LOGIN app_report WITH PASSWORD 这里放强口令, CHECK_POLICY ON; CREATE LOGIN dba_zhang WITH PASSWORD 这里放强口令, CHECK_POLICY ON;CHECK_POLICY ON会让 SQL Server 套用 Windows 的密码复杂度策略这是最省事的强口令落地方式比手工规定“12 位含大小写”可靠得多。2.2 启动账号权限与最小权限的配置边界01-01-03 管的是 SQL Server 服务以哪个 Windows 账号启动。默认安装经常用 LocalSystem 或 Administrators 组成员服务进程权限过高一旦数据库被提权攻击者拿到的就是接近系统级的权限。规范要求把服务账号从 User 组移除、不加入 Administrators只授予 SQLRunAs 所需的最小权限。实操上这条要格外小心因为改服务账号需要重启服务而且权限给少了服务起不来。常见做法是用 SQL Server 配置管理器改或者命令行# 查看当前各服务的启动账号 sc qc MSSQLSERVER sc qc SQLSERVERAGENT # 改启动账号需交互输入密码不要在脚本里明文写 sc config MSSQLSERVER obj DOMAIN\svc_sql password ***注意obj后面必须有空格这是sc命令的老坑。改完先别急着重启生产在测试机验证服务能正常启动、能读写数据文件目录、能访问备份路径再动生产。权限最小化的实操边界是数据文件目录、日志目录、备份目录的读写权限必须给足注册表项HKLM\SOFTWARE\Microsoft\Microsoft SQL Server的读权限必须有其余一律不给。01-01-04 和 01-01-05 讲数据库内的权限收敛取消业务账号不需要的服务器角色用数据库角色管理对象权限。这两条要一起做顺序是先建角色、再授角色、最后摘掉账号上的直接授权。直接给账号授对象权限的做法账号一多就彻底失控用角色是唯一能维护的方式-- 在业务库中建角色并授予对象级权限 USE SalesDB; CREATE ROLE role_report_reader; GRANT SELECT ON SCHEMA::dbo TO role_report_reader; GRANT EXECUTE ON OBJECT::dbo.usp_MonthlyReport TO role_report_reader; -- 把角色赋给具体账号避免直接授权 ALTER ROLE role_report_reader ADD MEMBER app_report;GRANT SELECT ON SCHEMA::dbo是库级粒度比逐个表授权好维护但要注意它会把该 schema 下未来新建的表也一并放开。如果业务对敏感性要求高就老老实实按表授。反过来服务器角色里sysadmin、securityadmin、bulkadmin这三个是重点审查对象业务账号身上挂着任何一个都要问清楚理由。2.3 空密码与弱口令的排查与整改01-01-06 的目标是清掉空密码账号、把包括 sa 在内的所有账号改成强口令规范明确要求 sa 至少 10 位。查空密码的原始语句是查syslogins里password is null的记录这个字段在新版已经不可用得换思路——新版判断空密码主要靠密码策略标志和实际认证测试-- 找出没启用密码策略检查的 SQL 登录这类账号最可能被设成弱口令 SELECT name, is_policy_checked, is_expiration_checked FROM sys.sql_logins WHERE is_policy_checked 0 OR is_expiration_checked 0; -- 确认 sa 是否被禁用最佳实践是禁用需要时再启用 SELECT name, is_disabled FROM sys.server_principals WHERE name sa;第一个查询结果里每一行都是一个待整改项is_policy_checked 0意味着这个账号可以设成123456而系统不拦。整改用ALTER LOGIN ... WITH PASSWORD加CHECK_POLICY ON改密码时如果旧密码不知道只要有ALTER ANY LOGIN权限就能强制重置这在接手别人环境时是救命功能也是要严格控制securityadmin角色的原因。sa 账号的处理建议是确认没有应用在用就直接ALTER LOGIN sa DISABLE必须用的场景改成强口令并限制登录来源结合后面的协议层限制。规范里sp_password的写法是旧版语法新版用ALTER LOGIN 账号 WITH PASSWORD 新口令更标准。改完记得跑一遍业务验证尤其是有定时任务的系统——用旧密码硬编码在连接串里的作业改完密码第二天必炸这就是为什么规范每条都写了回退方案。3. 日志与通信协议审计开关和加密配置的落地细节日志和协议这两块规范给的内容相对薄日志 1 条、协议 3 条但落地时踩的坑一点不少。日志的核心是“开了没、记了啥、存哪、留多久”协议的核心是“少开端口、开对端口、传的东西别裸奔”。这两块有个共同特点配置项都在图形界面里看起来简单但改完不验证等于没改。3.1 审计级别调整与登录日志的验证方法02-01-01 要求启用日志记录记录登录账号、成功与否、时间、来源 IP。规范给的路径是数据库属性里的“安全性”把审计级别调到“全部”身份验证改成“SQL Server 和 Windows”混合模式。审计级别“全部”对应的是同时记录成功和失败的登录只记失败的话攻击者成功登录的那一下你永远看不到这是很多环境的通病。图形界面改完之后必须用 SQL 验证确实生效-- 查看当前实例的登录审计级别0无 1仅失败 2仅成功 3成功和失败 EXEC xp_loginconfig audit level; -- 直接查实例配置 SELECT value_in_use FROM sys.configurations WHERE name audit level;value_in_use才是真正生效的值value是配置值两者不一致说明改完没重启或者没执行RECONFIGURE。登录日志落地在错误日志文件里默认位置在安装目录的LOG子目录文件名形如ERRORLOG、ERRORLOG.1。查最近登录记录最直接的方式是读错误日志EXEC sp_readerrorlog 0, 1, login;参数说明第一个 0 表示当前错误日志第二个 1 表示只读日志类型 1SQL Server第三个是过滤关键词。这个存储过程在规范的危险存储过程清单里也出现了说明它本身有信息泄露风险——能读错误日志的账号能看到实例路径、版本等敏感信息所以给业务账号授权时要避开。审计开了不等于留存够。错误日志默认会循环覆盖规范没写留存周期但实际做基线检查时通常要求不少于 6 个月。错误日志本身做不到得靠额外的审计功能SQL Server Audit2008 才有或者定期归档错误日志文件。这里要提醒一句老版本没有 SQL Server Audit只能靠登录触发器或者外部采集别指望一个开关解决所有审计需求。提示改完审计级别后用错误的密码连一次、再用正确的密码连一次然后sp_readerrorlog里两条都要能看到这才算验证通过。只改不验是这类配置最常见的失效原因。3.2 协议裁剪、TCP/IP 栈加固与强制加密03-01-01 要求只保留 TCP/IP、禁用其他协议。SQL Server 默认可能同时开着 Named Pipes、Shared Memory、VIA 等每多开一个就多一个攻击面。查看和修改通过 SQL Server 配置管理器的“SQL Server 网络配置”完成命令行方式也能查注册表确认# 查看已启用的协议注册表里 Enabled 为 1 表示启用 reg query HKLM\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL.1\MSSQLServer\SuperSocketNetLib /sMSSQL.1这个实例编号在不同安装里不一样用reg query HKLM\SOFTWARE\Microsoft\Microsoft SQL Server /s先找实例节点更稳妥。裁剪协议的风险等级规范标了“高”因为 Shared Memory 是本地连接用的直接禁用可能影响本机管理工具连接Named Pipes 禁了可能影响某些老应用。改之前先确认应用连接串里用的是哪种协议——这一步不做改完就是全公司喊数据库连不上。03-01-02 是 TCP/IP 栈加固改三个注册表键DisableIPSourceRouting设 2、EnableICMPRedirect设 0、SynAttackProtect设 2。这三个值的含义分别是禁用源路由防源路由欺骗、禁用 ICMP 重定向、开启 SYN 攻击防护。操作reg add HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters /v DisableIPSourceRouting /t REG_DWORD /d 2 /f reg add HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters /v EnableICMPRedirect /t REG_DWORD /d 0 /f reg add HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters /v SynAttackProtect /t REG_DWORD /d 2 /f/f是强制覆盖生产上建议先reg query看原值改完记录原值到变更单里这就是规范里“回退方案”的实际落地方式。注意SynAttackProtect设 2 后系统在 SYN 洪水下行为会变化极端情况下正常连接也可能被延迟压测环境要先观察。03-01-04 是强制协议加密规范路径是服务器网络配置工具的“常规”页勾选“强制协议加密”。这一条听起来最安全实际最坑勾上之后所有客户端连接必须用加密客户端驱动版本老、证书不受信任的直接连不上。老版本 SQL Server 用的是自签名证书客户端默认会校验失败并报证书链错误。常见做法是先确认所有客户端驱动支持加密、再在测试环境验证生产上稳妥的方式是给实例配置一张受信任的证书再启用强制加密别用默认自签名证书硬上。-- 检查实例是否已启用强制加密 SELECT value_in_use FROM sys.configurations WHERE name force encryption;这条查询返回 1 才算真开了。开了之后连接串里要加EncryptTrue;TrustServerCertificateTrue后者在自签名证书场景下必须加否则连不上——但这也意味着加密通道的证书校验被绕过安全性打了折扣属于“能用但不完美”的折中。4. 危险存储过程与补丁删之前怎么确认没人用设备其他安全要求这两条04-01-01 停用危险存储过程、04-01-02 安装补丁是整份规范里“看起来最猛、执行最需要怂”的部分。规范列了一长串建议删除的扩展存储过程从xp_cmdshell到xp_regwrite再到sp_OACreate系列每一个都能干出远超数据库范围的事。但直接照抄那一串sp_dropextendedproc执行下去出问题的概率极高因为业务代码里经常有看不见的依赖。4.1 危险存储过程的风险分级与删除前验证先说风险分级这决定了你能不能拍板删。xp_cmdshell能直接调系统命令是提权链里最经典的一环优先级最高sp_OACreate系列能创建 COM 对象可以读写文件、起进程危害等同xp_cmdshellxp_regread、xp_regwrite系列能读写注册表xp_dirtree、xp_subdirs能遍历目录常被用于信息收集。但风险高不等于随便删。删除前必须做依赖确认规范写的“判断依据调用存储过程检查是否存在”太单薄实际要查的是作业、存储过程、视图、函数里有没有引用-- 在所有库里搜索对象定义中是否引用了目标扩展存储过程 DECLARE keyword NVARCHAR(100) xp_cmdshell; EXEC sp_MSforeachdb IF DB_ID(?) 4 BEGIN USE [?]; SELECT DB_NAME() AS db_name, OBJECT_NAME(object_id) AS obj_name, TYPE_NAME(schema_id) AS obj_type FROM sys.sql_modules WHERE definition LIKE % keyword %; ENDsp_MSforeachdb是未公开的存储过程稳定但不是官方承诺的接口DB_ID(?) 4是为了排除系统库。这种全库扫描在设计不规范的环境里可能跑几分钟挑低峰期做。扫出来的结果要人工判断SQL Agent 作业步骤里引用的、业务存储过程里引用的都是删不得的只有测试代码引用或者完全没引用的才能进删除清单。规范给的删除语句分两种扩展存储过程用sp_dropextendedproc普通存储过程用DROP PROCEDURE。删之前统一先做备份式降级——把xp_cmdshell关掉而不是删掉可控性更好-- 关闭而不是删除需要时还能开回来 EXEC sp_configure show advanced options, 1; RECONFIGURE; EXEC sp_configure xp_cmdshell, 0; RECONFIGURE;这是我对xp_cmdshell的默认处理方式磁盘上留着、功能关掉比删了之后哪天业务真要用再去翻备份强。sp_OACreate系列没有配置开关只能删所以更要做依赖确认。删的时候一条条来每删一条立刻验证用应用账号调用一次确认报“对象不存在”错误而不是报别的权限错。4.2 补丁版本核对与升级窗口的安排04-01-02 要求打最新补丁规范给了 SQL Server 2000 的版本号和 SP 对应关系8.00.194 到 8.00.2039。这段内容明显是 2000 时代的产物现在还在用 2000 的环境基本属于“动不了”的状态规范里这条对它的实际价值是提醒你记录版本、别裸奔。查版本用SELECT VERSION返回里带版本号。判断要不要升级标准做法是对照官方补丁列表比对内部版本号。规范回退方案写的是“无”这一条必须重点提醒补丁升级没有可靠回退路径出问题直接删了重装所以升级前一定要有完整备份数据文件加日志、并且验证过备份能还原。升级窗口安排上我的习惯是先查VERSION记录基线版本再在测试实例上打一遍观察一周无异常生产打补丁前确认三项——完整备份完成、业务低峰窗口确认、回退方案是备份还原而不是卸载补丁。老版本升级大版本比如 2008 到 2012还要额外考虑兼容级别、SQL Server Agent 作业、链接服务器的驱动兼容性这些在补丁清单里看不出来得单独排。5. 把 22 条核查项跑成一套可复用的巡检流程规范的价值不在于那 22 条编号本身在于它给了一个“每条都有判断依据和回退方案”的结构。我把这份清单用过五六次之后沉淀出一个固定套路先跑只读盘点、再按风险等级排序整改、每条整改必须有验证语句、验证不过就回退。盘点阶段把能只读查的全查完一个脚本出来一张表-- 一次性盘点关键安全状态 SELECT 登录账号 AS item, CAST(COUNT(*) AS VARCHAR) AS detail FROM sys.server_principals WHERE type IN (S,U) UNION ALL SELECT 密码策略未启用的SQL登录, CAST(COUNT(*) AS VARCHAR) FROM sys.sql_logins WHERE is_policy_checked 0 UNION ALL SELECT 启用状态的sa, CAST(COUNT(*) AS VARCHAR) FROM sys.server_principals WHERE name sa AND is_disabled 0 UNION ALL SELECT 审计级别, CAST(value_in_use AS VARCHAR) FROM sys.configurations WHERE name audit level UNION ALL SELECT 强制加密, CAST(value_in_use AS VARCHAR) FROM sys.configurations WHERE name force encryption UNION ALL SELECT xp_cmdshell状态, CAST(value_in_use AS VARCHAR) FROM sys.configurations WHERE name xp_cmdshell;这一段跑完账号、审计、加密、危险功能四个高危项的当前状态一目了然结果直接填进核查表“系统当前状态”那一栏。整改顺序按风险等级排我的固定顺序是先关xp_cmdshell和sp_OACreate风险高、影响面小、再清空密码和禁用 sa风险高、影响面中等、然后收敛账号权限和角色风险中、需要业务配合、最后动启动账号、协议裁剪和强制加密风险高但影响面大必须走变更流程。每条整改的验证语句我单独存一份形成闭环。下面这个表是我实际用的核查表结构比规范原文多了两列核查项编号风险等级盘点语句整改动作验证语句回退方式负责人完成日期01-01-06★查is_policy_checked0改强口令并启用策略再查一遍确认无 0 值记录原密码——02-01-01★★★xp_loginconfig audit level改为“全部”错误登录后查sp_readerrorlog改回原值——04-01-01★全库扫sql_modules关闭或删除调用返回对象不存在重建或开配置——这个表的关键不是列多是“验证语句”和“回退方式”两列必须填实。我见过太多核查表这两列写“无”或者“按需回退”真出事的时候等于没有。补丁那条尤其要写死——回退方式写“备份还原”就得先确认备份真的能还原不是备份文件存在就算数。最后一个具体技巧把上面那段盘点 SQL 存成一个.sql文件每次巡检先跑一遍结果和上次对比看哪些项回退了。加固不是一次性动作sysadmin 账号今天收敛了三个月后新来的同事为了应急又加回去这是常态。定期比对盘点结果比反复读规范有效得多。从那以后我每接一个新环境第一件事就是跑这套盘点脚本先把当前状态摸清再谈整改绝不上来就照清单删东西——规范是地图验证语句是路标回退方案才是后悔药。希望帮到你。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。