/* ______________________________________________________________________________ Subject: Oracle 11g TNS AES-192 authentication details Authors: Massimiliano Montoro Issue date: November, 12, 2008 ______________________________________________________________________________ This code shows the encryption algorithm used by Oracle 11g TNS protocol authentication. Test authentication parameters captured from the network follows: USERNAME: SYSTEM (not used anymore as the password salt in Oracle 11g) PASSWORD: password AUTH_SESSKEY: B04AD02A39D98CE07F81C38B5D9CE3488B96D708C75272AFA87E481704524A88396A07F56351BAF3427F171B9AF2B64B AUTH_SESSKEY_CLIENT: 1C767091FC21BFA278AC0A11FDD49A7E28CBE2BFED97B8EE41E19A996464CFAB25B5D5DF8D495E78B58773A0A5EF3972 AUTH_PASSWORD: D89FD9EC07BA6F8CE76D245096C7200314A909AA181C082BF0A8DA16536516F2 AUTH_VFR_DATA: 0304C89CDE53769640A5 (the new password salt to be used for case sensitive passwords) The following code will show the AES-192 encryption algorithm to be used in order to check the correctness of the password "password" associated to the Oracle username "SYSTEM". NOTE: The following code does not use native functions of "oran11.dll" but the algorithm has been adapted to work with OpenSSL software. The code could be incomplete but correct enough to prove the concept. ______________________________________________________________________________ The information in this document are provided "AS IS" without warranty of any kind. In no event shall the authors be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages due to the misuse of any information provided in this document and in the use of the software compiled from the following code. ______________________________________________________________________________ */ // filename: oracle_tns_aes192_check.cpp #include "windows.h" #include "stdio.h" #include #include #include //********************************************************************************************************************* // Hashes captured on the network during authentication phase unsigned char AUTH_SESSKEY [] = { 0xB0,0x4A,0xD0,0x2A,0x39,0xD9,0x8C,0xE0,0x7F,0x81,0xC3,0x8B,0x5D,0x9C,0xE3,0x48, 0x8B,0x96,0xD7,0x08,0xC7,0x52,0x72,0xAF,0xA8,0x7E,0x48,0x17,0x04,0x52,0x4A,0x88, 0x39,0x6A,0x07,0xF5,0x63,0x51,0xBA,0xF3,0x42,0x7F,0x17,0x1B,0x9A,0xF2,0xB6,0x4B }; unsigned char AUTH_SESSKEY_C[] = { 0x1C,0x76,0x70,0x91,0xFC,0x21,0xBF,0xA2,0x78,0xAC,0x0A,0x11,0xFD,0xD4,0x9A,0x7E, 0x28,0xCB,0xE2,0xBF,0xED,0x97,0xB8,0xEE,0x41,0xE1,0x9A,0x99,0x64,0x64,0xCF,0xAB, 0x25,0xB5,0xD5,0xDF,0x8D,0x49,0x5E,0x78,0xB5,0x87,0x73,0xA0,0xA5,0xEF,0x39,0x72 }; unsigned char AUTH_PASSWORD [] = { 0xD8,0x9F,0xD9,0xEC,0x07,0xBA,0x6F,0x8C,0xE7,0x6D,0x24,0x50,0x96,0xC7,0x20,0x03, 0x14,0xA9,0x09,0xAA,0x18,0x1C,0x08,0x2B,0xF0,0xA8,0xDA,0x16,0x53,0x65,0x16,0xF2 }; unsigned char AUTH_VFR_DATA [] = { 0x03,0x04,0xC8,0x9C,0xDE,0x53,0x76,0x96,0x40,0xA5 }; //********************************************************************************************************************* void ORACLE_MixCase_Hash (char *passwd, int passwd_len, unsigned char salt[10], unsigned char* oracle_mixcase_hash) { unsigned char to_hash[256]; memcpy (to_hash, passwd, passwd_len); memcpy (to_hash+passwd_len, salt, 10); SHA_CTX ctx; SHA1_Init (&ctx); SHA1_Update (&ctx, to_hash, passwd_len+10); SHA1_Final (oracle_mixcase_hash, &ctx); } void ORACLE_TNS_Decrypt_AES192_CBC (unsigned char aes_key_bytes[24], unsigned char* input, int input_len, unsigned char* output) { unsigned char iv[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; AES_KEY key; AES_set_decrypt_key(aes_key_bytes, 192, &key); AES_cbc_encrypt(input, output, input_len, &key, iv, AES_DECRYPT); } void ORACLE_TNS_Combine_SessKeys_24bytes (unsigned char server_sesskey[24], unsigned char client_sesskey[24], unsigned char* output) { unsigned char final[32]; unsigned char combined_sesskeys[24]; MD5_CTX ctx1,ctx2; for (int i=0;i<24;i++) combined_sesskeys[i] = server_sesskey[i] ^ client_sesskey[i]; MD5_Init (&ctx1); MD5_Update (&ctx1, combined_sesskeys, 16); MD5_Final (final, &ctx1); MD5_Init (&ctx2); MD5_Update (&ctx2, &combined_sesskeys[16], 8); MD5_Final (final+16, &ctx2); memcpy (output, final, 24); } int terminate_ascii_string (char* ascii_string_not_terminated, int len) { int ascii_len = 0; unsigned char padding_byte; for (int pos=0; ; pos++) { if ( (ascii_string_not_terminated[pos] < 32) | (ascii_string_not_terminated[pos] > 126)) break; } ascii_len = pos; padding_byte = ascii_string_not_terminated[pos]; for (;pos= 0) strncpy (decrypted, &decrypted_password[16], passlen); return passlen; } int main(int argc, char* argv[]) { // char username [32]; char password [32]; unsigned char Oracle_MixCaseHash[20]; char decrypted_password[64]; int passlen = 0; memset (decrypted_password,0,sizeof(decrypted_password)); // User and password to test // strcpy (username, "SYSTEM"); strcpy (password, "password"); printf ("*************************************************************\n"); printf ("Oracle 11g TNS AES-192 encryption tester by mao \n"); printf ("*************************************************************\n\n"); // Create Oracle Hash from the salt (AUTH_VFR_DATA) and the password ORACLE_MixCase_Hash (password, strlen (password),AUTH_VFR_DATA, Oracle_MixCaseHash); // Decrypt AUTH_PASSWORD passlen = ORACLE_TNS_Decrypt_Password_11g (Oracle_MixCaseHash, AUTH_SESSKEY, AUTH_SESSKEY_C, AUTH_PASSWORD, 32, decrypted_password); if (passlen >= 0) { printf ("Decrypted password: %s ", decrypted_password); if (strcmp (decrypted_password, "password") == 0) printf ("(correct)\n\n"); else printf ("(failed)\n\n"); } else printf ("Couldn't decrypt password\n\n"); return 0; }