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数据库密码存储和验证过程4

服务器调用oracommon库中的函数kzsrdep(),利用密钥密码对AUTH_PASSWORD进行解密,这个时候服务器就拥有了明文密码的一个副本,然后服务器创建密码的散列值并将它与数据库中的散列值进行比较,如果匹配成功,那么用户就完成了整个身份验证。清楚这里面的原理就可以按照Oracle的思路在网络上嗅探到AUTH_SESSKEY和AUTH_PASSWORD,然后利用暴力破解破解出散列值,最终利用散列值AUTH_SESSKEY获得密码。

对于Oracle数据库来说,默认的用户要经常的进行修改密码,或者要定期的升级数据库的版本,并且对一些可能泄漏数据的配置文件进行加密,防止泄漏一些数据。从多方面进行着手,来防止攻击者对Oracle数据库的攻击导致密码的泄漏。