Why ACLs Are Important

Why ACLs Are Important

ACLs are quite literally your application s last backstop against an attack, with the possible exception of good encryption and key management. If an attacker can access a resource, his job is done.

important

Good ACLs are an incredibly important defensive mechanism. Use them.

Imagine you have some data held in the registry and the ACL on the registry key is Everyone (Full Control), which means anyone can do anything to the data, including read, write, or change the data or deny others access to the data. Look at the following code example, which reads the data from the registry key with the dangerous ACL:

#define MAX_BUFF (64) #define MY_VALUE "SomeData" BYTE bBuff[MAX_BUFF]; ZeroMemory(bBuff, MAX_BUFF); // Open the registry. HKEY hKey = NULL; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,                  "Software\\Northwindtraders",                  0,                  KEY_READ,                  &hKey) == ERROR_SUCCESS) {       // Determine how much data to read.       DWORD cbBuff = 0;       if (RegQueryValueEx(hKey,                           MY_VALUE,                           NULL,                           NULL,                           NULL,                           &cbBuff) == ERROR_SUCCESS) {           // Now read all the data.           if (RegQueryValueEx(hKey,                               MY_VALUE,                               NULL,                               NULL,                               bBuff,                               &cbBuff) == ERROR_SUCCESS) {               // Cool!               // We have read the data from the registry.           }       } } if (hKey)      RegCloseKey(hKey);

This code might look reasonable, but it s horribly flawed. The code incorrectly assumes that the data held in the registry is no bigger than 64 bytes in size. The first call to RegQueryValueEx reads the data size from the registry, and the second call to RegQueryValueEx reads into the local buffer as many bytes of data as were determined by the first call to RegQueryValueEx. A potential buffer overrun exists if this value is greater than 64 bytes.

How dangerous is this? First the code is bad and should be fixed. (I ll show you a fix in a moment.) The ACL on the registry key determines the threat potential. If the ACL is Everyone (Full Control), the threat is great because any user can set a buffer greater than 64 bytes on the registry key. Also, the attacker can set the ACL to Everyone (Deny Full Control), which will deny your application access to the data.

If the ACL is Administrators (Full Control) and Everyone (Read), the threat is less severe because only an administrator can set data on the key and change the ACL. Administrators have Full Control, which includes the ability to write an ACL, also called WRITE_DAC. All other users can only read the data. In other words, to force the sample application to fail, you need to be an administrator on the computer. If an attacker is already an administrator on the computer, this is only the start of your problems!

Does this mean that if you have good ACLs you can be a sloppy programmer? Not at all! If you need a reminder of why you must fix the code in this example, refer to the Defense in Depth section of Chapter 2, Designing Secure Systems. Let s look now at fixing the code.

A Diversion: Fixing the Registry Code

This section has nothing to do with ACLs, but because this is a book about code security, I thought I d round out the solution. The beginning of the solution is to write some code like this:

      // Determine how much data to read.       DWORD cbBuff = 0;       if (RegQueryValueEx(hKey,                           MY_VALUE,                           NULL,                           NULL,                           NULL,                           &cbBuff) == ERROR_SUCCESS) {             BYTE *pbBuff = new BYTE[cbBuff];             // Now read cbBuff bytes of data.              if (pbBuff && RegQueryValueEx(hKey,                                           MY_VALUE,                                           NULL,                                           NULL,                                           pbBuff,                                           &cbBuff) == ERROR_SUCCESS) {                 // Cool!                 // We have read the data from the registry.                 delete [] pbBuff;             }

This code still has a problem, but it s a different issue. In this case, the code allocates memory dynamically, based on the size of the data, and then reads the data from the registry. If an attacker can write 10 MB of data in the registry, because of a weak ACL she has now forced your application to allocate 10 MB of memory. Imagine the consequences if you do this tens or hundreds of times in your code or if the code is in some kind of loop. Your application could allocate hundreds of megabytes of data because the attacker is forcing the application to read 10 MB per read. Before long the application has run out of memory and the computer has ground to a halt as it pages memory in and out of the swap file.

Personally, the fix I d make is to use the following code:

BYTE bBuff[MAX_BUFF]; ZeroMemory(bBuff, MAX_BUFF); HKEY hKey = NULL; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,                  "Software\\Northwindtraders",                  0,                  KEY_READ,                  &hKey) == ERROR_SUCCESS) {       DWORD cbBuff = sizeof (bBuff);       // Now read no more than MAX_BUFF bytes of data.       if (RegQueryValueEx(hKey,                           MY_VALUE,                           NULL,                           NULL,                           bBuff,                           &cbBuff) == ERROR_SUCCESS) {             // Cool!             // We have read the data from the registry.       } } if (hKey)      RegCloseKey(hKey);

In this case, even if an attacker sets a large data value in the registry, the code will read up to MAX_BUFF bytes and no more. If there is more data, RegQueryValueEx will return an error, ERROR_MORE_DATA, indicating the buffer is not large enough to hold the data.

Once again, you can mitigate this threat by using good ACLs on the registry key in question, but you should still fix the code, just in case there s a poor ACL or the administrator accidentally sets a poor ACL. That s enough of a detour let s get back to ACLs.



Writing Secure Code
Writing Secure Code, Second Edition
ISBN: 0735617228
EAN: 2147483647
Year: 2005
Pages: 153

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