ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

等保测评SQL Server检查命令速查:从身份鉴别到备份恢复的完整流程

等保测评SQL Server检查命令速查:从身份鉴别到备份恢复的完整流程 等保测评进场后SQL Server 这块的检查往往最花时间。不是说它命令有多难而是测评项分散得很——身份鉴别、访问控制、安全审计、数据完整性、备份恢复几乎每一项都要在数据库上取证据。更麻烦的是 SQL Server 自身的权限体系复杂sysadmin、serveradmin 这些固定服务器角色一旦多给了人整库就等于裸奔。这篇文章我把在测评现场实际用到的 SQL Server 检查命令整理成一套能复现的流程按这个顺序敲下来该查的查完证据链也就齐了。不光是等保测评能用日常做数据库安全自查、加固后复查也一样用得上。1. 等保测评中SQL Server检查的整体思路与准备1.1 SQL Server要检查的核心维度有哪些等保测评对数据库的要求归纳起来其实就是五个层面身份鉴别、访问控制、安全审计、数据完整性、备份恢复。老版本 SQL Server 和新版本在这几个层面的检查手段基本一致差异主要体现在命令输出字段和部分功能的可用性上比如 SQL Server 2012 以后审计功能才真正完善SQL Server 2016 之后 TDE 透明数据加密也更容易配置。身份鉴别重点看三件事登录模式是混合模式还是仅 Windows 身份验证、SQL 登录账号是否强制了密码策略、是否存在空口令或弱口令账号。访问控制主要看 sysadmin、db_owner 这类高权限角色的成员是否过多guest 用户是否开着sa 账号是否还在用默认配置。安全审计看两点SQL Server 审计功能是否启用、错误日志中能否找到登录失败记录。数据完整性看数据库页面校验和是否开启近期有没有做过 DBCC CHECKDB。备份恢复看 msdb 里有没有完整备份记录完整备份、差异备份、日志备份的频率是否符合要求。这五个层面并不是孤立检查的。比如身份鉴别里发现问题通常会连带影响访问控制的判定审计没开就意味着登录失败的证据只能从错误日志里找。所以实际操作时我习惯按维度查但输出结论时会把问题项关联起来看。1.2 进场后先摸清环境再动手很多刚入行的测评人员拿到库就连上去敲命令第一个坑就出在这儿不先确认版本和权限有些命令在不同版本上行为不一样权限不足时还会报错现场浪费时间。我的习惯是先跑这几条把环境和身份认清楚SELECT SERVERNAME AS ServerName, VERSION AS VersionInfo; SELECT SERVERPROPERTY(ProductVersion) AS ProductVersion, SERVERPROPERTY(Edition) AS Edition, SERVERPROPERTY(ProductLevel) AS ProductLevel; SELECT name, state_desc, recovery_model_desc, is_encrypted FROM sys.databases; SELECT IS_SRVROLEMEMBER(sysadmin) AS IsSysAdmin;第一段看实例名和版本。不同版本对应的测评基线判定会有一点差异比如 SQL Server 2012 以后审计功能完整但 SQL Server 2008 里只能靠扩展存储过程或触发器写报告时依据就不一样。第二段看所有数据库的当前状态、恢复模式、是否加密state_desc 如果是 OFFLINE、RESTORING、RECOVERING后面备份和完整性检查的判定都要调整。第三段确认当前连进来的账号是否有 sysadmin 权限等保检查中大量命令需要 VIEW SERVER STATE 权限权限不足时后续记录没法取到有效证据不如一开始就跟客户提清楚要一个合适权限的账号。环境摸清后再决定用什么工具。SSMS 图形界面适合看配置但证据截图不如命令输出清晰所以现场我基本都是 SSMS 开查询窗口用结果到文本模式或者直接 sqlcmd 连。多实例环境用 sqlcmd -S 服务器名\实例名 连接单实例直接连默认端口即可。2. 身份鉴别与访问控制登录、口令与权限的检查命令2.1 身份验证模式与密码策略怎么查SQL Server 的登录模式决定了身份鉴别的基础。Windows 身份验证模式下数据库自己不管口令完全依赖域或本地操作系统账号体系混合模式则允许 SQL 登录账号数据库需要独立管理口令复杂度和有效期。等保测评里经常遇到的一个问题就是客户开了混合模式但 SQL 登录账号的口令复杂度策略没启用这就属于身份鉴别方面的风险项。查看登录模式的命令SELECT CASE SERVERPROPERTY(IsIntegratedSecurityOnly) WHEN 0 THEN Mixed Mode WHEN 1 THEN Windows Only END AS LoginMode;IsIntegratedSecurityOnly 返回 0 表示混合模式返回 1 表示仅 Windows 身份验证。混合模式下必须重点看 SQL 登录账号的密码策略。查看所有 SQL 登录账号是否强制密码策略和过期策略SELECT name, is_policy_checked, is_expiration_checked, is_disabled FROM sys.sql_logins ORDER BY name;is_policy_checked 表示该登录名是否强制了 Windows 密码策略is_expiration_checked 表示是否强制密码过期策略。如果大量账号这两个字段都是 0说明口令可能长期不换、复杂度也不受约束。测评时只要有一条账号是 0就可以对应到“身份鉴别信息未定期更换、复杂度不符合要求”这类问题项。判断是否存在空口令账号用 PWDCOMPARE 函数SELECT name, CASE WHEN PWDCOMPARE(, password_hash) 1 THEN Empty Password ELSE Not Empty END AS BlankPasswordCheck FROM sys.sql_logins WHERE password_hash IS NOT NULL;PWDCOMPARE 的用法很简单第一个参数传明文密码第二个参数传 sys.sql_logins 里的 password_hash返回 1 说明匹配。这里用空字符串判断 SQL 登录是否为空口令实测非常有效。注意 PWDCOMPARE 不能用于 Windows 登录账号那是另一套验证体系也不需要在这里判断。2.2 登录账号、sa账号与高权限角色检查把所有登录账号列出来是访问控制检查的基础。命令SELECT name, type_desc, is_disabled, default_database_name, create_date, modify_date FROM sys.server_principals WHERE type IN (S, U) AND name NOT LIKE ##% ORDER BY name;type_desc 为 SQL_LOGIN 的是 SQL 账号为 WINDOWS_LOGIN 的是 Windows 账号。重点看有没有明显不属于业务需要的账号、长期不用的账号、已离职人员账号。等保测评一般还会看账号是否定期清理所以 create_date 和 modify_date 也有参考价值。sa 账号需要单独查SELECT name, is_disabled, is_policy_checked, is_expiration_checked FROM sys.server_principals WHERE name sa;如果 sa 启用、密码策略没开就属于高风险。很多历史库是安装时默认配置sa 一直没动过。整改建议里最直接的就是要么改名ALTER LOGIN sa WITH NAME 其他名称要么直接禁用ALTER LOGIN sa DISABLE然后换强口令。如果业务系统确实依赖 sa 登录那至少要把密码策略打开、口令换成高强度复杂度并在整改建议中强调应用改造优先于继续沿用 sa。看哪些账号拥有高权限服务器角色SELECT p.name AS LoginName, p.type_desc, r.name AS ServerRole FROM sys.server_principals p JOIN sys.server_role_members rm ON p.principal_id rm.member_principal_id JOIN sys.server_principals r ON rm.role_principal_id r.principal_id WHERE p.is_disabled 0 ORDER BY r.name, p.name;这条查询把 sysadmin、securityadmin、serveradmin、processadmin 等固定服务器角色的成员列出来。sysadmin 成员实际上拥有实例全部权限。如果某业务系统的普通运维账号挂在 sysadmin 里或者开发人员账号直接给了 systemadmin这就是典型的越权。报告里的建议一般是按最小权限原则拆分账号普通业务账号只授予所需数据库的 db_datareader、db_datawriter 等角色而不是直接给服务器级最高权限。2.3 数据库级权限与最小化授权判断服务器级权限查完还要落到数据库级。很多公司服务器角色管得不严但数据库角色也一样混乱最常见的是开发账号全部挂在 db_owner 里。对每个业务库执行USE [AdventureWorks]; GO SELECT r.name AS RoleName, m.name AS MemberName FROM sys.database_role_members rm JOIN sys.database_principals r ON rm.role_principal_id r.principal_id JOIN sys.database_principals m ON rm.member_principal_id m.principal_id WHERE r.name IN (db_owner, db_securityadmin, db_accessadmin) ORDER BY r.name, m.name;db_owner 在单库内拥有全部权限能改表结构、加索引、删数据人员一旦多后期出问题都分不清是谁改的。db_securityadmin 可以管理用户和权限也属于高危角色。这里建议看返回值里是否有非 DBA 的普通业务账号。另外还要看数据库的所有者和 guest 用户SELECT SUSER_SNAME(owner_sid) AS OwnerLogin, name AS DatabaseName FROM sys.databases; USE [AdventureWorks]; GO SELECT name FROM sys.database_principals WHERE name guest AND is_disabled 0;guest 用户启用意味着任何没有有效数据库用户的登录名都能通过 guest 映射进入库相当于把访问控制的大门留了一条缝。正常情况下业务库建议禁用 guest。3. 安全审计与日志审计配置、错误日志和登录取证3.1 SQL Server审计功能是否真的在记录等保测评里安全审计的要求覆盖到每个用户也就是说登录成功、登录失败、权限变更、关键操作都应该有记录。SQL Server 自带审计功能从 2012 年开始比较成熟之前的老库更多靠错误日志和触发器。查看审计配置的命令SELECT name, is_enabled, has_old_backward_compatible_audit FROM sys.server_audits; SELECT name, is_enabled FROM sys.server_audit_specifications; SELECT name, is_enabled FROM sys.database_audit_specifications;如果 sys.server_audits 查询结果为空说明实例级别根本没创建审计。翻翻是否有 SQL Server 登录触发器在记录登录行为SELECT name, is_disabled, create_date FROM sys.server_triggers;有些客户的 DBA 会用触发器把登录成功、失败信息写进自定义表这可以作为审计覆盖的替代证据但说明书写起来要额外注意触发器方案和原生审计相比在权限变更审计方面覆盖不全。如果客户已经配置了审计建议把审计事件也确认一遍。服务器级别审计规范里一般应包含 FAILED_LOGIN_GROUP 和 SUCCESSFUL_LOGIN_GROUP数据库级别审计规范里应包含 SCHEMA_OBJECT_ACCESS_GROUP 或 DATABASE_PRINCIPAL_CHANGE_GROUP 之类的关键事件。只开了审计但没配事件等于没开。3.2 错误日志与登录记录排查没有原生审计时错误日志是最直接的登录取证来源。SQL Server 错误日志会记录“Login failed for user”这类信息默认保留几个历史文件。命令EXEC xp_readerrorlog 0, 1, N%Login failed%, NULL, NULL, NULL, NDESC; EXEC xp_readerrorlog 0, 1, N%Login succeeded%, NULL, NULL, NULL, NDESC;xp_readerrorlog 参数含义第一个参数是日志文件编号0 表示当前日志第二个参数 1 表示错误日志2 是代理日志第三、四个参数是要过滤的字符串第五、六个是起始和结束时间最后一个参数 NDESC 表示按时间倒序。执行后能看到失败的登录账号、来源 IP、失败时间审计证据就有了。如果不能直接跑这个存储过程查一下错误日志文件所在的路径SELECT SERVERPROPERTY(ErrorLogFileName) AS ErrorLogPath;再去对应目录把 ERRORLOG 和 ERRORLOG.1 等文件打开搜索 login failed。这个方法在客户权限管控严格、不想给查询权限时也能用。当前连接的会话信息也值得看一眼SELECT session_id, login_name, host_name, program_name, login_time FROM sys.dm_exec_sessions WHERE is_user_process 1;这条能看当时有哪些账号在连、从哪里连的、用的什么客户端工具。如果发现一个未知账号正连着库结合登录失败记录一起分析基本能判断是否存在可疑访问。3.3 高危扩展与危险配置检查入侵防范在数据库层的体现主要是看有没有不必要的扩展存储过程、危险配置项和未加密的连接。SQL Server 里最容易出问题的配置是 xp_cmdshell、OLE Automation Procedures、CLR 和远程访问。查询SELECT name, value_in_use FROM sys.configurations WHERE name IN (xp_cmdshell, Ole Automation Procedures, clr enabled, remote access, contained database authentication);xp_cmdshell 一旦开启SQL 登录账号就可能通过这个扩展执行操作系统命令。 etc 测评里看到 value_in_use 为 1 的 xp_cmdshell 基本就是高风险项整改建议一般是确认业务不需要后立即关闭。OLE Automation Procedures 允许在 SQL 里调用 COM 对象CLR 则允许运行 .NET 程序集这两个在业务软件没有明确依赖的情况下都应该保持关闭。contained database authentication 开启后包含数据库用户可以不用实例登录名直接连接等于绕开了服务器级身份鉴别一般不建议开。还可以查一下是否存在可疑的扩展存储过程开放情况SELECT name, is_disabled FROM sys.server_triggers WHERE is_disabled 0; EXEC sp_helprotect;sp_helprotect 返回当前数据库中对象的权限列表内容可能很多但能帮助筛查是否存在对 public 角色开放的敏感对象权限。4. 数据完整性和备份恢复备份历史、校验和与DBCC检查4.1 数据库状态、文件和页面校验数据完整性检查首先要看数据库本身状态和恢复模式。恢复模式如果是 SIMPLE日志备份就没有意义等保测评里备份策略的判定要从完整备份开始算。SELECT name, state_desc, recovery_model_desc, is_encrypted, page_verify_option_desc FROM sys.databases;sys.databases 里没有直接的 page_verify_option_desc 列这是一个容易记混的地方。页面校验和需要看 sys.database_filesUSE [AdventureWorks]; GO SELECT name, physical_name, type_desc, size, page_verify_option_desc FROM sys.database_files;page_verify_option_desc 只有两个常见值CHECKSUM 和 NONE老库常见 TORN_PAGE_DETECTION。SQL Server 默认在新建数据库时启用 CHECKSUM但一些从 2005、2008 迁移过来的老库可能还是 NONE。如果页面校验和没开数据库在 I/O 错误面前就没有自检能力恢复时也可能发现损坏页所以这个项在等保测评里通常建议开启ALTER DATABASE [AdventureWorks] SET PAGE_VERIFY CHECKSUM;这条属于整改命令测评现场可以只在报告里建议等客户确认业务窗口后再执行。4.2 DBCC CHECKDB怎么用而不踩坑DBCC CHECKDB 是数据库完整性的终极检查手段能检测逻辑和物理一致性。但等保测评现场不能乱跑尤其业务大库全库 CHECKDB 的 I/O 开销非常高。我通常在测评时只做两件事一是查数据库最近的 DBCC 执行记录或维护计划二是确有必要时才在低峰窗口跑一个物理一致性快速检查。查看维护计划里的数据库一致性检查作业USE msdb; GO SELECT j.name AS JobName, j.enabled, j.date_created, j.description FROM sysjobs j ORDER BY j.name;如果作业列表里有“数据库完整性检查”类似的作业且 enabled 1说明客户有例行机制。如果作业里没有再结合备份记录判断。这里要注意一个细节很多维护计划作业是用 dbo 账号建的如果该账号密码到期或被禁用历史记录可能停更所以最好同时看作业最近是否成功执行过SELECT j.name, j.enabled, jh.run_date, jh.run_time, jh.run_status FROM msdb.dbo.sysjobs j LEFT JOIN msdb.dbo.sysjobhistory jh ON j.job_id jh.job_id ORDER BY jh.run_date DESC;run_status 为 1 表示成功。如果作业最后执行时间已经是两三个月之前完整性检查这项就没法判合规。如果确实需要现场跑 CHECKDB我建议用物理模式控制开销DBCC CHECKDB (AdventureWorks) WITH NO_INFOMSGS, PHYSICAL_ONLY;NO_INFOMSGS 减少输出PHYSICAL_ONLY 只检查页结构、链指针等物理方面不检查逻辑一致性性能开销比完整 CHECKDB 小很多但仍有 I/O 压力。一定要避业务高峰期并在执行前和客户 DBA 确认。4.3 备份策略与备份记录核对备份恢复检查是等保测评里特别容易和客户起争论的环节。很多客户说“我们做了备份”但实际用的是虚拟化快照或第三方备份软件这些备份不一定写入 msdb 的备份历史表。所以第一步还是先查库里的备份记录SELECT database_name, type AS BackupType, backup_start_date, backup_finish_date, backup_size / 1024 / 1024 AS Size_MB FROM msdb.dbo.backupset WHERE database_name AdventureWorks ORDER BY backup_start_date DESC;type 字段的含义D 完整备份、I 差异备份、L 日志备份。正常等保三级要求里完整备份至少每周一次日志备份按恢复点目标而定业务系统一般建议每天差异加定期日志。测评时可以看最近一次完整备份是否在合规周期内比如一个月内没有完整备份恢复点就无法覆盖显然不合格。备份设备位置也要看SELECT b.database_name, b.backup_start_date, f.physical_device_name FROM msdb.dbo.backupset b LEFT JOIN msdb.dbo.backupmediafamily f ON b.media_set_id f.media_set_id WHERE b.database_name AdventureWorks ORDER BY b.backup_start_date DESC;physical_device_name 能看出备份是写到磁盘、磁带还是网络共享路径。如果备份路径在本机 C 盘磁盘故障时备份一样丢恢复性就无从谈起。报告里可以建议备份介质与数据库文件分离存储。第三方备份没写入 msdb 的情况要单独处理。我的做法是msdb 查不到记录先不急着判不合格直接问客户备份怎么做的让 DBA 截图备份软件的任务记录和恢复演练记录。如果客户能提供合理证据报告可以写“备份机制不在SQL Server内记录由第三方平台统一管理判定为合规”。这样既客观也少跟客户吵架。反过来如果客户连备份软件记录都拿不出来那就该记问题了。5. 等保测评SQL Server命令速查与现场常见问题5.1 高频命令速查表现场检查时不需要把上面所有命令都过一遍按测评项挑重点跑就行。我把常用命令整理成速查表进场照着刷检查项核心命令版本与环境SELECT VERSION;、SELECT SERVERPROPERTY(ProductVersion);身份验证模式SELECT SERVERPROPERTY(IsIntegratedSecurityOnly);SQL登录密码策略SELECT name, is_policy_checked, is_expiration_checked FROM sys.sql_logins;空口令检测SELECT name, PWDCOMPARE(, password_hash) FROM sys.sql_logins;登录账号列表SELECT name, type_desc, is_disabled FROM sys.server_principals WHERE type IN (S,U);sa账号状态SELECT name, is_disabled FROM sys.server_principals WHERE name sa;服务器角色成员SELECT p.name, r.name FROM sys.server_principals p JOIN sys.server_role_members rm ON p.principal_id rm.member_principal_id JOIN sys.server_principals r ON rm.role_principal_id r.principal_id;数据库角色成员USE 库名; SELECT r.name, m.name FROM sys.database_role_members rm JOIN sys.database_principals r ON rm.role_principal_id r.principal_id JOIN sys.database_principals m ON rm.member_principal_id m.principal_id;审计配置SELECT name, is_enabled FROM sys.server_audits;登录失败记录EXEC xp_readerrorlog 0, 1, N%Login failed%, NULL, NULL, NULL, NDESC;高危配置SELECT name, value_in_use FROM sys.configurations WHERE name IN (xp_cmdshell,Ole Automation Procedures,clr enabled);数据库状态与加密SELECT name, state_desc, recovery_model_desc, is_encrypted FROM sys.databases;页面校验和USE 库名; SELECT name, page_verify_option_desc FROM sys.database_files;备份记录SELECT database_name, type, backup_start_date, backup_size FROM msdb.dbo.backupset ORDER BY backup_start_date DESC;维护作业USE msdb; SELECT name, enabled, date_created FROM sysjobs;每执行一条命令后在 SSMS 里把结果切到“结果到文本”再另存为 txt 文件比截图更清晰后续写报告直接引用结果。5.2 测评现场容易踩的几个坑第一个坑是权限不足。有些客户只给一个 db_datareader 账号跑 xp_readerrorlog 直接报“权限不足”。这种情况别硬刚明确告诉客户测评需要 VIEW SERVER STATE 权限一般走申请流程很快能拿到。如果客户确实不给那就退一步让 DBA 代为执行并输出结果截图里必须保留执行账号。第二个坑是命令在旧版本上的兼容问题。SQL Server 2008 不支持部分新视图字段比如 sys.server_audits 在 2008 R2 里可能没有问题但在 SQL Server 2005 里根本不存在。进场第一步先跑版本信息的目的就在这里版本太老的话部分命令必须换写法比如用 xp_logininfo 查登录信息而不是直接查视图。第三个坑是 PWDCOMPARE 的结果受大小写和排序规则影响SQL Server 的登录密码本身区分大小写所以 PWDCOMPARE(, password_hash) 用来查空口令没问题但拿它去验证“密码是否等于账号名”这种弱口令时要注意排序规则。别在现场反复试错容易把账号锁住。遇到疑似弱口令建议让客户 DBA 用内部策略检查工具确认而不是在测评环境里暴力尝试。第四个坑是备份历史记录和实际备份情况不一致。第三方备份软件对 SQL Server 做 VSS 快照时通常不会写 msdb 的 backupset 表这类情况只按命令结果判不合规会冤枉客户。反过来有些客户的备份作业每天都在跑但备份文件没有做过恢复演练报告里也要指出缺乏恢复验证。我的建议是备份检查分为两步命令看记录访谈问流程两者对得上才算证据完整。第五个坑是执行顺序。先查环境再查配置先查 SELECT 再考虑是否需要执行 DBCC。测评人员不是挨骂的工具人数据库是客户的命根子。所有可能产生性能影响的命令必须在客户 DBA 确认的窗口内执行。5.3 从命令结果到报告素材测评报告的最后一步是把命令输出转成问题项和建议。这里有三个经验可以分享。第一个经验是保存证据时带上下文。SSMS 里把查询结果输出到文件文件名建议写成“实例名_检查项_日期.txt”比如SQL01_identity_auth_20250220.txt。多个结果合并到一个文件里后续写报告要找某一条记录时就特别省事。截图的时效性不如文本输出文本结果还能做二次分析比如统计登录失败次数。第二个经验是判据要一致。同样的 is_policy_checked 0在一个库里判了不合规在另一个库里也必须是相同结论不能因为客户态度不同而改变判定标准。测评独立性靠的就是这个。如果想给客户追加建议比如“该账号是运维脚本专用可以申请例外”那也应该在报告的整改建议里写明例外理由而不是在原始判定上放水。第三个经验是问题项要有整改闭环。命令发现问题后给客户一条可落地的 ALTER 语句比单纯写一句“建议修改口令复杂度”更有价值。比如ALTER LOGIN [ops_user] WITH CHECK_POLICY ON, CHECK_EXPIRATION ON;写成这样客户拿到报告直接执行就行落地成本低配合意愿也高。我个人在现场还有个习惯最后把所有检查结果整理成一张对照表每一项测评要求、对应命令、实际结果、判定结论、整改建议。这不是给客户看的是给自己保存证据链用的。数据库测评最怕的就是几个月后客户问“当时那条记录是怎么查的”你现在留好命令和原始输出后面怎么问都能翻出来。这套流程从头到尾跑一遍大概一两个小时取决于库的数量和关联账号的多少。整体思路不复杂难的是把每个判断背后的依据想清楚。命令只是抓手真正值钱的是你能否在拿到结果后知道哪里有问题、为什么有问题、怎么改才不踩生产环境的坑。数据库不是拿来练手的沙盒能用 SELECT 查到的就别乱改配置动手之前一定先确认影响范围。
返回列表