Open jackpit110 opened 8 years ago
Your link give me a 404.
Are you saying you'd want Oracle 9 supported? Is it different from Oracle 10? Is it still in use anywhere?
it is common in networks to see old versions and may be it would be useful for downgrading.i dont like miss something.
ettercat is not working on this cap file.
another thing is that in oracle protocol some times we can find windows hashes.
i think it is 10. i dont know.
ora9.zip
OK I can add support to Ettercap (for a starter) once we sort out what we need.
So this looks like client v 9.2.0.1.0 talking to server 11.2.0.1.0 and I see an AUTH_SESSKEY of E24A4529CB34F719E9D3F1B331771D29 and an AUTH_PASSWORD of 8C09DD6E50EBD24CA1626B0AC5FAC36B. Is this the older case-insensitive DES-based encryption? Do you have any references? The ekoparty PDF mentions 32-byte AUTH_SESSKEY for 10g auth but this is just half of that (after decoding hex). Maybe they got it wrong (they are wrong in some other details) and meant 32-byte hex string.
https://dl.packetstormsecurity.net/papers/database/oracle-interrupted.pdf
HOWTO Secure and Audit Oracle 10g and 11g - Ron Ben-Natan
(earlier link was broken)
yes . thc programs does not match to this passwords too. check this cap file with "SCOTTSCOTTSCOTTSCOTT" as password
scott scottscottscott1
AUTH_SESSKEY ... 819D062FE5D93F79FF19BDAFE2F9872A
AUTH_PASSWORD0...0C6D1ED7E6F4D3A6D94F1E49460122D39A3832CC792AD7137
scott scottscottscott1234
AUTH_SESSKEY ... 8E9E3E07864D99BB602C443F45E4AFC1
AUTH_PASSWORD0...03591851B327BB85A114BD73D51B80AF58E942002B9612F82
scott scottscottscott12345
AUTH_SESSKEY ... 4488AFD7905E9966912CA680A3C0A23E
AUTH_PASSWORD@...@628FBAC5CF0E5548743E16123BF027B9314D7EE8B4E30DB213F683F8D7E786EA
Edit: these are not valid passwords in database
Here is a checker (had to search a bit on net to find it). It does build with VC ;)
Updated source (fixed it for passwords > 16 bytes)
/*
_____________________________________________________________________________
Subject: Oracle 9i TNS 3DES authentication details
Authors: Massimiliano Montoro <mao@oxid.it>
Issue date: June, 21, 2008
______________________________________________________________________________
This code shows the encryption algorithm used by Oracle 9i TNS protocol authentication.
Recently I found on the Internet interesting articles about Oracle TNS security but no
one of them covers the algorithm used by version 9i in details.
The following documents:
http://www.pwc.com/extweb/service.nsf/docid/3AC99308583CCE398025727400391E31/$file/oraauthdg_pub.pdf
http://freeworld.thc.org/papers/thc-orakelsniffert.pdf
do not describe the 3DES algorithm used by Oracle TNS 9i and the article
http://soonerorlater.hu/index.khtml?article_id=511
only describe the oracle DLL functions used by it. The software "oradecrypt" at this link
http://www.soonerorlater.hu/download/oradecrypt.zip
can be used to check the correctness of encrypted authentication parameters AUTH_PASSWORD and AUTH_SESSKEY
sent on the network but since it uses the native "oran10.dll" functions it is not useful to prove
the effort made by Oracle guys to improve the security of TNS authentication protocol from version 8i
to version 9i.
Test authentication parameters captured from the network:
username: PASSWORD9
AUTH_PASSWORD: 3078D7DE44385654CC952A9C56E2659B
AUTH_SESSKEY: 8CF28B36E4F3D2095729CF59510003BF
The following code will show the 3DES encryption algorithm to be used in order to check the correctness
of the password "PASSWORD9" associated to the Oracle username "PASSWORD9".
NOTE: The following code does not use native functions of "oran10.dll" or "oran9.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 is 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_3des_check.cpp
#include "windows.h"
#include "openssl/des.h"
#include "openssl/sha.h"
unsigned char deskey_fixed[]={ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
unsigned char oracle_xor_table1[] = { 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0};
int ORACLE_Hash (char* username, char *passwd, int passwd_len, unsigned char* oracle_hash)
{
char ToEncrypt[256];
char temp[256];
DES_cblock iv,iv2;
DES_key_schedule ks1, ks2;
int len=0;
int j,ulen,plen;
//_strupr (username);
//_strupr (passwd);
ulen = strlen(username);
plen = passwd_len;
strcpy(temp, username);
_strupr(temp);
ToEncrypt[0] = 0;
for (len=1,j=0; j<ulen; len++,j++)
{
ToEncrypt[len] = temp[j];
ToEncrypt[++len] = 0;
}
strcpy(temp, passwd);
_strupr(temp);
for (j=0; j<plen; len++,j++)
{
ToEncrypt[len] = temp[j];
ToEncrypt[++len] = 0;
}
len=len-1;
memset (iv,0,8);
memset (iv2,0,8);
DES_set_key((DES_cblock*) deskey_fixed, &ks1);
printf (" %02x%02x%02x%02x%02x%02x%02x%02x\n", iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7]);
DES_ncbc_encrypt((unsigned char*) ToEncrypt, (unsigned char*) temp, len, &ks1, &iv, DES_ENCRYPT);
printf ("%S", &ToEncrypt[1]);
printf (" %02x%02x%02x%02x%02x%02x%02x%02x\n", iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7]);
DES_set_key((DES_cblock*) &iv, &ks2);
DES_ncbc_encrypt((unsigned char*) ToEncrypt, (unsigned char*) temp, len, &ks2, &iv2, DES_ENCRYPT);
printf ("%S", &ToEncrypt[1]);
printf (" %02x%02x%02x%02x%02x%02x%02x%02x\n", iv2[0], iv2[1], iv2[2], iv2[3], iv2[4], iv2[5], iv2[6], iv2[7]);
memcpy (oracle_hash,iv2,8);
return TRUE;
}
int ORACLE_TNS_Create_Key_SHA1 (unsigned char* input, int input_len, unsigned char* Entropy, int EntropyLen, int desired_keylen, unsigned char* out_key)
{
unsigned char fixed23 [] = {0xF2,0xFF,0x97,0x87,0x15,0x37,0x07,0x76,0x07,0x27,0xE2,0x7F,0xA3,0xB1,0xD6,0x73,0x3F,0x2F,0xD1,0x52,0xAB,0xAC,0xC0};
unsigned char sha_hash[20];
unsigned char sha_hash2[20];
SHA_CTX ctx;
int Ento_Len = EntropyLen;
if (Entropy == NULL)
{
Entropy = fixed23;
EntropyLen = 23;
}
for (int i=0; i<desired_keylen; i+=20)
{
SHA1_Init (&ctx);
SHA1_Update (&ctx, input, input_len);
if (i != 0)
{
sha_hash2[0]=2;
SHA1_Update (&ctx, sha_hash2, i);
}
SHA1_Update (&ctx, Entropy, EntropyLen);
SHA1_Final (sha_hash, &ctx);
memcpy (sha_hash2, sha_hash, 20);
memcpy (out_key+i, sha_hash, desired_keylen-i);
}
return 0;
}
int ORACLE_TNS_Decrypt_3DES_CBC (unsigned char* input, int input_len, unsigned char key[24], unsigned char* decrypted)
{
DES_key_schedule ks1,ks2,ks3;
unsigned char iv[] = {0x80,0x20,0x40,0x04,0x08,0x02,0x10,0x01};
DES_set_key((DES_cblock*) &key[0], &ks1);
DES_set_key((DES_cblock*) &key[8], &ks2);
DES_set_key((DES_cblock*) &key[16], &ks3);
DES_ede3_cbc_encrypt(input,decrypted,input_len,&ks1,&ks2,&ks3,(DES_cblock*) iv,DES_DECRYPT);
return 0;
}
void ORACLE_TNS_DeObfuscate (unsigned char* key, unsigned char* InOutBytes, int* pLen)
{
__asm {
mov edx, [pLen]
push ebx
push esi
push edi
mov eax, [edx]
mov edi, [InOutBytes]
mov bl, [edi]
lea esi, [eax+edi]
mov cl, [esi-4]
lea eax, [esi-4]
mov [eax], bl
inc eax
mov [edi], cl
lea ecx, [edi+1]
mov bl, [eax]
inc eax
mov byte ptr [InOutBytes+3], bl
mov bl, [ecx]
mov [eax-1], bl
mov bl, byte ptr [InOutBytes+3]
mov [ecx], bl
mov bl, [eax]
inc ecx
mov byte ptr [InOutBytes+3], bl
inc eax
mov bl, [ecx]
inc ecx
mov [eax-1], bl
mov bl, byte ptr [InOutBytes+3]
mov [ecx-1], bl
mov bl, [eax]
mov byte ptr [InOutBytes+3], bl
mov bl, [ecx]
mov [eax], bl
mov al, byte ptr [InOutBytes+3]
mov [ecx], al
mov ecx, [edx]
test ecx, ecx
mov [InOutBytes], 0
jbe short uscita
mov edx, [key]
add edx, 24
ciclo:
dec esi
xor eax, eax
xor ebx, ebx
mov al, [esi]
mov bl, [edx]
xor eax, ebx
mov ebx, eax
and eax, 0Fh
shr ebx, 4
mov ebx, dword ptr oracle_xor_table1[ebx*4]
xor ebx, dword ptr oracle_xor_table1[eax*4]
jnz short sotto
mov eax, [InOutBytes]
inc eax
inc edx
cmp eax, ecx
mov [InOutBytes], eax
jb short ciclo
sotto:
mov edx, [pLen]
uscita:
sub esi, edi
pop edi
mov [edx], esi
pop esi
xor eax, eax
pop ebx
}
}
int ORACLE_TNS_Decrypt_Password_9i (unsigned char OracleHash[8], unsigned char* auth_sesskey, int auto_sesskeylen, unsigned char *auth_password, int auth_passwordlen, char* decrypted)
{
unsigned char fixed31 [] = {0xA2,0xFB,0xE6,0xAD,0x4C,0x7D,0x1E,0x3D,0x6E,0xB0,0xB7,0x6C,0x97,0xEF,0xFF,0x84,0x44,0x71,0x02,0x84,0xAC,0xF1,0x3B,0x29,0x5C,0x0F,0x0C,0xB1,0x87,0x75,0xEF};
unsigned char triple_des_key[64];
unsigned char sesskey[16];
unsigned char obfuscated[256];
int PassLen = auth_passwordlen;
ORACLE_TNS_Create_Key_SHA1 (OracleHash, 8, fixed31, sizeof(fixed31), 24, triple_des_key);
ORACLE_TNS_Decrypt_3DES_CBC (auth_sesskey, 16, triple_des_key, sesskey);
ORACLE_TNS_Create_Key_SHA1 (sesskey, 16, NULL, 0, 40, triple_des_key);
ORACLE_TNS_Decrypt_3DES_CBC (auth_password, PassLen, triple_des_key, obfuscated);
ORACLE_TNS_DeObfuscate (triple_des_key, obfuscated, &PassLen);
memcpy (decrypted, obfuscated, PassLen);
return PassLen;
}
// scott scottscottscott1
// AUTH_SESSKEY ... 819D062FE5D93F79FF19BDAFE2F9872A
// AUTH_PASSWORD0...0C6D1ED7E6F4D3A6D94F1E49460122D39A3832CC792AD7137
//
// scott scottscottscott1234
// AUTH_SESSKEY ... 8E9E3E07864D99BB602C443F45E4AFC1
// AUTH_PASSWORD0...03591851B327BB85A114BD73D51B80AF58E942002B9612F82
//
// scott scottscottscott12345
// AUTH_SESSKEY ... 4488AFD7905E9966912CA680A3C0A23E
// AUTH_PASSWORD@...@628FBAC5CF0E5548743E16123BF027B9314D7EE8B4E30DB213F683F8D7E786EA
int main(int argc, char* argv[])
{
char username [32];
char password [32];
unsigned char Oracle_Hash[8];
char decrypted_password[32];
memset (decrypted_password,0,sizeof(decrypted_password));
// Hashes transmitted on the network during authentication phase
//unsigned char AUTH_PASSWORD [] = {0x30,0x78,0xD7,0xDE,0x44,0x38,0x56,0x54,0xCC,0x95,0x2A,0x9C,0x56,0xE2,0x65,0x9B};
//unsigned char AUTH_SESSKEY [] = {0x8C,0xF2,0x8B,0x36,0xE4,0xF3,0xD2,0x09,0x57,0x29,0xCF,0x59,0x51,0x00,0x03,0xBF};
// unsigned char AUTH_PASSWORD [] = {0xC6,0xD1,0xED,0x7E,0x6F,0x4D,0x3A,0x6D,0x94,0xF1,0xE4,0x94,0x60,0x12,0x2D,0x39,0xA3,0x83,0x2C,0xC7,0x92,0xAD,0x71,0x37};
// unsigned char AUTH_SESSKEY [] = {0x81,0x9D,0x06,0x2F,0xE5,0xD9,0x3F,0x79,0xFF,0x19,0xBD,0xAF,0xE2,0xF9,0x87,0x2A};
unsigned char AUTH_PASSWORD [] = {0x62,0x8F,0xBA,0xC5,0xCF,0x0E,0x55,0x48,0x74,0x3E,0x16,0x12,0x3B,0xF0,0x27,0xB9,0x31,0x4D,0x7E,0xE8,0xB4,0xE3,0x0D,0xB2,0x13,0xF6,0x83,0xF8,0xD7,0xE7,0x86,0xEA};
unsigned char AUTH_SESSKEY [] = {0x44,0x88,0xAF,0xD7,0x90,0x5E,0x99,0x66,0x91,0x2C,0xA6,0x80,0xA3,0xC0,0xA2,0x3E};
// User and password to test
//strcpy (username, "password9");
//strcpy (password, "password9");
strcpy (username, "scott");
strcpy (password, "scottscottscott12345");
// TNS 3DES encryption algorithm
ORACLE_Hash (username, password, strlen (password), Oracle_Hash);
ORACLE_TNS_Decrypt_Password_9i (Oracle_Hash, AUTH_SESSKEY, sizeof(AUTH_SESSKEY), AUTH_PASSWORD, sizeof(AUTH_PASSWORD), decrypted_password);
printf ("*********************************************************\n");
printf ("Oracle 9i TNS 3DES encryption tester by mao <mao@oxid.it>\n");
printf ("*********************************************************\n\n");
printf ("Decrypted password: %s ", decrypted_password);
if (strcmp (decrypted_password, password) == 0)
printf ("(correct)\n");
else
printf ("(failed)\n");
return 0;
}
60fc31b
@jackpit110 please test. Also, if you can provide some hashes which have password (and user name if possible), that are not pure lower ascii characters. Things like
deberá etc which have non 0x7f ascii characters would be nice to get.
Note, this is VERY close to the oracle10 hash format. I assume under the hood, this is the same hash, BUT what we are seeing is 2 items sent to the client so the client can 'pre-validate' the password or something like that.
NOTE, there is no sniffed-oracle-2-john yet. Also, I took liberty in the format:
$ora9i$ user $ auth_sesskey $ auth_password
Since this is a 'new' format, we can easily change that if we need to.
NOTE, we also need some passwords entered that have upper case in them. I changed the format to be FMT_CASE, 'but' it may simply be that it is not case, but lowercases the password before encryption sent over the wire. Somewhat strange, since all the rest of oracle upcases (with proper utf16-be encoding).
But it is what it is. If this is how the actual server does things, we just need to mimic that behavior.
We should add a PR to https://github.com/Ettercap/ettercap for a sniffer dissector.
BTW we have oracle, oracle11, Oracle12C as normal (not sniffed) hash formats, and o5logon for the sniffed Oracle 10/11/12 stuff. Perhaps this should be called o3logon or whatever this protocol is called.
what do you think about the format (first) ?
$ora9i$ user $ sess $ pass
?
Note, should this be renamed oracle-sniffed, vs oracle9? I really do not think this is oracle 9i only, but think it is a quick-check value passed back to the client, prior to the client making the actual login request.
I actually think this is oracle 10 (and probably same in oracle 9) but is sniffed, vs grabbed from the DB.
The 'setup' looks damn near the same as oracle 10. We just have to decrypt the buffer in oracle's convoluted way, and then see that the password was in the encrypted data (i.e. there is no binary() data in our format).
BUT from the looks of things, it must be the same internal hash as we see in our oracle 10 (look at the DES, the key setup, IV's used, etc). Same stuff.
so possibly $oraclesniff$ ??
Where did the name '05login' come from? Would this not be 04login if 05 was 'correct' ? But yes, you are right, this probably is a better name if the 05login is also the 'sniffed' version.
Ok, hopefully this will pass tests: 70eb55a (it works fine on my clang, Sparc, linux-64, VC and cygwin).
It is not that fast, nor is it written in stone that the format signature is what we want in the end. It is still missing OMP, and I need to see if it can also be optimized. I simply wanted 'something' that worked, and can be used as a test bed when the Ettercap or whatever *2john tool is built. I would like to get this into pass_gen.pl also (possibly), but it might be a bit more work than I want to invest for that tool however.
@magnumripper/@kholia I was not looking at doing a PR for Ettercap. I think you 2 are the main liaison between the projects, correct?
Good, the clang build/run got past this format with no core now. I am out for the evening, so hopefully whatever choices are made for the signature will be made for when the buzz wears off ;)
It's not 05login, it's o5logon. The '5' is a version. IIRC I've seen o3logon mentioned but not o4logon so o4 may never have made it to the public (just like IPv5). Not sure at all.
How do we get the $o5logon$ hashes? Is that some builtin output from Ettercap ?
I see no o5logon2john nor is it done in pcap2john.py.
It's a dissector in ettercap. Just run a pcap through ettercap and it will output o5logon hashes in JtR format. I have an active PR submitted, enhancing it and adding Oracle 12 support.
Note, there is also a format we should make, that I 'think' is based on o5logon, but where the AUTH_VFR_DATA field contains no data, so the improvement we see where we only need to use the servers's session_key and the servers auth_vfr_data to see if the hash matches. BUT there is an algorithm that is almost like what I have done for this O3login hash, but it uses AES vs using DES (well there are other changes, BUT in the end it is very similar).
I just sniffed a login for my own account on our oracle server, and I can crack my password just fine. This deals with sniffing login sessions that are 'valid' (much like the 4-way WPAPSK sniffed sessions). I am pretty sure the O3logon is the same thing (sniffed valid login).
Here is the code for O5Logon without the AUTH_VFR_DATA security hole. This one uses a sniff of a valid login, needing to get both the client and server responses. This is very similar to the O3login format, but using aes and of course a little different logic. But still, we might want to investigate this as a format. I sniffed my corp network, while making an oracle connection with my desktop client, and from the wshark packets was able to get the 3 items needed (4 with my user id), and plugged into this code, and it cracked it just fine.
/*
_____________________________________________________________________________
Subject: Oracle 10g TNS AES-128 authentication details
Authors: Massimiliano Montoro <mao@oxid.it>
Issue date: July, 1, 2008
______________________________________________________________________________
This code shows the encryption algorithm used by Oracle 10g TNS protocol authentication.
Recently I found on the Internet interesting articles about Oracle TNS security but no
one of them covers the algorithm used by version 10g in details.
The following documents:
http://www.pwc.com/extweb/service.nsf/docid/3AC99308583CCE398025727400391E31/$file/oraauthdg_pub.pdf
http://freeworld.thc.org/papers/thc-orakelsniffert.pdf
do not describe the AES algorithm used by Oracle TNS 10g and the article
http://soonerorlater.hu/index.khtml?article_id=511
only descrybe the oracle DLL functions used by it. The software "oradecrypt" at this link
http://www.soonerorlater.hu/download/oradecrypt.zip
can be used to check the correctness of encrypted authentication parameters AUTH_PASSWORD and AUTH_SESSKEY
sent on the network but because it uses the native "oran10.dll" functions it is not useful to prove
the effort made by Oracle guys to improve the security of TNS authentication protocol from version 8i and 9i
to version 10g.
Test authentication parameters captured from the network:
username: TESTUSER
AUTH_SESSKEY: EEABE812530C6D4432F781DFC14A7C7F81EAE1804F340D3289732477FD351FCC
AUTH_SESSKEY_CLIENT: 7B244D7A1DB5ABE553FB9B7325110024911FCBE95EF99E7965A754BC41CF31C0
AUTH_PASSWORD: 4C5E28E66B6382117F9D41B08957A3B9E363B42760C33B44CA5D53EA90204ABE
The following code will show the AES-128 encryption algorithm to be used in order to check the correctness
of the password "TESTPASS" associated to the Oracle username "TESTUSER".
NOTE: The following code does not use native functions of "oran10.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 is 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_aes128_check.cpp
#include "windows.h"
#include <openssl/des.h>
#include <openssl/aes.h>
#include <openssl/md5.h>
//*********************************************************************************************************************
// Hashes captured on the network during authentication phase
unsigned char AUTH_SESSKEY [] = {0xEE,0xAB,0xE8,0x12,0x53,0x0C,0x6D,0x44,0x32,0xF7,0x81,0xDF,0xC1,0x4A,0x7C,0x7F,0x81,0xEA,0xE1,0x80,0x4F,0x34,0x0D,0x32,0x89,0x73,0x24,0x77,0xFD,0x35,0x1F,0xCC};
unsigned char AUTH_SESSKEY_C[] = {0x7B,0x24,0x4D,0x7A,0x1D,0xB5,0xAB,0xE5,0x53,0xFB,0x9B,0x73,0x25,0x11,0x00,0x24,0x91,0x1F,0xCB,0xE9,0x5E,0xF9,0x9E,0x79,0x65,0xA7,0x54,0xBC,0x41,0xCF,0x31,0xC0};
unsigned char AUTH_PASSWORD [] = {0x4C,0x5E,0x28,0xE6,0x6B,0x63,0x82,0x11,0x7F,0x9D,0x41,0xB0,0x89,0x57,0xA3,0xB9,0xE3,0x63,0xB4,0x27,0x60,0xC3,0x3B,0x44,0xCA,0x5D,0x53,0xEA,0x90,0x20,0x4A,0xBE};
//*********************************************************************************************************************
unsigned char deskey_fixed[]={ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
int ORACLE_Hash (char* username, char *passwd, int passwd_len, unsigned char* oracle_hash)
{
char ToEncrypt[256];
char temp[256];
DES_cblock iv,iv2;
DES_key_schedule ks1, ks2;
int len=0;
int j,ulen,plen;
memset (ToEncrypt,0,sizeof(ToEncrypt));
strupr (username);
strupr (passwd);
ulen = strlen(username);
plen = passwd_len;
for (len=1,j=0; j<ulen; len++,j++)
{
ToEncrypt[len] = username[j];
len++;
}
for (j=0; j<plen; len++,j++)
{
ToEncrypt[len] = passwd[j];
len++;
}
len=len-1;
memset (iv,0,8);
memset (iv2,0,8);
DES_set_key((DES_cblock*) deskey_fixed, &ks1);
DES_ncbc_encrypt((unsigned char*) ToEncrypt, (unsigned char*) temp, len, &ks1, &iv, DES_ENCRYPT);
DES_set_key((DES_cblock*) &iv, &ks2);
DES_ncbc_encrypt((unsigned char*) ToEncrypt, (unsigned char*) temp, len, &ks2, &iv2, DES_ENCRYPT);
memcpy (oracle_hash,iv2,8);
return TRUE;
}
void ORACLE_TNS_Decrypt_AES128_CBC (unsigned char aes_key_bytes[16], 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, 128, &key);
AES_cbc_encrypt(input, output, input_len, &key, iv, AES_DECRYPT);
}
void ORACLE_TNS_Combine_SessKeys (unsigned char server_sesskey[16], unsigned char client_sesskey[16], unsigned char* output)
{
unsigned char combined_sesskeys[16];
for (int i=0;i<16;i++) combined_sesskeys[i] = server_sesskey[i] ^ client_sesskey[i];
MD5_CTX ctx;
MD5_Init (&ctx);
MD5_Update (&ctx, combined_sesskeys,16);
MD5_Final (output, &ctx);
}
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<len; pos++)
if (ascii_string_not_terminated[pos] != padding_byte) return -1;
ascii_string_not_terminated[ascii_len] = 0;
return ascii_len;
}
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)
{
int passlen = 0;
unsigned char aes_key_bytes[32];
unsigned char decrypted_server_sesskey[32];
unsigned char decrypted_client_sesskey[32];
unsigned char combined_sesskeys[16];
char decrypted_password[64];
memset (aes_key_bytes,0,sizeof(aes_key_bytes));
memcpy (aes_key_bytes,OracleHash,8);
// Decrypt server and client session keys
ORACLE_TNS_Decrypt_AES128_CBC (aes_key_bytes, auth_sesskey, 32, decrypted_server_sesskey);
ORACLE_TNS_Decrypt_AES128_CBC (aes_key_bytes, auth_sesskey_cli, 32, decrypted_client_sesskey);
// Combine server and client session keys
ORACLE_TNS_Combine_SessKeys (&decrypted_server_sesskey[16], &decrypted_client_sesskey[16], combined_sesskeys);
// Decrypt auth password with combined session key
ORACLE_TNS_Decrypt_AES128_CBC (combined_sesskeys, auth_password, auth_password_len, (unsigned char*) decrypted_password);
// terminate decrypted password with NULL
passlen = terminate_ascii_string (&decrypted_password[16], auth_password_len-16);
if (passlen != -1)
strncpy (decrypted, &decrypted_password[16], passlen);
return passlen;
}
int main(int argc, char* argv[])
{
char username [32];
char password [32];
unsigned char Oracle_Hash[8];
char decrypted_password[64];
memset (decrypted_password,0,sizeof(decrypted_password));
// User and password to test
strcpy (username, "TESTUSER");
strcpy (password, "TESTPASS");
printf ("*************************************************************\n");
printf ("Oracle 10g TNS AES-128 encryption tester by mao <mao@oxid.it>\n");
printf ("*************************************************************\n\n");
// Create Oracle Hash from username and password
ORACLE_Hash (username, password, strlen (password), Oracle_Hash);
// Decrypt AUTH_PASSWORD
int passlen = ORACLE_TNS_Decrypt_Password_10g (Oracle_Hash, AUTH_SESSKEY, AUTH_SESSKEY_C, AUTH_PASSWORD, 32, decrypted_password);
if (passlen != -1)
{
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;
}
I am adding the above algorithm (there is no x2john at the moment). I am calling this o10glogon NOTE, 05logon is oracle 11g sniffed (with some security flaw). This is oracle 10g (sniffed) and there is no 'flaw' in the 10g AFAIK. I bet there is also 11g sniffed without the security flaw, not sure if we can find that or not.
What do ppl think of the name o10glogon ?? Could this be o4logon if there is such a beast ?
Not bad speed (but get an OMP helping hand, lol).
$ ../run/john -test=5 -form=oracle
Benchmarking: oracle, Oracle 10 [DES 32/64]... DONE
Raw: 851116 c/s real, 850857 c/s virtual
$ ../run/john -test=5 -form=o10glogon
Will run 8 OpenMP threads
Benchmarking: o10glogon, Oracle 10g-logon protocol [DES-AES128-MD5 32/64]... (8xOMP) DONE
Raw: 1427K c/s real, 226015 c/s virtual
here is the code. I will wait to check in, to allow people to comment on the format_tag, format name, file name, etc. I am currently calling this o10glogon_fmt_plug.c with $o10glogon$
as the format tag.
/*
* This software was written by JimF jfoug AT cox dot net
* in 2016. No copyright is claimed, and the software is hereby
* placed in the public domain. In case this attempt to disclaim
* copyright and place the software in the public domain is deemed
* null and void, then the software is Copyright (c) 2016 JimF
* and it is hereby released to the general public under the following
* terms:
*
* This software may be modified, redistributed, and used for any
* purpose, in source and binary forms, with or without modification.
*
* This is oracle O10g-logon format. NOTE, if the hashes came from a
* Oracle 10g, and the hash data can be sniffed from network traffic
* TNS records.
*
*/
#if FMT_EXTERNS_H
extern struct fmt_main fmt_o10glogon;
#elif FMT_REGISTERS_H
john_register_one(&fmt_o10glogon);
#else
#include <string.h>
#include <openssl/des.h>
#include <openssl/aes.h>
#include "arch.h"
#include "misc.h"
#include "common.h"
#include "formats.h"
#include "md5.h"
#include "unicode.h"
#include "base64_convert.h"
#ifdef _OPENMP
static int omp_t = 1;
#include <omp.h>
#ifndef OMP_SCALE
#define OMP_SCALE 512 // tuned on core i7
//#define OMP_SCALE 8192 // tuned on K8-Dual HT
#endif
#endif
#include "memdbg.h"
#define FORMAT_LABEL "o10glogon"
#define FORMAT_NAME "Oracle 10g-logon protocol"
#define FORMAT_TAG "$o10glogon$"
#define FORMAT_TAG_LEN (sizeof(FORMAT_TAG)-1)
#define ALGORITHM_NAME "DES-AES128-MD5 32/" ARCH_BITS_STR
#define BENCHMARK_COMMENT ""
#define BENCHMARK_LENGTH -1
#define PLAINTEXT_LENGTH 32
#define BINARY_SIZE 0
#define BINARY_ALIGN 1
#define MAX_USERNAME_LEN 30
#define SALT_SIZE (sizeof(ora10g_salt))
#define SALT_ALIGN (sizeof(unsigned int))
#define CIPHERTEXT_LENGTH 16
#define MIN_KEYS_PER_CRYPT 1
#define MAX_KEYS_PER_CRYPT 1
#define MAX_HASH_LEN (FORMAT_TAG_LEN+MAX_USERNAME_LEN+1+64+1+64+1+160)
//#define DEBUG_ORACLE
//
// The keys are $o10glogon$oracle-user-name$auth_sess_key$auth_sess_key_c$auth_password
// These can be found in sniffed network traffic.
static struct fmt_tests tests[] = {
{"$o10glogon$jimf$6DA8BE6D9713B7F9190DC0F87F1BB1BDFFE44EB1892E40915592980ECCE60AA3$1C08586339E5806DD45CF8E6D83CC6EA2B8CDCDE7CC9F00ADF43DA0F07309090$E2F3D778138213BF01FD743F2092FC976FD60AB2C9F4A1B1D9B08439325421B1", "JimF"},
{"$o10glogon$SESA218390$3B16F14C3DC6048C993000E2BF543BAB489DF7BD8D6061B7274CC9E1DB743E08$1695D5255EDF15CA6B1F14C5CB39C72C98E2CC2B62FB3224ECA5A6A6790511D4$F0F64E384E567F44E9DF8D7F4C029AA59770FA75094F1C26A66C45AFA9913987", "jimf"},
{"$o10glogon$TESTUSER$EEABE812530C6D4432F781DFC14A7C7F81EAE1804F340D3289732477FD351FCC$7B244D7A1DB5ABE553FB9B7325110024911FCBE95EF99E7965A754BC41CF31C0$4C5E28E66B6382117F9D41B08957A3B9E363B42760C33B44CA5D53EA90204ABE", "TESTPASS"},
{NULL}
};
typedef struct ora10g_salt_t {
int userlen, auth_pass_len;
UTF16 user[MAX_USERNAME_LEN+1];
unsigned char auth_sesskey[32];
unsigned char auth_sesskey_c[32];
unsigned char auth_pass[80];
} ora10g_salt;
static ora10g_salt *cur_salt;
static UTF16 (*cur_key)[PLAINTEXT_LENGTH + 1];
static char (*plain_key)[PLAINTEXT_LENGTH + 1];
static int *cur_key_len;
static int *cracked, any_cracked;
static DES_key_schedule desschedule1; // key 0x0123456789abcdef
static void init(struct fmt_main *self)
{
DES_set_key((DES_cblock *)"\x01\x23\x45\x67\x89\xab\xcd\xef", &desschedule1);
#ifdef _OPENMP
omp_t = omp_get_max_threads();
self->params.min_keys_per_crypt *= omp_t;
omp_t *= OMP_SCALE;
self->params.max_keys_per_crypt *= omp_t;
#endif
cur_key = mem_calloc(self->params.max_keys_per_crypt,
sizeof(*cur_key));
plain_key = mem_calloc(self->params.max_keys_per_crypt,
sizeof(*plain_key));
cur_key_len = mem_calloc(self->params.max_keys_per_crypt,
sizeof(*cur_key_len));
cracked = mem_calloc(self->params.max_keys_per_crypt,
sizeof(*cracked));
}
static void done(void)
{
MEM_FREE(cracked);
MEM_FREE(cur_key_len);
MEM_FREE(plain_key);
MEM_FREE(cur_key);
}
static int valid(char *ciphertext, struct fmt_main *self)
{
char *cp;
char tmp[32*5+1];
UTF16 cur_key_mixedcase[MAX_USERNAME_LEN+2];
int len, extra;
if (strncmp(ciphertext, FORMAT_TAG, FORMAT_TAG_LEN))
return 0;
ciphertext += FORMAT_TAG_LEN;
cp = strchr(ciphertext, '$');
if (!cp)
return 0;
// make sure username fits in MAX_USERNAME_LEN UTF16
if (cp-ciphertext > sizeof(tmp)-1)
return 0;
memcpy(tmp, ciphertext, cp-ciphertext);
tmp[cp-ciphertext] = 0;
len = enc_to_utf16((UTF16 *)cur_key_mixedcase, MAX_USERNAME_LEN+1, (unsigned char*)tmp, strlen(tmp));
if (len < 0 || (len == 0 && cp-ciphertext)) {
static int error_shown = 0;
#ifdef HAVE_FUZZ
if (options.flags & (FLG_FUZZ_CHK | FLG_FUZZ_DUMP_CHK))
return 0;
#endif
if (!error_shown)
fprintf(stderr, "%s: Input file is not UTF-8. Please use --input-enc to specify a codepage.\n", self->params.label);
error_shown = 1;
return 0;
}
if (len > MAX_USERNAME_LEN)
return 0;
ciphertext = cp+1;
cp = strchr(ciphertext, '$');
if (!cp || cp-ciphertext != 64 || hexlenu(ciphertext, 0) != 64)
return 0;
ciphertext = cp+1;
cp = strchr(ciphertext, '$');
if (!cp || cp-ciphertext != 64 || hexlenu(ciphertext, 0) != 64)
return 0;
ciphertext = cp+1;
len = strlen(ciphertext);
cp = strchr(ciphertext, '$');
if (!len || cp || len%16 || hexlenu(ciphertext, &extra) != len || extra)
return 0;
return 1;
}
static char *split(char *ciphertext, int index, struct fmt_main *self)
{
static char out[MAX_HASH_LEN*5+1];
strnzcpy(out, ciphertext, MAX_HASH_LEN+1);
enc_strupper(&out[FORMAT_TAG_LEN]);
return out;
}
static void set_salt(void *salt) {
cur_salt = (ora10g_salt *)salt;
}
static void oracle_set_key(char *key, int index) {
UTF16 cur_key_mixedcase[PLAINTEXT_LENGTH+1];
UTF16 *c;
int key_length;
strcpy(plain_key[index], key);
// Can't use enc_to_utf16_be() because we need to do utf16_uc later
key_length = enc_to_utf16(cur_key_mixedcase, PLAINTEXT_LENGTH, (unsigned char*)key, strlen(key));
if (key_length < 0)
key_length = strlen16(cur_key_mixedcase);
// We convert and uppercase in one shot
key_length = utf16_uc(cur_key[index], PLAINTEXT_LENGTH, cur_key_mixedcase, key_length);
// we have no way to 'undo' here, since the expansion is due to single-2-multi expansion in the upcase,
// and we can not 'fix' our password. We simply have to 'not' properly decrypt this one, but protect ourselves.
if (key_length < 0)
key_length *= -1;
cur_key_len[index] = key_length * sizeof(UTF16);
// Now byte-swap to UTF16-BE
c = cur_key[index];
while((*c = *c << 8 | *c >> 8))
c++;
#ifdef DEBUG_ORACLE
dump_stuff_msg("cur_key ", (unsigned char*)cur_key[index], cur_key_len[index]);
#endif
}
static char *get_key(int index) {
return plain_key[index];
}
static void ORACLE_TNS_Decrypt_AES128_CBC (unsigned char aes_key_bytes[16], 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, 128, &key);
AES_cbc_encrypt(input, output, input_len, &key, iv, AES_DECRYPT);
}
static int terminate_ascii_string (char* ascii_string_not_terminated, int len)
{
int ascii_len = 0;
unsigned char padding_byte;
int pos;
for (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<len; pos++) {
if (ascii_string_not_terminated[pos] != padding_byte)
return -1;
}
ascii_string_not_terminated[ascii_len] = 0;
return ascii_len;
}
static void ORACLE_TNS_Combine_SessKeys (unsigned char server_sesskey[16], unsigned char client_sesskey[16], unsigned char* output)
{
unsigned char combined_sesskeys[16];
int i;
MD5_CTX ctx;
for (i=0;i<16;i++)
combined_sesskeys[i] = server_sesskey[i] ^ client_sesskey[i];
MD5_Init (&ctx);
MD5_Update (&ctx, combined_sesskeys,16);
MD5_Final (output, &ctx);
}
static int ORACLE_TNS_Decrypt_Password_10g (unsigned char OracleHash[8], unsigned char *auth_sesskey, unsigned char *auth_sesskey_c, unsigned char *auth_password, int auth_passwordlen, unsigned char *decrypted)
{
int passlen = 0;
unsigned char aes_key_bytes[32];
unsigned char decrypted_server_sesskey[32];
unsigned char decrypted_client_sesskey[32];
unsigned char combined_sesskeys[16];
char decrypted_password[64];
memset (aes_key_bytes,0,sizeof(aes_key_bytes));
memcpy (aes_key_bytes,OracleHash,8);
// Decrypt server and client session keys
ORACLE_TNS_Decrypt_AES128_CBC (aes_key_bytes, auth_sesskey, 32, decrypted_server_sesskey);
ORACLE_TNS_Decrypt_AES128_CBC (aes_key_bytes, auth_sesskey_c, 32, decrypted_client_sesskey);
// Combine server and client session keys
ORACLE_TNS_Combine_SessKeys (&decrypted_server_sesskey[16], &decrypted_client_sesskey[16], combined_sesskeys);
// Decrypt auth password with combined session key
ORACLE_TNS_Decrypt_AES128_CBC (combined_sesskeys, auth_password, auth_passwordlen, (unsigned char*) decrypted_password);
// terminate decrypted password with NULL
passlen = terminate_ascii_string (&decrypted_password[16], auth_passwordlen-16);
if (passlen != -1)
strncpy ((char*)decrypted, &decrypted_password[16], passlen);
return passlen;
}
static int crypt_all(int *pcount, struct db_salt *salt)
{
const int count = *pcount;
int idx = 0;
if (any_cracked) {
memset(cracked, 0, sizeof(*cracked) * count);
any_cracked = 0;
}
#ifdef DEBUG_ORACLE
dump_stuff_msg("cur_salt ", buf, cur_salt->userlen+key_length);
#endif
#ifdef _OPENMP
#pragma omp parallel for
for (idx = 0; idx < count; idx++)
#endif
{
unsigned char buf[256], buf1[256];
unsigned int l;
ARCH_WORD_32 iv[2];
DES_key_schedule desschedule2;
l = cur_salt->userlen + cur_key_len[idx];
memcpy(buf, cur_salt->user, cur_salt->userlen);
memcpy(buf + cur_salt->userlen, cur_key[idx], cur_key_len[idx]);
iv[0] = iv[1] = 0;
DES_ncbc_encrypt((unsigned char *)buf, buf1, l, &desschedule1, (DES_cblock *) iv, DES_ENCRYPT);
DES_set_key((DES_cblock *)iv, &desschedule2);
iv[0] = iv[1] = 0;
DES_ncbc_encrypt((unsigned char *)buf, buf1, l, &desschedule2, (DES_cblock *) iv, DES_ENCRYPT);
#ifdef DEBUG_ORACLE
dump_stuff_msg(" iv (the hash key) ", (unsigned char*)&iv[0], 8);
#endif
ORACLE_TNS_Decrypt_Password_10g ((unsigned char*)iv, cur_salt->auth_sesskey, cur_salt->auth_sesskey_c, cur_salt->auth_pass, cur_salt->auth_pass_len, buf);
if (!strncmp((char*)buf, plain_key[idx], strlen(plain_key[idx])))
{
cracked[idx] = 1;
#ifdef _OPENMP
#pragma omp atomic
#endif
any_cracked |= 1;
}
}
return count;
}
static void *get_salt(char *ciphertext)
{
static ora10g_salt salt;
UTF8 tmp[MAX_USERNAME_LEN*5+1];
char *cp;
memset(&salt, 0, sizeof(salt));
ciphertext += FORMAT_TAG_LEN;
cp = strchr(ciphertext, '$');
strncpy((char*)tmp, ciphertext, cp-ciphertext);
tmp[cp-ciphertext] = 0;
salt.userlen = enc_to_utf16_be(salt.user, MAX_USERNAME_LEN, tmp, cp-ciphertext);
if (salt.userlen < 0)
salt.userlen = strlen16(salt.user);
salt.userlen *= 2;
base64_convert(cp+1,e_b64_hex,64,salt.auth_sesskey,e_b64_raw,32,0,0);
cp = strchr(cp+1, '$');
base64_convert(cp+1,e_b64_hex,64,salt.auth_sesskey_c,e_b64_raw,32,0,0);
cp = strchr(cp+1, '$') + 1;
salt.auth_pass_len = strlen(cp)/2;
base64_convert(cp,e_b64_hex,salt.auth_pass_len*2,salt.auth_pass,e_b64_raw,salt.auth_pass_len,0,0);
return &salt;
}
// Public domain hash function by DJ Bernstein (salt is a username)
static int salt_hash(void *salt)
{
UTF16 *s = ((UTF16*)salt) + 1;
unsigned int hash = 5381;
while (*s)
hash = ((hash << 5) + hash) ^ *s++;
return hash & (SALT_HASH_SIZE - 1);
}
static int cmp_all(void *binary, int count)
{
return any_cracked;
}
static int cmp_one(void *binary, int count)
{
return cracked[count];
}
static int cmp_exact(char *source, int index)
{
return 1;
}
struct fmt_main fmt_o10glogon = {
{
FORMAT_LABEL,
FORMAT_NAME,
ALGORITHM_NAME,
BENCHMARK_COMMENT,
BENCHMARK_LENGTH,
0,
PLAINTEXT_LENGTH,
BINARY_SIZE,
BINARY_ALIGN,
SALT_SIZE,
SALT_ALIGN,
MIN_KEYS_PER_CRYPT,
MAX_KEYS_PER_CRYPT,
FMT_8_BIT | FMT_UNICODE | FMT_UTF8 | FMT_SPLIT_UNIFIES_CASE | FMT_CASE | FMT_OMP,
{ NULL },
{ FORMAT_TAG },
tests
}, {
init,
done,
fmt_default_reset,
fmt_default_prepare,
valid,
split,
fmt_default_binary,
get_salt,
{ NULL },
fmt_default_source,
{
fmt_default_binary_hash
},
salt_hash,
NULL,
set_salt,
oracle_set_key,
get_key,
fmt_default_clear_keys,
crypt_all,
{
fmt_default_get_hash
},
cmp_all,
cmp_one,
cmp_exact
}
};
#endif /* plugin stanza */
What do ppl think of the name o10glogon ?? Could this be o4logon if there is such a beast ?
AFAIK o3logon and o5logon are Oracle's names for protocols so we shouldn't invent our own that sounds like them. Either find out what they are calling this one, or use some generally descripting name.
that is what o10glogon was (my own generic name). It is the sniffed login data from oracle 10g client logon's. The problem is that 03logon is for oracle 8 (and 9?) and 05logon is for buggy 11g. (all sniffed). I bet there is also 11g 'generic' that is not the broken buggy o5logon that we support.
But this format is 100% 'there'. I have verified that it works, and all hashes were sniffed from a real oracle client/server connections. I just do not know what to name the damn thing. I am sort of leaning of leaving it alone, since it does list that this is a sniffed 10g protocol.
Yeah o10glogon is fine until we know better. These are not exactly well documented protocols, I think most public info is reverse engineered.
I am pretty sure all of these are rev engineered (gotta love java where you ship source code, lol). And there are dozens of tweaks and mods to the oracle scheme.
I will check it in the way it is. NOTE, I have no intention of building a 10g2john ripper. Probably should be done in etercap in some manner (but I do not know that project at all). 9b18eef
Sorry i wasn't around.
cap file from testing in oracle net manager in oracle 9: oracle9ClientToOra11R2_Oracle9.zip
attached file is from oracle 9 to oracle 11 r2 . oracle 9 session encryption is not same with oracle 10 user: scott password: Oracle9
@jfoug After running this query -- USER SQL ALTER USER "SCOTT" IDENTIFIED BY deberá DEFAULT TABLESPACE "EXAMPLE" TEMPORARY TABLESPACE "TEMP" ACCOUNT UNLOCK ;
I got SQL Error: ORA-00911: invalid character
Comma, backslash, double quote and the DEFINE symbol are not allowed in passwords
cap file Oracle Enterprise Manager in Oracle 9: oracle9toOracle11_Oracle9_oracleEnterpriseManager.zip
user: scott password: Oracle9
it seems oracle 11 newer version have no problem with this password user: scott password: deberá
I was not successful with cracking this cap file. In this cap file i am connecting from sqlplus oracle 11 unpatched padding to oracle 12. so it is downgrading to oracle 10(may be) User: sys password: hashcat sqlplus11toOra12_hashcat.zip
$o10glogon$sys$9283C006D592527A298BCF1F7D6FCF358533793B32977A6839DE411482906C90$4529BF09FAC648A9250FB32FE44BAFAC8C4B97E17CC1D8914959E3CBD98F9E9D$32D21C6E5C3DCD93E55A29DCFE80BD1A644EEC5D62C36A0B3D0B0E9D460875BC
oracle client 9 pass: hashcat
oracle client 9.zip