一、说明
本篇文章主要说一说oracle数据库中身份鉴别控制点中测评项a的相关内容和理解,关于身份鉴别的基础知识点在《等保测评2.0:Oracle身份鉴别(上)》中,请大家先阅读它。
二、测评项a
a)应对登录的用户进行身份标识和鉴别,身份标识具有唯一性,身份鉴别信息具有复杂度要求并定期更换;
三、测评项a要求1
应对登录的用户进行身份标识和鉴别
oracle使用用户名对登录用户进行身份标识,这没啥好说的。oracle在身份鉴别这一块,拥有密码文件验证和操作系统验证两种方式。
密码文件验证的话,是需要登录用户输入用户名、口令的,但是操作系统验证则不需要。
对于数据库特殊账户的操作系统验证,仅由sqlnet.ora文件中的SQLNET.AUTHENTICATION_SERVICES进行控制,至于它有什么值以及代表什么意义,请大家去看上篇。
这里大家如果不想麻烦的话,其实也没有必要把SQLNET.AUTHENTICATION_SERVICES参数的值在linux和windows系统中代表的意义都搞清楚,测评的时候直接测试即可。
以centos系统为例子,也就是测评的时候先登录oracle数据库服务器的oracle账户,如果被测评方不清楚oracle账户的口令,也可以登录到root账户,然后使用“su – oracle”命令切换过去。
其实这里需要登录的是属于oinstall用户组的用户,但是一般情况下没人会去改默认配置,默认安装情况下操作系统的oracle用户会属于oinstall用户组。
登录oracle账户成功后,使用sqlplus / as sysdba命令去登录oracle数据库,这里就是使用数据库特殊账户的操作系统验证方式去验证。
如果能登录成功则说明开启了这种验证方式,不能则说明没开启。
如果开启了,那么这个要求项它就不能满足了,顶多是部分符合,因为这种方式登录数据库特殊账户不需要用户名、密码(虽然只能在本地登录,且登录的操作系统账户需要隶属于oinstall用户组),是一个比较大的安全隐患。
还有一种针对数据库普通账户的操作系统验证方式,这种验证方式对于登录的操作系统账户没有啥要求。
先去查看remote_os_authent和os_authent_prefix参数,它们的默认值分别是FALSE和ops$。
如果remote_os_authent是FALSE,那么是否开启这种验证方式还是由SQLNET.AUTHENTICATION_SERVICES决定。
如果开启了,假定os_authent_prefix的值是ops$,假定操作系统中存在一个cv的账户。
那么只要oracle数据库中建立一个名为ops$cv的账户并给与基础权限(连接权限等),用户在登录操作系统中的cv后,可以直接使用sqlplus /或sqlplus / as normal(两个命令是一个意思),以普通账户的身份登录ops$cv账户(当然这里需在cv账户的环境变量里配置一下好方便的使用sqlplus命令)。
同样的,如果开启了这种验证方式,那么也就顶多是部分符合了。
如果remote_os_authent为TRUE,那不用看了,数据库普通账户的操作系统验证方式肯定开启了,并且数据库普通账户的远程操作系统验证方式也开启了。
还是用上面的数据举例子,假定os_authent_prefix的值是ops$,假定远程终端存在一个cv的操作系统账户,那么在远程终端那也可以用空用户名、空口令的方式登录ops$cv账户,更不安全了。
至于空口令,在oracle中似乎不能设置空口令,我反正没有尝试成功……
四、测评项a要求2
身份标识具有唯一性
即用户名不会重复,oracle自动实现,默认符合。
五、测评项a要求3
身份鉴别信息具有复杂度要求
这个要从两个方面看,我个人觉得两个方面都符合才能算达到要求。
第一个方面即实际的口令是否具有一定的复杂度,也即口令至少8位,且包含大写字母、小写字母、数字、特殊字符这四类字符种的三种,且口令不包含简单排列规律,如admin!@#123此类弱口令。
第二个方面就是在oracle中是否设置了口令复杂度策略,这里要看的就是配置表中的PASSWORD_VERIFY_FUNCTION字段的值:
select * from dba_profiles;
这里插一句嘴,说一说配置表的规则,用户是可以自定义多个配置给不同的用户使用。
比如这里的PASSWORD_VERIFY_FUNCTION的Profile字段值为Default,某用户要使用Default的相关配置,就要设置DBA_USERS表中的Profile字段值为Default。
默认情况下,用户使用的都是Default:
select username,profile from DBA_USERS
好,咱们说一说PASSWORD_VERIFY_FUNCTION字段是什么意思,该字段的值应该为oracle中某函数对象的名字,当创建、更改用户口令时会调用到该函数对口令进行校验,默认情况下这里的值是null,也即不使用任何函数对口令进行校验。
在初级教材中,让我们去查看utlpwdmg.sql中的相关信息,其实是不准确的。
因为utlpwdmg.sql并不是函数本身,它只是创建函数的一段语句而已。
实际上在oracle11g中,运行utlpwdmg.sql会创建两个函数,一个是新版本的口令校验函数,一个是老版本的,在里面还会对配置表进行修改,让PASSWORD_VERIFY_FUNCTION的值为新版本的口令校验函数的名字。
这个是utlpwdmg.sql文件中新版本的口令校验函数FUNCTION verify_function_11G的定义语句:
CREATE OR REPLACE FUNCTION verify_function_11G
(username varchar2,
password varchar2,
old_password varchar2)
RETURN boolean IS
n boolean;
m integer;
differ integer;
isdigit boolean;
ischar boolean;
ispunct boolean;
db_name varchar2(40);
digitarray varchar2(20);
punctarray varchar2(25);
chararray varchar2(52);
i_char varchar2(10);
simple_password varchar2(10);
reverse_user varchar2(32);
BEGIN
digitarray:= '0123456789';
chararray:= 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
-- Check for the minimum length of the password
IF length(password) < 8 THEN
raise_application_error(-20001, 'Password length less than 8');
END IF;
-- Check if the password is same as the username or username(1-100)
IF NLS_LOWER(password) = NLS_LOWER(username) THEN
raise_application_error(-20002, 'Password same as or similar to user');
END IF;
FOR i IN 1..100 LOOP
i_char := to_char(i);
if NLS_LOWER(username)|| i_char = NLS_LOWER(password) THEN
raise_application_error(-20005, 'Password same as or similar to user name ');
END IF;
END LOOP;
-- Check if the password is same as the username reversed
FOR i in REVERSE 1..length(username) LOOP
reverse_user := reverse_user || substr(username, i, 1);
END LOOP;
IF NLS_LOWER(password) = NLS_LOWER(reverse_user) THEN
raise_application_error(-20003, 'Password same as username reversed');
END IF;
-- Check if the password is the same as server name and or servername(1-100)
select name into db_name from sys.v$database;
if NLS_LOWER(db_name) = NLS_LOWER(password) THEN
raise_application_error(-20004, 'Password same as or similar to server name');
END IF;
FOR i IN 1..100 LOOP
i_char := to_char(i);
if NLS_LOWER(db_name)|| i_char = NLS_LOWER(password) THEN
raise_application_error(-20005, 'Password same as or similar to server name ');
END IF;
END LOOP;
-- Check if the password is too simple. A dictionary of words may be
-- maintained and a check may be made so as not to allow the words
-- that are too simple for the password.
IF NLS_LOWER(password) IN ('welcome1', 'database1', 'account1', 'user1234', 'password1', 'oracle123', 'computer1', 'abcdefg1', 'change_on_install') THEN
raise_application_error(-20006, 'Password too simple');
END IF;
-- Check if the password is the same as oracle (1-100)
simple_password := 'oracle';
FOR i IN 1..100 LOOP
i_char := to_char(i);
if simple_password || i_char = NLS_LOWER(password) THEN
raise_application_error(-20007, 'Password too simple ');
END IF;
END LOOP;
-- Check if the password contains at least one letter, one digit
-- 1. Check for the digit
isdigit:=FALSE;
m := length(password);
FOR i IN 1..10 LOOP
FOR j IN 1..m LOOP
IF substr(password,j,1) = substr(digitarray,i,1) THEN
isdigit:=TRUE;
GOTO findchar;
END IF;
END LOOP;
END LOOP;
IF isdigit = FALSE THEN
raise_application_error(-20008, 'Password must contain at least one digit, one character');
END IF;
-- 2. Check for the character
<<findchar>>
ischar:=FALSE;
FOR i IN 1..length(chararray) LOOP
FOR j IN 1..m LOOP
IF substr(password,j,1) = substr(chararray,i,1) THEN
ischar:=TRUE;
GOTO endsearch;
END IF;
END LOOP;
END LOOP;
IF ischar = FALSE THEN
raise_application_error(-20009, 'Password must contain at least one \
digit, and one character');
END IF;
<<endsearch>>
-- Check if the password differs from the previous password by at least
-- 3 letters
IF old_password IS NOT NULL THEN
differ := length(old_password) - length(password);
differ := abs(differ);
IF differ < 3 THEN
IF length(password) < length(old_password) THEN
m := length(password);
ELSE
m := length(old_password);
END IF;
FOR i IN 1..m LOOP
IF substr(password,i,1) != substr(old_password,i,1) THEN
differ := differ + 1;
END IF;
END LOOP;
IF differ < 3 THEN
raise_application_error(-20011, 'Password should differ from the \
old password by at least 3 characters');
END IF;
END IF;
END IF;
-- Everything is fine; return TRUE ;
RETURN(TRUE);
END;
/
然后在这里,对配置文件进行了修改,设置PASSWORD_VERIFY_FUNCTION的值为verify_function_11G:
-- This script alters the default parameters for Password Management
-- This means that all the users on the system have Password Management
-- enabled and set to the following values unless another profile is
-- created with parameter values set to different value or UNLIMITED
-- is created and assigned to the user.
ALTER PROFILE DEFAULT LIMIT
PASSWORD_LIFE_TIME 180
PASSWORD_GRACE_TIME 7
PASSWORD_REUSE_TIME UNLIMITED
PASSWORD_REUSE_MAX UNLIMITED
FAILED_LOGIN_ATTEMPTS 10
PASSWORD_LOCK_TIME 1
PASSWORD_VERIFY_FUNCTION verify_function_11G;
这个是老版本的校验函数FUNCTION verify_function
的定义语句:
-- Below is the older version of the script
-- This script sets the default password resource parameters
-- This script needs to be run to enable the password features.
-- However the default resource parameters can be changed based
-- on the need.
-- A default password complexity function is also provided.
-- This function makes the minimum complexity checks like
-- the minimum length of the password, password not same as the
-- username, etc. The user may enhance this function according to
-- the need.
-- This function must be created in SYS schema.
-- connect sys/<password> as sysdba before running the script
CREATE OR REPLACE FUNCTION verify_function
(username varchar2,
password varchar2,
old_password varchar2)
RETURN boolean IS
n boolean;
m integer;
differ integer;
isdigit boolean;
ischar boolean;
ispunct boolean;
digitarray varchar2(20);
punctarray varchar2(25);
chararray varchar2(52);
BEGIN
digitarray:= '0123456789';
chararray:= 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
punctarray:='!"#$%&()``*+,-/:;<=>?_';
-- Check if the password is same as the username
IF NLS_LOWER(password) = NLS_LOWER(username) THEN
raise_application_error(-20001, 'Password same as or similar to user');
END IF;
-- Check for the minimum length of the password
IF length(password) < 4 THEN
raise_application_error(-20002, 'Password length less than 4');
END IF;
-- Check if the password is too simple. A dictionary of words may be
-- maintained and a check may be made so as not to allow the words
-- that are too simple for the password.
IF NLS_LOWER(password) IN ('welcome', 'database', 'account', 'user', 'password', 'oracle', 'computer', 'abcd') THEN
raise_application_error(-20002, 'Password too simple');
END IF;
-- Check if the password contains at least one letter, one digit and one
-- punctuation mark.
-- 1. Check for the digit
isdigit:=FALSE;
m := length(password);
FOR i IN 1..10 LOOP
FOR j IN 1..m LOOP
IF substr(password,j,1) = substr(digitarray,i,1) THEN
isdigit:=TRUE;
GOTO findchar;
END IF;
END LOOP;
END LOOP;
IF isdigit = FALSE THEN
raise_application_error(-20003, 'Password should contain at least one digit, one character and one punctuation');
END IF;
-- 2. Check for the character
<<findchar>>
ischar:=FALSE;
FOR i IN 1..length(chararray) LOOP
FOR j IN 1..m LOOP
IF substr(password,j,1) = substr(chararray,i,1) THEN
ischar:=TRUE;
GOTO findpunct;
END IF;
END LOOP;
END LOOP;
IF ischar = FALSE THEN
raise_application_error(-20003, 'Password should contain at least one \
digit, one character and one punctuation');
END IF;
-- 3. Check for the punctuation
<<findpunct>>
ispunct:=FALSE;
FOR i IN 1..length(punctarray) LOOP
FOR j IN 1..m LOOP
IF substr(password,j,1) = substr(punctarray,i,1) THEN
ispunct:=TRUE;
GOTO endsearch;
END IF;
END LOOP;
END LOOP;
IF ispunct = FALSE THEN
raise_application_error(-20003, 'Password should contain at least one \
digit, one character and one punctuation');
END IF;
<<endsearch>>
-- Check if the password differs from the previous password by at least
-- 3 letters
IF old_password IS NOT NULL THEN
differ := length(old_password) - length(password);
IF abs(differ) < 3 THEN
IF length(password) < length(old_password) THEN
m := length(password);
ELSE
m := length(old_password);
END IF;
differ := abs(differ);
FOR i IN 1..m LOOP
IF substr(password,i,1) != substr(old_password,i,1) THEN
differ := differ + 1;
END IF;
END LOOP;
IF differ < 3 THEN
raise_application_error(-20004, 'Password should differ by at \
least 3 characters');
END IF;
END IF;
END IF;
-- Everything is fine; return TRUE ;
RETURN(TRUE);
END;
/
所以,实际上想要知道现在实际使用的校验函数的内容,就应该直接在数据库中查看校验函数的内容,而不是去查看utlpwdmg.sql文件。
在这里,使用的是verify_function_11G,由于其内容我没有修改过,所以和utlpwdmg.sql中所定义的是一样的:
至于其中的内容嘛,注释写得很清楚的,我就从上到下大概说明下:
检查口令的最小长度,如果小于8就返回错误,所以口令的最小长度是9
-- Check for the minimum length of the password
IF length(password) < 8 THEN
raise_application_error(-20001, 'Password length less than 8');
END IF;
检查被创建或被更改口令的账户的用户名是否和新的口令一样,如果一样返回错误
检查新的口令是是否等于用户名后面加上1到100的数字,比如用户名时user,那么口令如果是user0到user100中的任何一个,也会返回错误。
-- Check if the password is same as the username or username(1-100)
IF NLS_LOWER(password) = NLS_LOWER(username) THEN
raise_application_error(-20002, 'Password same as or similar to user');
END IF;
FOR i IN 1..100 LOOP
i_char := to_char(i);
if NLS_LOWER(username)|| i_char = NLS_LOWER(password) THEN
raise_application_error(-20005, 'Password same as or similar to user name ');
END IF;
END LOOP;
这里是检查口令是否等于倒序的用户名,或者与其相似,比如用户名是user,则口令不能是r、re、res、resu中的任何一个
-- Check if the password is same as the username reversed
FOR i in REVERSE 1..length(username) LOOP
reverse_user := reverse_user || substr(username, i, 1);
END LOOP;
IF NLS_LOWER(password) = NLS_LOWER(reverse_user) THEN
raise_application_error(-20003, 'Password same as username reversed');
END IF;
这里检查口令是否和数据库名相等,以及是否和数据库名0到数据库名100相等。
我这里是默认的数据库名:ORCL
-- Check if the password is the same as server name and or servername(1-100)
select name into db_name from sys.v$database;
if NLS_LOWER(db_name) = NLS_LOWER(password) THEN
raise_application_error(-20004, 'Password same as or similar to server name');
END IF;
FOR i IN 1..100 LOOP
i_char := to_char(i);
if NLS_LOWER(db_name)|| i_char = NLS_LOWER(password) THEN
raise_application_error(-20005, 'Password same as or similar to server name ');
END IF;
END LOOP;
检查口令是否是一些简单的单词,只不过这里只是一个示例而已,用户可以根据需要多添加一些弱口令。
-- Check if the password is too simple. A dictionary of words may be
-- maintained and a check may be made so as not to allow the words
-- that are too simple for the password.
IF NLS_LOWER(password) IN ('welcome1', 'database1', 'account1', 'user1234', 'password1', 'oracle123', 'computer1', 'abcdefg1', 'change_on_install') THEN
raise_application_error(-20006, 'Password too simple');
END IF;
检查口令是否是oracle1到oracle100中的一个,不过这里口令可以等于oracle,不知道为啥这里是否等于oracle的校验
-- Check if the password is the same as oracle (1-100)
simple_password := 'oracle';
FOR i IN 1..100 LOOP
i_char := to_char(i);
if simple_password || i_char = NLS_LOWER(password) THEN
raise_application_error(-20007, 'Password too simple ');
END IF;
END LOOP;
检查口令是否包含至少一个数字和一个字母(同时包含才可以通过校验)
由于这里字母数组的定义是:chararray:= ‘abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’;
所以指的是至少一个大写或小写字母。
-- Check if the password contains at least one letter, one digit
-- 1. Check for the digit
isdigit:=FALSE;
m := length(password);
FOR i IN 1..10 LOOP
FOR j IN 1..m LOOP
IF substr(password,j,1) = substr(digitarray,i,1) THEN
isdigit:=TRUE;
GOTO findchar;
END IF;
END LOOP;
END LOOP;
IF isdigit = FALSE THEN
raise_application_error(-20008, 'Password must contain at least one digit, one character');
END IF;
-- 2. Check for the character
<<findchar>>
ischar:=FALSE;
FOR i IN 1..length(chararray) LOOP
FOR j IN 1..m LOOP
IF substr(password,j,1) = substr(chararray,i,1) THEN
ischar:=TRUE;
GOTO endsearch;
END IF;
END LOOP;
END LOOP;
IF ischar = FALSE THEN
raise_application_error(-20009, 'Password must contain at least one \
digit, and one character');
END IF;
检查口令和旧口令的相似程度:
假设新口令是user,旧口令是admin
新口令长度和旧口令长度的差值大于等于3的话,直接通过校验。
这里的差值是1,所以需要进行校验。
循环的次数为长度小的那一边的口令的长度,也就是user字符串的长度4。
顺序取字符串来对比:
u不等于a,differ的值加1,为1
s不等于d,differ加1,为2
最后循环4次结束,differ为4,
如果最后differ小于3,则未通过校验,大于等3,则通过校验。
-- Check if the password differs from the previous password by at least
-- 3 letters
IF old_password IS NOT NULL THEN
differ := length(old_password) - length(password);
differ := abs(differ);
IF differ < 3 THEN
IF length(password) < length(old_password) THEN
m := length(password);
ELSE
m := length(old_password);
END IF;
FOR i IN 1..m LOOP
IF substr(password,i,1) != substr(old_password,i,1) THEN
differ := differ + 1;
END IF;
END LOOP;
IF differ < 3 THEN
raise_application_error(-20011, 'Password should differ from the \
old password by at least 3 characters');
END IF;
END IF;
END IF;
最后,如果通过了所有的校验(中途没有返回错误),就直接返回true:
-- Everything is fine; return TRUE ;
RETURN(TRUE);
从整个默认的新版的校验函数看来,主要就是口令长度不低于9位,需要同时包含数字、字母(大小写皆可),感觉稍微差了那么一点。
理论上比较好的应该是口令长度不低于8位(这里是9位当然更好了),同时包含数字、大写字母、小写字母、特殊字符其中的3种字符。
另外,不知道为什么,SYS账户的口令的更改,不受到这个校验函数的限制。
登录SYS按道理来说使用的是密码文件或操作系统的验证,所以不知道在USER$中SYS账户的PASSWORD字段的值有什么用,虽然也会跟着口令的更改而更改就是了。
六、测评项a要求4
并定期更换
一方面查看实际的更换时间:
select name,PTIME from USER$
另一方面查看相关的策略,先看和口令过期直接相关的两个参数:
PASSWORD_LIFE_TIME和PASSWORD_GRACE_TIME
这里的时间单位是天,我这里自己修改过,默认情况下PASSWORD_LIFE_TIME的值是180,PASSWORD_GRACE_TIME的值是7。
PASSWORD_LIFE_TIME代表口令过期时间,而PASSWORD_GRACE_TIME则代表口令过期后的宽恕时间。
口令过期但还未超过宽恕期时,登录时会提醒你口令在多久后过期(这里的过期是指超过宽恕期),询问你是否修改口令,可以不修改,然后正常登录账户。
但是超过宽恕期再登录,就无法登录上去了。
oracle在这里的逻辑是这样的,需要通过用户的登录来改变用户的状态。
举个例子,假如PASSWORD_LIFE_TIME的值是1,PASSWORD_GRACE_TIME的值是也是1。
我在2020年4月7日10点整,创建了一个账户,在DBA_USERS表中,该账户的CREATED(创建时间)就是2020年4月7日10点,ACCOUNT_STATUS(账户状态)是OPEN,在USER$表中该账户的PTIME(口令修改时间)也是2020年4月7日10点整。
在DBA_USERS表中,该账户的EXPIRY_DATE是PTIME+PASSWORD_LIFE_TIME的值,也就是2020年4月8日10点整。
(注意,在USER$表中也有一个EXPTIME字段,但是好像这个字段有时候不是实时的,需要用户的登录才会更新,比如现在,该字段就是一个空字符串)
那么,在到达2020年4月8日10点整后,这个账户的ACCOUNT_STATUS是不会自动变成EXPIRED(GRACE)(口令过期但还处于宽恕期内),只要你不登录这个账户,那么该账户会一直处于OPEN状态。哪怕是过了两天,也就是超过PASSWORD_LIFE_TIME+PASSWORD_GRACE_TIME的值,仍然是OPEN状态。
在2020年4月8日10点整后,登录该账户,会更新账户的ACCOUNT_STATUS,更新成EXPIRED(GRACE),而EXPIRY_DATE也会更新,更新为登录时间点+PASSWORD_GRACE_TIME的值。
同样的,如果在这之后一直不登录账户,则超过宽恕期后,账户的状态还是EXPIRED(GRACE),只有等你尝试登录这个账户时,才会更新状态值为EXPIRED,当然这个时候你也登录不上了。
所以根据账户状态值不同,EXPIRY_DATE代表的意思有所不同,状态值为OPEN,则代表过期时间是什么时间。状态值为EXPIRED(GRACE),则代表宽恕期结束是什么时间。
另外,更新PASSWORD_LIFE_TIME值,也会实时的更新账户的EXPIRY_DATE值,但是仅对处于OPEN状态的账户有效。
如某账户为OPEN状态,其EXPIRY_DATE值为2020年4月8日10点,此时将PASSWORD_LIFE_TIME更改为2,则EXPIRY_DATE值就变成2020年4月9日10点了。
但是如果该账户是处于EXPIRED(GRACE)状态,修改PASSWORD_LIFE_TIME或PASSWORD_GRACE_TIME对它都是没用的。
不知道为什么,SYS账户不受到口令过期的限制,我测试的时候确实是这样。
可能是因为它属于特殊账户?毕竟判断是否过期也要去先读取数据库,而SYS账户可以在数据库未开启的时候连接它。
与口令过期间接相关的两个参数:PASSWORD_REUSE_TIME和PASSWORD_REUSE_MAX
PASSWORD_REUSE_TIME:指定了口令在多少天内不能重用,单位为1天。
PASSWORD_REUSE_MAX:指定了当前口令在被重用之前需要更改几次。
这里的重用是针对每个账户的自己的口令,如果不设置这两个参数,设置账户新口令的时候就可以使用当前的口令,那么口令过期就不存在意义了。
这里光看说明是看是不太容易理解的,试一试就明白了:
在PASSWORD_REUSE_TIME、PASSWORD_REUSE_MAX均为默认值UNLIMITED的时候,修改口令的时候可以随意重用,用当前的口令当新口令也都可以。
这里会突然想到verify_function_11G,如果新口令和旧口令一样的话,应该通不过校验的才对。
经过实验,不知道是为什么old_password是空字符串,压根就没有传值进来,所以实际上直接跳过了旧口令和新口令的对比校验……
当PASSWORD_REUSE_TIME、PASSWORD_REUSE_MAX均非默认值UNLIMITED的时候,则需要两个条件都满足才可以更改口令。
如PASSWORD_REUSE_TIME从UNLIMITED变成1,以及PASSWORD_REUSE_MAX从UNLIMITED变成1开始,oracle开始记录使用过的口令。
如某账户,这个时候依次设置新口令a、b、c、d、e,此时的口令是e,在1天内,该账户设置新口令的话,使用a、b、c、d、e中的任何一个都不可以。
超过1天后,a、b、c、d均可作为新口令,但是e不可以,因为PASSWORD_REUSE_MAX的值是1,相当于从e往前数,有1个口令不能被当做新口令,那就是e自己了。如果PASSWORD_REUSE_MAX的值是2,那么e、d均不可以作为新口令。
而如果PASSWORD_REUSE_TIME为unlimited、PASSWORD_REUSE_MAX为某个数值,或者PASSWORD_REUSE_TIME为某个数值,PASSWORD_REUSE_MAX为unlimited的时候,账户使用的口令都不能当做新口令进行设置。
所以为了满足定期更换的要求,PASSWORD_REUSE_TIME、PASSWORD_REUSE_MAX都应该设置为非unlimited的值。
最后,不知道为什么,SYS账户也不受到这两个参数的限制,可以随意重用口令。
*本文作者:起于凡而非于凡,转载请注明来自FreeBuf.COM
来源:freebuf.com 2020-05-03 09:00:35 by: 起于凡而非于凡
请登录后发表评论
注册