While working with larger clients one sometimes encounters legacy applications that have been running on the same technology stack / backend for 20 years (or more). Running old components comes with a particular set of challenges without any doubt. But from time to time one can see artifacts that suggest security awareness itself was really just in its infancy (at least for some products on the market).
Some leeway should perhaps be given to the fact that this is old technology (for context, while Microsofts Access 97 was published on CD-rom, it was also distributed as a set of a 44 3½-inch floppy disks).
Still, it is shocking how simple it is to retrieve the database password (as stored by JET 3-4). Read a portion of the file header, and XOR that against a constant pattern. Done!
internal static class PasswordRetrieval
{
private const char NullChar = '\0';
internal static string RetrievePassword(string dbPath)
{
const int length = 19;
byte[] constantPattern =
{
0x86, 0xfb, 0xec, 0x37, 0x5d, 0x44, 0x9c, 0xfa,
0xc6, 0x5e, 0x28, 0xe6, 0x13, 0xb6, 0x8a, 0x60,
0x54, 0x94
};
var mdbPasswordSection = new byte[length];
var output = new byte[length];
using (var fileStream = File.OpenRead(dbPath))
{
fileStream.Seek(66, SeekOrigin.Begin);
fileStream.Read(mdbPasswordSection, 0, length);
}
for (var i = 0; i < length - 1; i++)
output[i] = (byte)(constantPattern[i] ^ mdbPasswordSection[i]);
var chars = Encoding.ASCII.GetString(output);
var result = chars.Substring(0, chars.IndexOf(NullChar));
return result;
}
}