> 数据库 > Oracle >

Oracle密码存储和验证过程剖析及防御建议

Oracle作为目前市场占有率第一的数据库产品,相比其他数据库产品,自身存在的漏洞数量也是同类产品之中最多的,而且还在增长。由此,我们可以预见,数据库安全问题也将长期存在。

谈到数据库安全问题,备受用户关注的有数据库密码安全,专业的说法是数据库身份验证过程安全。数据库密码是保护库内核心数据的关键,一旦数据库密码被窃取,会导致攻击者对数据库乃至整个网络更深入的入侵。

攻击者针对数据库的身份验证过程主要采取两种策略:一种是绕过数据库身份验证过程,一种是是攻破数据库身份验证过程。本文主要针对后者主动攻破方式进行探讨。安华金和数据库攻防实验室结合Oracle数据库的特点论述攻击Oracle身份验证过程的办法,以及针对这些攻击行为提出防御建议。

Oracle数据库身份验证绕过手段

利用Oracle的默认密码和Oracle密码特点破解密码

获取Oracle密码的暴力破解方法,除去通用的排列组、字典破解等方式外,Oracle 自身存在一些默认用户名密码,例如智能代理账户DBSNMP/DBSNMP。这是Oracle 中最可能被忘记修改的默认用户名和密码。造成这一现象的原因是智能代理的密码需要在两个不同的地方进行修改,首先要在数据库中对DBSNMP用户密码进行修改,其次需要在snmp_rw.ora这个文件中再次进行密码修改。

还有Oracle登陆包中会带有数据库密码位数的信息,这是由于数据库服务器和客户端之间加密协议造成的。在数据库的登录信息包中存在一个关键字段AUTH_PASSWORD,这个字段是客户端对密码进行加密后传出的,这个参数的长度和原密码的长度密切相关。我们以Oracle 11g为例这个AUTH_PASSWORD的长度是96位预示着密码明文的长度应该是16-30位之间(Oracle密码长度最大不超过30位)。

Oracle密码存储和验证过程剖析及防御建议

下图中AUTH_PASSWORD的长度是64位预示着密码明文的长度应该是1-15位之间。

Oracle密码存储和验证过程剖析及防御建议

这一特点不是11g版本独有的,oracle所有版本都有类似的特点。通过包中AUTH_PASSWORD位数确定密码的位数,此举将有效的降低暴力破解的成本。

从Oracle本地文件获取密码

虽然可以进行一定的优化,但暴力破解本质还是靠大量的访问链接进行测试。除了暴力破解外还存在着更为简便的获得密码的方法。假设已经可以访问数据库所在主机的文件系统,那么可以通过Oracle的一些本该删除的文件获得数据库密码信息。例如在数据库四大用户中SYSMAN的密码会以密文的形式被写入到文件中,但是同时也会把密钥写入到同一个文档中。例如C:\app\lsc\product\11.2.0\dbhome_1\sysman\config下的emoms.properties 中存储了 SYSMAN的密码和密钥。打开emoms.propeties

Oracle密码存储和验证过程剖析及防御建议

图中画红线的位置:

oracle.sysman.eml.mntr.emdRepPwd记录的是sysman的密码,oracle.sysman.eml.mntr.emdRepPwdSeed记录的是对应密码的密钥。

同时得到了密文与密钥用DES解密器可以获得密码原文

Oracle密码存储和验证过程剖析及防御建议

如果数据库管理中多个账号采用统一密码,就会导致直接外泄SYS/SYSTEM密码。

在Oracle主目录的cfgtoologs文件夹中还存在一些会暴露密码信息的文件。

利用Oracle加密原理破解密码

除了以上两种获取密码的方法外还有更加直接的办法,这种方法就是通过理解Oracle的密钥传输过程破解Oracle通讯协议中的密文。(下面以Oracle 9i为例说明这一方法,10、11原理类似,只是更加复杂)

首先拿一个Oracle登录包来说明整个过程。首先客户端给服务器发送SERVICE_NAME。

Oracle密码存储和验证过程剖析及防御建议

这一发送过程如果没有向Listener登记该服务,那么Listener会生成一个错误,则终止所有过程。如果成功则进入身份验证过程,首先客户端向服务器发送一个含有用户名的数据包,服务器判断用户名存在后从数据库中提取出该用户名的散列值,服务器使用这个散列值生成一个密码。

这个密码的生成过程是服务器调用orageneric库中的函数slgdt()过程。slgdt()函数是用来重新获得系统时间的,将分钟、小时、秒、毫秒结合起来形成一个用来加密的8个字节的“文本”。文本的前四位是由分钟和小时与用户名对应的散列的后四位进行异或运算得出,文本的后四位是由秒和毫秒与用户名对应的散列的前四位进行异或运算得出。

加密过程通过调用oracommon库中的函数kzsrenc(),使用该密钥对文本进行加密。通过使用函数lncgks(),函数kzsrenc()基本完成了DES密钥的生成,最后利用函数incecb()输出ecb模式下的DES密文,这里生成的密文就是密码。接着再次调用函数kzsrenc(),利用用户的密码散列值对该密码加密,这样调用的结果就是AUTH_SESSKEY然后发送给客户端。

Oracle密码存储和验证过程剖析及防御建议

收到AUTH_SESSKEY后,客户端将其重新解密并重新获得该密码。用户利用oracore库中的函数lncupw()创建自己密码散列值的一个副本,然后通过调用函数kzsrdec(),将该散列值用作对AUTH_SESSKEY进行解密的密钥。这一过程顺利完成后就会生成密码。

这个密码通过调用函数kzsrenp()作为密钥对其中的明文、大小写敏感字符进行加密。kzsrenp()函数完成了DES密钥的生成以及在CBC模式下用户密码的加密。接下来,密文以AUTH_PASSWORD的形式被送回服务器。

Oracle密码存储和验证过程剖析及防御建议

服务器调用oracommon库中的函数kzsrdep(),利用密钥密码对AUTH_PASSWORD进行解密,这个时候服务器就拥有了明文密码的一个副本,然后服务器创建密码的散列值并将它与数据库中的散列值进行比较,如果匹配成功,那么用户就完成了整个身份验证。

清楚这里面的原理就可以按照Oracle的思路在网络上嗅探到AUTH_SESSKEY和AUTH_PASSWORD,然后利用暴力破解破解出散列值,最终利用散列值解密AUTH_SESSKEY获得密码。

知道了攻击者获取数据库密码的办法,就可以有针对性的对其进行防御。从攻击方法上看,第一种方法主要是依赖默认口令或弱口令;第二种方法是配置文件泄漏;第三种方法是通过破解散列值获取。

根据安华金和攻防实验室专家多年经验以下3点有助于加固Oracle密码安全,解决攻击者对Oracle验证绕过的威胁。

Oracle身份认证加固建议

定期修改账户的密码

在数据库创建之后会存在一些默认用户,例如文中提到的智能代理账号DBSNMP。要定期对这些使用的账号进行修改密码。密钥要遵循Oracle的建议,并且理论上密码越复杂越有利于安全。

锁死一些不需要的用户,对系统文件进行加锁处理

例如文中的文件系统中暴露的是SYSMAN的密码,这个账号是用于管理EM的账号,如果你的环境不需要EM,请锁死这个账号,并对一些可能泄露密码的配置文件进行文件加锁,防止本地文件系统被入侵牵连到数据库。

提高数据库版本,使用非定值的散列值

10g之前的数据库由于固定用户名对应的散列值是固定的仅依靠时间函数做调整,这就给攻击者对数据库散列值做暴力破解带来了可能。建议升级数据库到11g版本,11g开始引入了AUTH_VFR_DATA这个随机值,并对AUTH_SESSKEY的生成做了更复杂的调整有利于防止密码通过泄露的传输信息被破译。

相信只要做到以上三点,就可以有效的防止攻击者获取数据库密码。

(责任编辑:IT)