前几天帮一个客户处理数据库服务器频繁告警,打开SQL Server错误日志一看,几千条登录失败记录,登录名清一色都是sa。这些年只要服务器开了外网访问,或者内网里有主机扫描,SQL Server的sa弱口令爆破几乎是每天都会遇到的常规动作。其实应对这种攻击的手段非常多,但最省心、最有效的第一道闸门,恰恰是最多人忽略的一个操作:直接禁用掉sa账户。
这话听起来简单,实际操作里涉及的细节、坑和前置条件非常多。我见过不少同事上来就执行ALTER LOGIN [sa] DISABLE;,结果发现SQL Agent作业跑不了了,数据库owner变成无效账户,更尴尬的是Windows账号居然没有系统管理员权限,最后只能费劲地用单用户模式把sa启回来。这篇文章就把这些前置检查、操作步骤、连带加固和应急恢复整个链路完整写一遍,照着做基本不会翻车。
1. sa账户为什么是SQL Server的第一攻击目标
1.1 sa账户的本质:绕过Windows认证的超级管理员入口
要理解为什么所有人盯着sa不放,先要清楚这个账户在SQL Server里的定位。sa是SQL Server安装时默认创建的超级管理员登录名,属于sysadmin固定服务器角色,这意味着只要拿到sa的密码,就相当于拿到了整个数据库实例的完全控制权,读所有数据库、执行系统存储过程、修改服务器配置、调用xp_cmdshell甚至访问操作系统命令,全都畅通无阻。
更关键的是,sa走的是SQL Server身份验证,不是Windows身份验证。Windows身份验证要求用户先通过操作系统的域账户或本地账户认证,攻击者就算想撞库,也还得先摸清Windows账户体系。而SQL Server身份验证完全独立,只要知道登录名和密码,从任何一台能通过网络连接到1433端口的机器上都能直接发起登录尝试,不需要操作系统层面的任何权限。这等于攻击者少过一扇门,只需要撞开一个密码就行。
而且sa这个登录名在99%的实例上都是存在的,名字固定不变,连枚举用户名这一步都省了。攻击者拿到一个开放了1433端口的IP,第一反应就是用sa加一个弱密码字典开始爆破,密码正确率高不高取决于运气,但尝试成本极低。这就是sa成为第一攻击目标的核心原因——它是一个固定存在、固定名字、权限极大、走纯口令认证的超级入口。
1.2 爆破sa的典型攻击路径与观测特征
爆破sa的流量特征其实非常明显。以我处理过的案例来说,最常见的路径是攻击者先扫描全网段开放TCP 1433端口的主机,然后针对每一台存活主机尝试登录名sa和一批弱密码。密码字典里基本都包含admin、123456、sa、sa123、password、!QAZ2wsx之类的组合,如果服务器密码设得简单,运气成分占很大比重地就会被打穿。
在SQL Server这边,每次登录失败都会写入错误日志,错误号是18456。用这条语句就能快速查看最近登录失败的情况:
EXEC xp_readerrorlog 0, 1, N'Login failed', N'sa', N'08/01/2025', N'09/01/2025';如果环境里开了默认审计,也可以用sys.dm_exec_sessions看有没有异常活动,但更直接的是看错误日志里有没有大量来自同一IP的Login failed for user 'sa'记录。真实被爆破的实例,错误日志往往是几千行、几万行连续刷屏,时间间隔都在几秒以内,这种节奏不可能是人为输错密码造成的。
还有一个容易忽略的观察点:SQL Server默认开启了sa登录,但很多系统安装完以后从来没有为sa设置过强密码,甚至有的直接在连接字符串里硬编码了sa的弱密码。这相当于把超级管理员的钥匙挂在门口,爆破只是时间问题。前面提到的客户就是这样,检查密码之后发现竟然是sa123,这种状态下不被打穿反而奇怪。
1.3 禁用sa是"先堵门"而非"终极方案"
这里要澄清一个观点:禁用sa只能堵住一个固定的登录入口,它解决的是针对固定超级账号的爆破风险,并不能替代密码策略、网络隔离、审计、最小权限这些纵深防御措施。但为什么大家还是把这个操作放在安全加固清单的最前面?
因为它的投入产出比极高。一条T-SQL命令执行完,攻击者针对这个实例的sa爆破路径就完全失效了,即使密码字典里正好有这个密码,也会因为账户被禁用而登录失败。这个操作不依赖补丁版本、不增加硬件成本、不需要改动应用代码(前提是应用原本就没用sa),是安全加固里少有的"一行命令买断一个攻击面"的动作。所以门要堵,但堵完不等于完事,后续的其他加固同样不能省。
2. 动手禁用前,先把这些"后路"留好
2.1 先确认Windows管理员的sysadmin角色还在
这是整个操作里最容易翻车的一步。禁用sa必须保证另一个具备sysadmin权限的登录名还能正常工作,否则一旦sa被禁用,又没有一个可用的Windows账号能进来,就只能通过单用户模式或DAC(专用管理员连接)去恢复了,非常被动。
建议在禁用前先执行下面这条语句,列出实例上所有具备sysadmin角色的服务器登录名:
SELECT sp.name AS login_name, sp.type_desc, sp.is_disabled FROM sys.server_role_members rm INNER JOIN sys.server_principals AS sp ON rm.member_principal_id = sp.principal_id WHERE rm.role_principal_id = ( SELECT principal_id FROM sys.server_principals WHERE name = 'sysadmin' );注意检查两点:一是确认存在至少一个Windows登录(比如[DOMAIN\admin]或本机的[MACHINE\Administrator])拥有sysadmin角色;二是这个Windows登录的is_disabled为0。很多生产服务器安装时只用了默认配置,Windows管理员组里确实有映射,但如果在域环境里这台机器的管理员账号被禁用或者组策略限制交互式登录,也会导致后续进不去。所以一定先在SSMS里断开所有SQL账号连接,只保留Windows身份验证连接试一次,确认能正常打开实例,再往下走。
如果查询结果里只有一个sa,那就需要先用Windows身份验证登录并手动创建一个新的sysadmin登录:
CREATE LOGIN [DOMAIN\admin_user] FROM WINDOWS; EXEC sp_addsrvrolemember 'DOMAIN\admin_user', 'sysadmin';创建完再重新检查一遍,确认新登录可用再做后续的禁用操作。
2.2 为应用系统创建专用账号并改好连接字符串
禁用sa前最大的现实问题不是操作本身,而是应用系统。老系统最喜欢干的事就是把连接字符串写成User ID=sa;Password=...,一旦sa被禁用,业务系统立刻大面积报错。所以禁用前最好的做法是先创建一个应用专用账号,赋予它业务所需的最小权限,然后把连接字符串切换过来。
创建应用账号的标准流程是:服务器级别创建登录名,数据库级别创建用户名,再分配角色。以ERP系统账号为例:
USE [master]; GO CREATE LOGIN [app_erp] WITH PASSWORD = N'这里放强密码', CHECK_POLICY = ON, CHECK_EXPIRATION = ON, DEFAULT_DATABASE = [YourDB]; GO USE [YourDB]; GO CREATE USER [app_erp] FOR LOGIN [app_erp]; GO ALTER ROLE db_datareader ADD MEMBER [app_erp]; ALTER ROLE db_datawriter ADD MEMBER [app_erp]; GO连接字符串的调整也要同步进行。原来可能是:
Server=10.0.0.5,1433;Database=YourDB;User Id=sa;Password=old_password;切换后是:
Server=10.0.0.5,1433;Database=YourDB;User Id=app_erp;Password=新的强密码;Encrypt=True;这里有一个细节很多人会忽略:CHECK_POLICY=ON意味着这个账号受Windows密码策略约束,有密码复杂度要求和过期时间。如果应用账号是给程序用的,最好按行业惯例设置CHECK_EXPIRATION=ON的同时在密码里做好轮换计划,否则密码过期当天应用就会连不上。当然如果不想处理密码过期,可以把CHECK_EXPIRATION设为OFF,但密码复杂度建议保留,不要为了省事把两个策略都关掉。
2.3 排查作业、链接服务器、维护计划里的sa引用
这一步容易被当成多余,但实际操作中坑最多的就是这里。SQL Server Agent里的作业步骤、维护计划、链接服务器、SSIS包,都可能写死了sa账号。先查Agent作业里的命令文本:
USE msdb; GO SELECT j.name AS job_name, s.step_name, s.command FROM dbo.sysjobs j INNER JOIN dbo.sysjobsteps s ON j.job_id = s.job_id WHERE s.command LIKE '%sa%';查询结果里凡是命令里有sa字样的步骤都要人工确认。常见的是sqlcmd -U sa -P ...、EXEC xp_cmdshell 'sqlcmd -U sa ...',这些命令在sa被禁用后全部会失败,而且运行结果往往是作业失败告警,排查起来比较隐蔽。
链接服务器也要查:
SELECT srv.name AS linked_server_name, ll.local_principal_id, sp.name AS local_login_name FROM sys.servers srv LEFT JOIN sys.linked_logins ll ON srv.server_id = ll.server_id LEFT JOIN sys.server_principals sp ON ll.local_principal_id = sp.principal_id WHERE sp.name = 'sa';有sa引用的话,右键链接服务器属性,把"使用此安全上下文建立连接"里的本地登录名改成新建的应用账号,注意远端登录名和密码也要同步改成远端实例能识别的凭据。如果有维护计划指向sa,同样要一一改掉。这些前置工作做完,才算是真正清空了sa的依赖,禁用之后不会有业务反扑。
3. 禁用sa账户的几种方式与操作细节
3.1 图形界面方式:SSMS里的三步操作
SSMS操作是最直观的方式,适合单实例、不频繁变更的环境。流程是:连接到实例后,在左侧对象资源管理器中展开"安全性"→"登录名",找到sa,右键选择"属性",在"常规"页面确认登录名是sa,然后切到"状态"页面,把"登录"这一项从"已启用"改成"已禁用",点击确定即可。
这个操作执行完,sa登录名会被标记为禁用,后续任何使用sa登录的连接请求都会收到18456错误。图形界面的好处是所见即所得,不容易输错命令,但缺点是如果一次要管几十台服务器,一台台点下来效率太低,而且很容易漏掉某台。所以在我自己的运维习惯里,图形界面只用来做单台确认,批处理统一使用T-SQL。
另外需要注意,图形界面方式禁用sa之后,一定要到对象资源管理器里刷新一下登录名的状态,确认sa前面的图标变成了一个向下的箭头,这才是禁用的可视标志。
3.2 T-SQL方式:一行命令禁用,注意执行上下文
T-SQL方式推荐在生产环境推广,因为可重复、可审计、可批量执行。禁用sa的语句非常简单:
ALTER LOGIN [sa] DISABLE;执行完后通过下面这条语句验证状态:
SELECT name, is_disabled, type_desc FROM sys.sql_logins WHERE name = 'sa';结果里is_disabled为1表示禁用成功。有一点必须提醒:执行ALTER LOGIN [sa] DISABLE时需要有ALTER ANY LOGIN权限,通常sysadmin或者securityadmin角色成员才能执行。另外这条语句在执行时不会影响当前的sa会话,也就是说如果你正用sa登录着,执行完这条命令后当前会话还是能继续用,只是新的sa连接会被拒绝。这个行为在安全应急的时候有用,可以在不中断现有连接的情况下快速封堵新的登录,但也要注意如果当前会话是sa开的,后续操作要赶紧切到其他管理员账号,避免操作到一半被审计发现没有可用管理员。
如果是批量管理多台服务器,可以用Invoke-Sqlcmd配合脚本循环执行:
$servers = @('SERVER01', 'SERVER02', 'SERVER03') foreach ($server in $servers) { Invoke-Sqlcmd -ServerInstance $server -Query "ALTER LOGIN [sa] DISABLE;" Invoke-Sqlcmd -ServerInstance $server -Query "SELECT name, is_disabled FROM sys.sql_logins WHERE name = 'sa';" }批量执行时脚本里务必加上日志记录,明确哪些实例执行成功、哪些失败,避免漏掉某一台。
3.3 更彻底的方式:切换为Windows身份验证模式
如果说禁用sa是"关掉一个账号",改成Windows身份验证模式就是"把SQL Server身份验证这条链路整个关掉"。在这个模式下,所有纯SQL账号登录请求都会失败,包括sa、包括新建的SQL登录名,只剩Windows认证路径可用。
切换方式有两种。图形界面在服务器属性→安全性→服务器身份验证里,把"SQL Server和Windows身份验证模式"改成"Windows身份验证模式",改完需要重启SQL Server服务生效。
注册表方式是这样:
USE [master]; GO EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'LoginMode', REG_DWORD, 1; GO注册表LoginMode的值1表示Windows身份验证模式,2表示混合模式。改完必须重启SQL Server服务才能生效:
Restart-Service -Name 'MSSQLSERVER' -Force这种方式的优点是一劳永逸,连爆破的入口都直接消失,非常推荐在纯内网、Windows域环境、且应用全部使用Windows身份验证的场合用。缺点也很明显:一旦有应用或工具必须使用SQL账号登录,这个模式会直接导致连接失败,落地时对环境的判断要求很高。我的建议是:如果你的组织已经有AD域、应用的连接字符串里都用了集成安全(Integrated Security=True),优先级最高的方案是Windows身份验证模式加禁用sa双管齐下;如果还有一堆老旧系统必须要SQL账号,就先禁用sa、保留混合模式,等应用逐渐改造完再切。
3.4 验证禁用效果与常见误判
禁用或者切换模式后,验证不是简单用sa连一次就行,要做三层检查。
第一层,状态检查。执行前面提到的sys.sql_logins查询,确认sa的is_disabled = 1。
第二层,实际连接测试。新建一个查询窗口,使用SQL Server身份验证输入sa和原密码连接,预期结果是收到如下错误:
用户 'sa' 登录失败。原因: 基于帐户的登录已禁用。看到这个错误才说明禁用在网络层和控制层都生效了。
第三层,检查错误日志确认攻击路径已经中断。用:
EXEC xp_readerrorlog 0, 1, N'Login failed', N'sa';如果错误日志里还在持续出现大量sa登录失败记录,这些记录现在都应该是"已禁用"的提示,而不是"密码错误"。密码错误说明攻击者在尝试撞库,禁用状态说明即使密码对了也进不来,这是两个完全不同的安全级别。看到日志里的提示从"密码不匹配"变成"已禁用",就可以放心了。
有一点容易误判的是:切换Windows身份验证模式后,刚才说的xp_readerrorlog里仍然可能出现很多sa登录失败记录,这并不是sa被启用了,而是SQL Server在网络层接收到SQL账号登录请求后,发现服务器处于Windows身份验证模式,于是拒绝该请求并记录日志。看到读日志有大量记录不用慌,先确认当前身份验证模式是还是不是预期状态。
4. 禁用sa之后的连带加固,这几项建议一起做掉
4.1 修改默认1433端口并启用防火墙策略
禁用sa相当于堵住了登录口的钥匙孔,但门牌号没换,攻击者照样能找到这扇门。默认情况下SQL Server监听1433端口,全网扫描器最喜欢扫这个端口。把端口改掉,能显著降低被扫描命中的概率。
在SQL Server配置管理器里改端口的路径是:SQL Server网络配置→MSSQLSERVER的协议→右键TCP/IP→属性→IP地址→拉到最底部IPAll→TCP端口改为自定义端口,比如14333。改完后需要重启SQL Server服务。
如果是命令行方式,可以用PowerShell改注册表:
$port = '14333' Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQLServer\SuperSocketNetLib\Tcp\IPAll' -Name 'TcpPort' -Value $port Restart-Service -Name 'MSSQLSERVER'注意注册表路径中的MSSQL15.MSSQLSERVER对应SQL Server 2019,不同版本的实例名不一样,如果是命名实例或者更新版本,路径要相应调整。
改端口的副作用是:所有应用连接字符串里的端口都要同步修改,否则应用连不上。如果应用比较多,建议先在测试环境把连接字符串配置成统一读取配置中心的方式,降低后续变更成本。防火墙层面也要同步放行新端口,默认1433在绝大多数企业防火墙策略里都是重点关注对象,换成一个不常见的端口可以减少非常多的扫描流量。
4.2 开启登录审计,让误连有据可查
禁用sa之后,很多运维会误以为登录安全问题就结束了,其实这时正是观察攻击行为的好时机。默认SQL Server只把登录失败事件记到错误日志里,信息非常粗粒度。更规范的做法是启用SQL Server Audit,专门记录失败登录的源IP和攻击频率。
创建审计的方式如下:
USE [master]; GO CREATE SERVER AUDIT [Audit_FailedLogin] TO FILE (FILEPATH = N'D:\SQLAudit\', MAXSIZE = 100 MB) WITH (ON_FAILURE = CONTINUE); GO CREATE SERVER AUDIT SPECIFICATION [AuditSpec_FailedLogin] FOR SERVER AUDIT [Audit_FailedLogin] ADD (FAILED_LOGIN_GROUP); GO ALTER SERVER AUDIT SPECIFICATION [AuditSpec_FailedLogin] WITH (STATE = ON); GO ALTER SERVER AUDIT [Audit_FailedLogin] WITH (STATE = ON); GO之后可以在审计日志里看到每次登录失败的客户端IP。结合Windows防火墙日志或安全设备SIEM,就能把爆破源IP揪出来,加黑名单封禁。这一步在纯靠数据库层面保护的时代可能有点重,但今天的安全管理体系下,登录审计已经是基线要求了,建议宁可提前配置也不要等出了事再来补。
4.3 强化密码策略与锁定阈值
这里有一个经常被忽略的细节:ALTER LOGIN [sa] DISABLE只禁用账户,并不会修改sa的密码。如果哪天因为应急需要重新启用sa,它使用的还是之前那个弱密码,风险依然存在。所以在最终禁用之前,最稳妥的做法是先把sa密码改成一个高强度的随机密码,再执行禁用。这样即使未来被重新启用,攻击者也猜不到原密码。
改密码并启用策略:
ALTER LOGIN [sa] WITH PASSWORD = N'这里是高强度随机密码', CHECK_POLICY = ON, CHECK_EXPIRATION = OFF; GO ALTER LOGIN [sa] DISABLE; GO密码长度建议20位以上,包含大小写字母、数字、特殊字符。之前我见过有人改完密码之后把这段脚本直接放在共享文档里,这跟没改区别不大,密码一定要放到企业密码管理器里做权限控制。
关于账户锁定阈值,SQL Server本身没有独立的锁定时长设置,它依赖Windows组策略里的"账户锁定策略"。如果服务器在域环境里,SQL账号的密码策略由域策略统一控制,但自动锁定需要针对SQL Server账号单独确认。非域环境或独立服务器上,默认的锁定阈值选项往往是"不锁定",这种状态下即使被爆破也不会计数。建议在本地安全策略里设置"账户锁定阈值"为5次,"重置账户锁定计数器"为30分钟,这样即使sa被启用,也能触发锁定保护。注意这个策略对SQL Server登录名的生效条件是该登录启用了CHECK_POLICY = ON,所以前面那条ALTER LOGIN语句里这个参数必须保留。
4.4 清理数据库owner和固定服务器角色的多余成员
禁用sa后,很多数据库的owner如果还指向sa,日常运维里会遇到各种奇怪的问题,比如数据库属性打不开、某些功能不可用、ALTER AUTHORIZATION操作报错。更关键的是,如果owner是sa,它在数据库里的权限映射并不会因为sa被禁用而消失,只是在需要以owner身份执行上下文时会出现异常。稳妥的做法是提前把数据库owner迁移到应用账号或其他管理账号:
USE [YourDB]; GO EXEC sp_changedbowner 'app_erp'; GO或者使用ALTER AUTHORIZATION的方式:
ALTER AUTHORIZATION ON DATABASE::[YourDB] TO [app_erp]; GO这一条操作对每个数据库都要执行一遍,如果数据库多,可以写个动态SQL循环处理:
USE [master]; GO DECLARE @dbname sysname; DECLARE db_cursor CURSOR FOR SELECT name FROM sys.databases WHERE state = 0 AND name NOT IN ('master', 'tempdb', 'model', 'msdb'); OPEN db_cursor; FETCH NEXT FROM db_cursor INTO @dbname; WHILE @@FETCH_STATUS = 0 BEGIN DECLARE @sql nvarchar(max) = 'ALTER AUTHORIZATION ON DATABASE::[' + @dbname + '] TO [app_erp];'; EXEC sp_executesql @sql; FETCH NEXT FROM db_cursor INTO @dbname; END CLOSE db_cursor; DEALLOCATE db_cursor;固定服务器角色的成员也要做一次清查。重点检查sysadmin、securityadmin、serveradmin、setupadmin这几个高权限角色里有没有不认识的登录名,把多余的删除。
SELECT r.name AS role_name, m.name AS member_name FROM sys.server_role_members rm INNER JOIN sys.server_principals r ON rm.role_principal_id = r.principal_id INNER JOIN sys.server_principals m ON rm.member_principal_id = m.principal_id WHERE r.name IN ('sysadmin', 'securityadmin', 'serveradmin', 'setupadmin') ORDER BY r.name;原则上生产实例的sysadmin成员越少越好,每多一个成员就是多一个被攻击的入口。
5. 禁用sa后运维中真实会遇到的问题
5.1 应用连不上的排查顺序
禁用sa后最常见的告警就是应用突然报"无法登录",尤其在那些没有提前切换应用账号的环境里。如果遇到这种情况,先不要慌,按照下面这个顺序排查能把定位时间压到最短。
第一,确认连接字符串用的是不是sa。很多应用运维根本不知道代码里写的什么账号,需要开发配合查配置。这一步占80%的问题原因。
第二,确认是不是数据库实例名或端口写错了。如果应用连的是命名实例,禁用sa这个动作本身不会影响实例名,但如果你顺手改了端口,连接字符串里的端口没同步更新,也会报错,而且报错信息和账号被禁用的信息长得一摸一样。
第三,确认错误日志信息。用:
EXEC xp_readerrorlog 0, 1, N'Login failed', N'';看最新几个条目里的登录名是什么。如果显示Login failed for user 'sa',就是应用还在用sa;如果显示Login failed for user 'app_erp',那是应用账号密码或权限问题,再去查应用账号的状态和映射。
5.2 临时需要sa时的安全启用流程
有些老旧系统短期改不掉,或者某个安全评估场景需要临时开启sa排查问题。上线临时启用时需要遵守一个原则:"能不开就不开,必须开就开最短时间,用完立刻关"。
安全启用流程建议按这个步骤:
- 先在密码管理器里领取一个一次性的高强度sa密码。
- 执行启用:
ALTER LOGIN [sa] WITH PASSWORD = N'一次性高强度密码'; ALTER LOGIN [sa] ENABLE;- 作业、脚本或人工操作完成,立刻重新禁用:
ALTER LOGIN [sa] DISABLE;- 刷新密码管理器里的一次性密码,防止泄漏后被继续使用。
我见过有人临时启用之后忘了禁用,结果下个月安全检查发现sa又是启用状态,而且密码还是一个月前那个神秘密码。强烈建议在SQL Agent里建一个"哨兵作业",每天自动检查sa的is_disabled状态,如果发现被启用就告警,有条件甚至可以写作业自动重新禁用:
IF EXISTS ( SELECT 1 FROM sys.sql_logins WHERE name = 'sa' AND is_disabled = 0 ) BEGIN ALTER LOGIN [sa] DISABLE; RAISERROR('sa account was enabled and has been auto-disabled', 16, 1); END这个作业一天跑几次,能有效防止人为疏漏。
5.3 别忽视其他超级权限账号
禁用sa后有一类账号特别容易被漏掉:那些名字不起眼、但实际拥有sysadmin权限的应用账号或历史遗留账号。比如曾经为了某个集成需求创建的通用SQL账号,密码早就写在N个人电脑的txt文件里;再比如从SQL Server 2000时代迁移过来的老账号,权限一直没有清理。这些账号的权限与sa等价,攻击者一旦通过它们打进内部,禁用sa的成果就形同虚设。
建议定期做一次账号权限全量审计,输出所有登录名、权限角色、启用状态,对照业务确认每个账号的负责人和使用场景。
SELECT sp.name AS login_name, sp.type_desc, sp.is_disabled, r.name AS server_role FROM sys.server_principals sp LEFT JOIN sys.server_role_members rm ON sp.principal_id = rm.member_principal_id LEFT JOIN sys.server_principals r ON rm.role_principal_id = r.principal_id WHERE sp.type IN ('S', 'U', 'G') ORDER BY sp.name;对不确定用途的账号,遵循"先停用观察,再删除清理"的原则,先ALTER LOGIN [xxx] DISABLE,观察一个业务周期没有异常反馈再DROP LOGIN。
5.4 给数据库课程设计和大作业场景的一个提醒
很多学生在做数据库课程设计或毕业设计时,SQL Server是直接装在本地电脑上的,习惯性用sa加简单密码连接,甚至写完代码直接把sa密码提交到Git仓库。如果只是学习环境,可能觉得无关紧要,但一旦项目里用了真实数据,或者电脑连了校园网,sa弱口令的风险同样存在。个人开发环境建议也养成"禁用一个、新建专用登录"的习惯,哪怕只是本地练习,这个习惯能帮你避掉日后工作里因为权限滥用导致的安全事故。
我自己从第一台SQL Server服务器上线那天起,就把sa禁用写进了标准部署脚本。这几年下来,错误日志里几乎再也看不到针对sa的爆破记录了,该连接的应用也早就换成了专用权限的账号。禁用sa这件事,本质上不是把一个账号关掉那么简单,而是倒逼整个数据库实例的账号体系从"默认+超级权限"走向"最小权限+专人专用",这个转变无论对单台服务器还是整个企业的数据库资产来说,都是最值得做的一笔安全投资。最后提醒一句,如果你所在的环境还依赖混合模式认证,禁用sa之前务必保证应用账号、作业、链接服务器这些依赖项都切换完毕,否则断连只是时间问题。