Protecting Secrets in Windows NT 4

Protecting Secrets in Windows NT 4

Windows NT 4 does not include the DPAPI, but it includes CryptoAPI support and ACLs. You can protect data in Windows NT 4 by performing these steps:

  1. Create a random key by using CryptGenRandom.

  2. Store the key in the registry.

  3. ACL the registry key such that Creator/Owner and Administrators have full control.

  4. If you are really paranoid, place an audit ACE (SACL) on the resource so that you can see who is attempting to read the data.

Each time you want to encrypt or decrypt the data, only the user account that created the key (the object's owner) or a local administrator can read the key and use it to carry out the task. This is not perfect, but at least the security bar has been raised such that only an administrator or the user in question can carry out the process. Of course, if you invite a Trojan horse application to run on your computer, it can read the key data from the registry, because it runs under your account, and then decrypt the data.

You can also use LSA secrets (LsaStorePrivateData and LsaRetrievePrivateData) as discussed previously in the Protecting Secrets in Windows 2000 and Later section. Four types of LSA secrets exist: local data, global data, machine data, and private data. Local data LSA secrets can be read only locally from the machine storing the data. Attempting to read such data remotely results in an Access Denied error. Local data LSA secrets have key names that begin with the prefix L$. Global data LSA secrets are global such that if they are created on a domain controller (DC), they are automatically replicated to all other DCs in that domain. Global data LSA secrets have key names beginning with G$. Machine data LSA secrets can be accessed only by the operating system. These key names begin with M$. Private data LSA secrets, unlike the preceding specialized types, have key names that do not start with a prefix. Such data is not replicated and can be read locally or remotely. Note that service account passwords are not disclosed remotely and start with an SC_ prefix. Other prefixes exist, and you should refer to the LsaStorePrivateData MSDN documentation for further detail.

The Differences Between LSA Secrets and DPAPI

You should be aware of a number of differences between these two data protection technologies. They include the following:
  • LSA secrets are limited to 4096 objects; DPAPI is unlimited.

  • LSA code is complex; DPAPI code is simple!

  • DPAPI adds an integrity check to the data; LSA does not.

  • LSA stores the data on behalf of the application; DPAPI returns an encrypted blob to the application, and the application must store the data.

  • To use LSA, the calling application must execute in the context of an administrator. Any user ACLs on the encrypted data aside can use DPAPI.

Before you can store or retrieve LSA secret data, your application must acquire a handle to the LSA policy object. Here's a sample C++ function that will open the policy object:

//LSASecrets.cpp : Defines the entry point for the console application. #include <windows.h> #include <stdio.h> #include "ntsecapi.h" bool InitUnicodeString(LSA_UNICODE_STRING* pUs, const WCHAR* input){ DWORD len = 0; if(!pUs) return false; if(input){ len = wcslen(input); if(len > 0x7ffe) //32k -1 return false; } pUs->Buffer = (WCHAR*)input; pUs->Length = (USHORT)len * sizeof(WCHAR); pUs->MaximumLength = (USHORT)(len + 1) * sizeof(WCHAR); return true; } LSA_HANDLE GetLSAPolicyHandle(WCHAR *wszSystemName) { LSA_OBJECT_ATTRIBUTES ObjectAttributes; ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); LSA_UNICODE_STRING lusSystemName; if(!InitUnicodeString(&lusSystemName, wszSystemName))return NULL; LSA_HANDLE hLSAPolicy = NULL; NTSTATUS ntsResult = LsaOpenPolicy(&lusSystemName,&ObjectAttributes, POLICY_ALL_ACCESS, &hLSAPolicy); DWORD dwStatus = LsaNtStatusToWinError(ntsResult); if (dwStatus != ERROR_SUCCESS) { wprintf(L"OpenPolicy returned %lu\n",dwStatus); return NULL; } return hLSAPolicy; }

The following code example shows how to use LSA secrets to encrypt and decrypt information:

DWORD WriteLsaSecret(LSA_HANDLE hLSA, WCHAR *wszSecret, WCHAR *wszName) { LSA_UNICODE_STRING lucName; if(!InitUnicodeString(&lucName, wszName)) return ERROR_INVALID_PARAMETER; LSA_UNICODE_STRING lucSecret; if(!InitUnicodeString(&lucSecret, wszSecret)) return ERROR_INVALID_PARAMETER; NTSTATUS ntsResult = LsaStorePrivateData(hLSA,&lucName, &lucSecret); DWORD dwStatus = LsaNtStatusToWinError(ntsResult); if (dwStatus != ERROR_SUCCESS) wprintf(L"Store private object failed %lu\n",dwStatus); return dwStatus; } DWORD ReadLsaSecret(LSA_HANDLE hLSA,DWORD dwBuffLen, WCHAR *wszSecret, WCHAR *wszName) { LSA_UNICODE_STRING lucName; if(!InitUnicodeString(&lucName, wszName)) return ERROR_INVALID_PARAMETER; PLSA_UNICODE_STRING plucSecret = NULL; NTSTATUS ntsResult = LsaRetrievePrivateData(hLSA, &lucName, &plucSecret); DWORD dwStatus = LsaNtStatusToWinError(ntsResult); if (dwStatus != ERROR_SUCCESS) wprintf(L"Store private object failed %lu\n",dwStatus); else wcsncpy(wszSecret, plucSecret->Buffer, min((plucSecret->Length)/sizeof WCHAR,dwBuffLen)); if (plucSecret) LsaFreeMemory(plucSecret); return dwStatus; } int main(int argc, char* argv[]) { LSA_HANDLE hLSA = GetLSAPolicyHandle(NULL); WCHAR *wszName = L"L$WritingSecureCode"; WCHAR *wszSecret = L"My Secret Data!"; if (WriteLsaSecret(hLSA, wszSecret, wszName) == ERROR_SUCCESS) { WCHAR wszSecretRead[128]; if (ReadLsaSecret(hLSA,sizeof wszSecretRead / sizeof WCHAR, wszSecretRead,wszName) == ERROR_SUCCESS) wprintf(L"LSA Secret '%s' is '%s'\n",wszName,wszSecretRead); } if (hLSA) LsaClose(hLSA); return 0; }

This example code is also available with the book's sample files in the folder Secureco2\Chapter09\LSASecrets. You can delete an LSA secret by setting the last argument to LsaStorePrivateData NULL.

NOTE
Secrets protected by LSA can be viewed by local computer administrators using LSADUMP2.exe from BindView. The tool is available at http://razor.bindview.com/tools/desc/lsadump2_readme.html. Of course, an administrator can do anything!



Writing Secure Code
Writing Secure Code, Second Edition
ISBN: 0735617228
EAN: 2147483647
Year: 2001
Pages: 286

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net