DBA账户是Oracle数据库中权限最高的一类账户,包括sys、system以及拥有DBA角色的业务管理账户。这类账户一旦密码长期不更换,或者多个环境共用同一个密码,风险会不断累积。安全审计和等保合规要求中,几乎都会明确提到特权账户密码必须定期轮换,周期一般是90天或者更短。本文就来聊聊在Oracle数据库里怎么做DBA账户的密码轮换,既满足合规要求,又不影响业务正常运行。

一、先搞清楚要轮换哪些账户
很多DBA一提到密码轮换就只想到sys和system,其实这两者只是冰山一角。完整的特权账户梳理应该包括:sys、system默认账户,所有被授予DBA角色的账户,sysman、dbsnmp等Oracle自带的组件账户,以及通过操作系统认证可以直接连接的账户。可以通过下面的SQL把高权限账户全部查出来:
-- 查询所有拥有DBA角色的账户 SELECT grantee FROM dba_role_privs WHERE granted_role = 'DBA' ORDER BY grantee; -- 查看账户当前状态和锁定情况 SELECT username, account_status, profile, created FROM dba_users WHERE username IN ( SELECT grantee FROM dba_role_privs WHERE granted_role = 'DBA' );
除了数据库内部的账户,还要注意操作系统层面的认证。如果sqlnet.ora里配置了SQLNET.AUTHENTICATION_SERVICES=(NTS)或者操作系统用户属于dba组(Linux下),本地连接sqlplus / as sysdba是不需要密码的。这种情况下,光改数据库密码挡不住拥有操作系统权限的人,需要把OS层权限一并纳入管理范围。
另外,dbsnmp这类账户经常被DBA遗忘。如果使用了OEM(Oracle Enterprise Manager)监控,dbsnmp的密码改了但监控端配置没同步更新,监控立刻就会报账户锁定告警,这是轮换时最常见的翻车点之一。
二、用PROFILE建立密码策略
Oracle的密码管理是通过PROFILE实现的,很多数据库默认的DEFAULT profile对密码几乎没有任何约束。建议为DBA账户单独创建一个严格的PROFILE,示例配置如下:
-- 创建DBA专用profile CREATE PROFILE dba_secure LIMIT PASSWORD_LIFE_TIME 90 -- 密码90天过期 PASSWORD_GRACE_TIME 7 -- 过期后7天宽限期 PASSWORD_REUSE_TIME 365 -- 365天内不能重用旧密码 PASSWORD_REUSE_MAX 10 -- 至少要换10次才能重用 FAILED_LOGIN_ATTEMPTS 5 -- 连续失败5次锁定 PASSWORD_LOCK_TIME 1/24; -- 锁定1小时 -- 将profile应用到账户 ALTER USER sys PROFILE dba_secure; ALTER USER system PROFILE dba_secure;
配置完PROFILE后,还需要启用密码复杂度校验函数。Oracle提供了现成的utlpwdmg.sql脚本,位于$ORACLE_HOME/rdbms/admin/utlpwdmg.sql,执行后会在DEFAULT profile上挂载校验函数。如果只想对DBA profile生效,可以自己写一个校验函数:
CREATE OR REPLACE FUNCTION verify_dba_pwd(
username VARCHAR2, password VARCHAR2, old_password VARCHAR2
) RETURN BOOLEAN IS
BEGIN
-- 密码长度至少12位,且不能与用户名相同
IF length(password) < 12 THEN
RETURN FALSE;
END IF;
IF lower(password) = lower(username) THEN
RETURN FALSE;
END IF;
RETURN TRUE;
END;
/
ALTER PROFILE dba_secure LIMIT PASSWORD_VERIFY_FUNCTION verify_dba_pwd;
有一点要特别注意:给账户设置PASSWORD_LIFE_TIME后,如果账户原本密码已经用了很久,切换profile的瞬间就可能直接进入宽限期甚至过期状态。所以上线密码策略前,先统一改一次密码,让生命周期从新密码开始计算,避免策略一上线账户就批量过期。
三、轮换的具体操作与密码文件同步
改密码本身很简单,一条ALTER USER ... IDENTIFIED BY就搞定,但DBA账户轮换的难点在于联动。sys用户的密码不仅存在数据库里,还存在于密码文件中(Linux下路径一般是$ORACLE_HOME/dbs/orapw<SID>,Windows下在database目录)。用ALTER USER改了sys密码后,密码文件会自动同步更新,这一点Oracle 11g之后做得没问题。但如果直接用orapwd工具重建密码文件,就必须在所有节点执行,RAC环境下漏一个节点,重启时该节点就可能起不来。
手工轮换时建议用下面的方式生成随机密码并执行修改:
-- 生成随机密码(Linux下也可以用 openssl rand -base64 12)
SELECT UPPER(SUBSTR(RAWTOHEX(SYS_GUID()), 1, 8)) || '_'
|| LOWER(SUBSTR(RAWTOHEX(SYS_GUID()), 17, 6)) AS new_pwd FROM dual;
-- 执行修改(以system为例)
ALTER USER system IDENTIFIED BY "Xk29Fz8Q_Le4mA";
密码尽量用双引号包裹,这样可以包含特殊字符。改完之后要把新密码妥善保管到密码保险箱(比如Vault、Keeper这类工具),绝不能写在脚本明文里或者贴在运维文档中。审计时最常见的问题就是密码以明文形式散落在各种crontab脚本、shell脚本和Excel表格里,轮换做得再勤,泄露风险依然存在。
如果环境里账户多、周期短,手工轮换容易遗漏,可以考虑自动化方案。思路是写一个轮换脚本,从密码管理工具获取或生成新密码,调用sqlplus执行修改,然后将新密码回写到密码管理系统,最后验证登录。脚本示例:
#!/bin/bash
# 简化版轮换脚本,实际使用需配合密码管理工具
NEW_PWD=$(openssl rand -base64 12 | tr '/+' '_-')
sqlplus -S / as sysdba <<EOF
ALTER USER system IDENTIFIED BY "${NEW_PWD}";
EXIT;
EOF
if [ $? -eq 0 ]; then
echo "system|${NEW_PWD}" >> /secure/vault/pwd_record_$(date +%F).txt
chmod 600 /secure/vault/pwd_record_$(date +%F).txt
fi
更规范的做法是接入企业的特权访问管理平台(PAM),通过动态密码墙的方式,DBA平时根本不知道真实密码,登录时由平台代为注入,轮换完全在后台自动完成,这是目前大型企业主流的方案。
四、轮换时容易踩的坑
第一个坑是密码过期导致业务中断。有些应用直接用DBA账户连接数据库,密码过期后应用重启时连不上,业务就挂了。原则上应用账户和DBA账户必须分离,应用账户走单独的profile和轮换策略,改密码前要和开发团队确认变更窗口。
第二个坑是登录失败锁定被恶意触发。设置了FAILED_LOGIN_ATTEMPTS后,攻击者可以故意输错密码把账户锁死,形成变相拒绝服务。对于关键账户,可以设置合理的锁定时间,同时通过审计日志(dba_audit_session)监控失败登录来源,及时发现暴力破解行为。
第三个坑是宽限期的处理。PASSWORD_GRACE_TIME期间登录会收到ORA-28002警告,很多应用对告警不敏感,宽限期一过直接报ORA-28001密码过期。所以要把告警接入监控,在宽限期内主动完成轮换,而不是被动等过期。
最后,每次轮换后务必做验证:确认新密码能正常登录,确认相关组件(OEM监控、备份脚本、巡检脚本)工作正常,并保留完整的变更记录,包括轮换时间、执行人、验证结果,这些记录在安全审计时都是必查项。密码管理没有一劳永逸的方案,策略加流程加工具三者结合,才能真正把特权账户的风险管起来。
Oracle DBA密码轮换Oracle数据库安全密码策略修改时间:2026-09-13 03:52:33