Listener Password in Oracle 10g

在Google上搜索“监听 安全 oracle”,一堆《实例讲解Oracle监听口令及监听器安全》的文章,都是copy+paste自eygle的这篇《Oracle的监听口令及监听器安全》,eygle的测试环境是本地的10.2.0.3客户端加远程9.2.0.4数据库。

如果服务器端数据库版本在Oracle9i以后,设置监听密码的情况则有一些变化。

Metalink Note 260986.1中,可以看到:

In Oracle 10, the TNSListener is secure out of the box and there should not be a need to set a listener password as in older versions of the Oracle listener.

Oracle10g以后,设置Listener密码已经不是安全检查的必要条件了,因为默认在10g里面除了启动监听的用户之外,其它用户都无法停止Listener(还有另外一些lsnrctl的命令也同样被禁止了,比如trace, reload等),即使Listener没有设置密码。

在默认情况下,启动Listener或者使用lsnrctl status命令查看监听状态,可以看到:

Security                  ON: Password or Local OS Authentication

这表明Listener的安全机制使用了Password方式或者Local OS Authentication方式,在这种状态下,即使是设置了监听密码,对于启动监听的user来说,也仍然是不需要任何密码就可以停止监听的。

如果我们想去除自Oracle10g之后的这种新安全机制,那么需要在listener.ora文件中添加:

LOCAL_OS_AUTHENTICATION_[listener name] = OFF

重新启动Listener之后,将会只看到:

Security                  ON: Password

这就又回复到了Oracle9i时的状态,只要有密码存在,无论是谁尝试停止监听都会被要求set password。

D:\Temp>lsnrctl

LSNRCTL for 32-bit Windows: Version 11.1.0.7.0 - Production on 20-MAY-2009 11:15:41

Copyright (c) 1991, 2008, Oracle.  All rights reserved.

Welcome to LSNRCTL, type "help" for information.

LSNRCTL> status
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=kamus-laptop)(PORT=1521)))
TNS-01169: The listener has not recognized the password
LSNRCTL> stop
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=kamus-laptop)(PORT=1521)))
TNS-01169: The listener has not recognized the password
LSNRCTL> set password
Password:
The command completed successfully
LSNRCTL> status
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=kamus-laptop)(PORT=1521)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for 32-bit Windows: Version 11.1.0.7.0 - Production
Start Date                20-MAY-2009 11:14:22
Uptime                    0 days 0 hr. 1 min. 34 sec
Trace Level               off
Security                  ON: Password
SNMP                      OFF
Listener Parameter File   D:\oracle\product\11.1.0\db_1\network\admin\listener.ora
Listener Log File         d:\oracle\diag\tnslsnr\kamus-laptop\listener\alert\log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=kamus-laptop)(PORT=1521)))
Services Summary...
Service "orcl11g" has 1 instance(s).
  Instance "orcl11g", status READY, has 1 handler(s) for this service...
Service "orcl11g_XPT" has 1 instance(s).
  Instance "orcl11g", status READY, has 1 handler(s) for this service...
The command completed successfully
LSNRCTL> stop
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=kamus-laptop)(PORT=1521)))
The command completed successfully
LSNRCTL>

How to Prevent DBA User From Logining Database Without Password

我们知道如果某个操作系统用户属于dba组,那么登录了这个用户之后,不再需要任何密码就能以SYS用户登录到数据库中,在产品环境中,这无疑是一个严重的安全漏洞。

kamus@desktop:~$ whoami
kamus
kamus@desktop:~$ sqlplus / as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 17:56:58 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> show user
USER is "SYS"
SQL> exit
Disconnected
kamus@desktop:~$ sqlplus nouser/nopassword as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 17:37:42 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> show user
USER is "SYS"
SQL>  

正如上面的演示,我们轻松以SYS身份登录进了数据库,无须给任何用户名密码,甚至是随便给一个毫不存在的用户和密码也可以。

如何防止这样的问题?

首先,我们可以利用oracle自身提供的sqlnet.ora文件中的参数sqlnet.authentication_services。在$ORACLE_HOME/network/admin/sqlnet.ora文件中添加如下行:
sqlnet.authentication_services=(NONE)

再次尝试不提供用户密码登录sqlplus,将遇到ORA-01031错误。

kamus@desktop:~$ sqlplus / as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 18:05:07 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

ERROR:
ORA-01031: insufficient privileges


Enter user-name: ^C
kamus@desktop:~$ sqlplus sys/oracle as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 18:06:31 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> 

更进一步,我们还可以让dba组的其他用户必须通过监听程序来连接数据库,这样内置于监听中的审计和跟踪功能就能得到更好的使用。

先来看一下如果不通过监听连接数据库的情况。继续上面的例子,在我们通过用户名密码成功登录数据库实例以后,查看一下操作系统级别的进程。

kamus@desktop:~$ ps -ef|grep sqlplus
kamus     6556  5409  0 18:06 pts/0    00:00:00 sqlplus            as sysdba
kamus     6561  5601  0 18:11 pts/2    00:00:00 grep sqlplus
kamus@desktop:~$ ps -ef|grep 6556 | grep -v grep
kamus     6556  5409  0 18:06 pts/0    00:00:00 sqlplus            as sysdba
oracle    6557  6556  0 18:06 ?        00:00:00 oracleorcl11g (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))

pid为6556的进程是user process,对应其的server process的pid是6557,这就是oracle使用的双层架构(Two-Task Architecture),任何用户进程(user process)不会跟数据库内存或者数据文件直接交互,而是通过一个对应的服务端进程(server process)来完成工作的。

我们可以注意到,6556进程的属主是kamus,因为是这个用户执行的sqlplus命令,但是6557进程的属主却是oracle,这是为什么呢?这归功于setuid。查看一下oracle可执行文件的权限。

kamus@desktop:~$ cd $ORACLE_HOME/bin
kamus@desktop:/u01/app/oracle/product/11.1.0/bin$ ls -l oracle
-rwsr-s--x 1 oracle oinstall 144792107 2009-01-05 14:01 oracle

owner的权限是rws,最后的s位表明在该执行文件上启用了setuid,具体含义就是不管是那个用户执行了该文件,该文件总是以属主的身份运行。那么如果我们取消掉s位,会出现什么情况呢?

kamus@desktop:/u01/app/oracle/product/11.1.0/network/admin$ cd
kamus@desktop:~$ su - oracle
Password: 
[orcl11g]@desktop[/home/oracle]$cd $ORACLE_HOME/bin
[orcl11g]@desktop[/u01/app/oracle/product/11.1.0/bin]$chmod u-s oracle
[orcl11g]@desktop[/u01/app/oracle/product/11.1.0/bin]$ls -l oracle
-rwxr-s--x 1 oracle oinstall 144792107 2009-01-05 14:01 oracle

再次尝试在kamus用户下登录sqlplus。碰到了ORA-09925错误。

kamus@desktop:~$ sqlplus sys/oracle as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 18:26:16 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

ERROR:
ORA-09925: Unable to create audit trail file


Enter user-name: 

再检查一下后台进程。

kamus@desktop:~$ ps -ef|grep sqlplus|grep -v grep
kamus     6699  5601  0 18:26 pts/2    00:00:00 sqlplus            as sysdba
kamus@desktop:~$ ps -ef|grep 6699|grep -v grep
kamus     6699  5601  0 18:26 pts/2    00:00:00 sqlplus            as sysdba
kamus     6700  6699  0 18:26 ?        00:00:00 oracleorcl11g (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))

原因很清楚,当我们去掉了oracle可执行文件的s位以后,server process的属主成为了kamus,而不是之前的oracle。登录sqlplus需要记录一定的audit信息,这是由server process来完成的,但是因为现在属主是kamus,并没有权限在oracle软件的安装目录中写入任何信息,因此报ORA-09925错误。

更彻底一些,我们连server process都不允许在本地启动,去掉oracle可执行文件的其他用户执行权限,只保留属主的读写执行权限。

[orcl11g]@desktop[/u01/app/oracle/product/11.1.0/bin]$chmod 0700 oracle
[orcl11g]@desktop[/u01/app/oracle/product/11.1.0/bin]$ls -l oracle
-rwx------ 1 oracle oinstall 144792107 2009-01-05 14:01 oracle

再次尝试登录sqlplus,这次碰到了ORA-12546错误。

kamus@desktop:~$ sqlplus sys/oracle as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 18:44:14 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

ERROR:
ORA-12546: TNS:permission denied


Enter user-name: 

检查后台进程,可以看到根本就没有启动成功的server process。

kamus@desktop:~$ ps -ef|grep sqlplus|grep -v grep
kamus     6916  5601  0 18:44 pts/2    00:00:00 sqlplus            as sysdba
kamus     6917  6916  0 18:44 ?        00:00:00 [sqlplus] 

在这种设置下,必须要通过监听才可以登录数据库。

首先,使用oracle用户登陆,启动数据库。取消掉oracle可执行文件的s位后,必须要登陆到该文件的属主用户下,才可以启动数据库。

[orcl11g]@desktop[/home/oracle]$sqlplus sys/oracle as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 18:56:23 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> startup
ORACLE instance started.

Total System Global Area  238530560 bytes
Fixed Size                  1299116 bytes
Variable Size             100666708 bytes
Database Buffers          134217728 bytes
Redo Buffers                2347008 bytes
Database mounted.
Database opened.
SQL> 

然后再登陆kamus用户,尝试登陆sqlplus。orcl11g是在tnsnames.ora文件中已经设置过的连接字串。

[orcl11g]@desktop[/home/kamus]$sqlplus sys/oracle@orcl11g as sysdba

SQL*Plus: Release 11.1.0.6.0 - Production on Sun Apr 5 18:57:16 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
With the Partitioning and Real Application Testing options

SQL> 

通过监听,可以正常连接数据库了。再检查一下后台进程的情况。

[orcl11g]@desktop[/home/kamus]$ps -ef|grep sqlplus|grep -v grep
oracle    7077  6966  0 18:56 pts/3    00:00:00 sqlplus            as sysdba
kamus     7156  7008  0 18:57 pts/5    00:00:00 sqlplus                    as sysdba
[orcl11g]@desktop[/home/kamus]$ps -ef|grep LOCAL|grep -v grep
oracle    7118  7077  1 18:56 ?        00:00:02 oracleorcl11g (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
oracle    7172     1  0 18:57 ?        00:00:00 oracleorcl11g (LOCAL=NO) 

7077进程是我们使用oracle用户打开的sqlplus连接,对应的server process是7118,7156进程则是使用kamus用户打开的sqlplus连接,可以看到并没有父进程是7156的server process,只有一个7172的进程,它的父进程号是1。

[orcl11g]@desktop[/home/kamus]$ps -fp 1
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 17:10 ?        00:00:01 /sbin/init 

1是初始化进程,父进程为1代表这个进程是被fork出来的,这就是通过监听连接数据库的机制,user process联系监听,监听再fork一个server process用以应对客户端的请求。

至此,我们已经完成了对于数据库连接的基本安全性设置。

结论:通过下面的两种方法来完成数据库连接的安全保障。
1. 在sqlnet.ora文件中添加sqlnet.authentication_services=(NONE),用以保证必须要给出SYS用户密码才能登陆。
2. 设置oracle可执行文件的运行权限为0700,用以保证非oracle软件的属主必须要通过监听才可以连接数据库。

安全,并不仅仅是局限于数据库本身的,在本文的安全性设置中,它牵涉到数据库运行的机制以及操作系统的部分知识,当你的知识越全面,你就能想到越多的方法来完善整个系统的安全。当然,安全性的建设也远远不局限于技术层面,规章制度、人员素质、完善的审计流程都具有决定性的影响。

User Default Password Check in Oracle 11g

在数据库安全性检查中有一项首先要完成的工作,就是检查数据库中的用户密码是否还仍然保留着默认值,比如sys的密码是否还是change_on_install,system的密码是否还是manager,scott的密码是否还是tiger。

在Oracle 11g之前,我们需要手工来完成这样的工作,大概步骤是:
1. 创建一张自定义的表,保存下常用的系统用户以及默认密码的HASH值。
2. 将系统中的用户密码HASH值与该表中的HASH值比较,如果相同,则表明还在使用默认值。

注意:在数据字典中存储的密码是被HASH算法加密过的,加密后的值不但跟密码本身有关还跟用户名有关,也就是,如果是不相同的用户名那么即使是完全相同的密码,加密后的HASH值也是不一样的。这样保证了每一个用户的每一个密码都有自己独一无二的HASH值。

在Oracle 11g之前,加密后的密码可以从DBA_USERS数据字典的PASSWORD字段中获得,因此可以通过这个字段中存储的值来做是否是默认值的检查。但是在11g中,PASSWORD字段却不再显示密码的内容了。

先看一下文档中对这个字段的描述:

Indicates whether the user is authenticated by OID (GLOBAL) or externally authenticated (EXTERNAL); NULL otherwise

SQL> select username,decode(password,null,'NULL',password) password from dba_users;
 
USERNAME                       PASSWORD
------------------------------ ------------------------------
MGMT_VIEW                      NULL
SYS                            NULL
SYSTEM                         NULL
DBSNMP                         NULL
SNPM                           NULL
SYSMAN                         NULL
SNPW                           NULL
SCOTT                          NULL
KAMUS                          NULL
OUTLN                          NULL
WMSYS                          NULL
DIP                            NULL
ORACLE_OCM                     NULL
TSMSYS                         NULL
 
14 rows selected

可以看到PASSWORD字段已经不再显示密码内容,全部都为空。

那么,如果再去检查这些用户是否还在使用默认的密码呢?

方法一:从SYS.USER$基表中检查,在基表的password字段中仍然可以查到HASH后的值。

SQL>  select name,password from user$ where name='SCOTT';

NAME                           PASSWORD
------------------------------ ------------------------------
SCOTT                          F894844C34402B67

方法二:这是推荐的方法,最简单的方法,11g中可以使用的方法,11g提供了新的DBA_USERS_WITH_DEFPWD视图,该视图中包含了所有还在使用默认密码的用户名。

SQL> alter user scott identified by tiger;

User altered.

SQL> select * from DBA_USERS_WITH_DEFPWD where username='SCOTT';

USERNAME
------------------------------
SCOTT

SQL> alter user scott identified by tiger1;

User altered.

SQL> select * from DBA_USERS_WITH_DEFPWD where username='SCOTT';

no rows selected

Oracle对于安全性的支持力求做到业界领先,Oracle始终在每个细节上进步着。