Creating Temporary Files Securely

Creating Temporary Files Securely

UNIX has a long history of vulnerabilities caused by poor temporary file creation. To date there have been few in Windows, but that does not mean they do not exist. The following list describes some examples, which could happen in Windows also:

  • Linux-Mandrake MandrakeUpdate Race Condition vulnerability Files downloaded by the MandrakeUpdate application are stored in the poorly secured /tmp directory. An attacker might tamper with updated files before they are installed. More information is available at www.securityfocus.com/bid/1567.

  • XFree86 4.0.1 /tmp vulnerabilities Many /tmp issues reside in this bug. Most notably, temporary files are created using a somewhat predictable name, the process identity of the installation software. Hence, an attacker might tamper with the data before it is fully installed. More information is available at www.securityfocus.com/bid/1430.

A secure temporary file has three properties:

  • A unique name

  • A difficult-to-guess name

  • Good access control policies, which prevent malicious users from creating, changing, or viewing the contents of the file

When creating temporary files in Windows, you should use the system functions GetTempPath and GetTempFileName, rather than writing your own versions. Do not rely on the values held in either of the TMP or TEMP environment variables. Use GetTempPath to determine the temporary location.

These functions satisfy the first and third requirements because GetTempFileName can guarantee the name is unique and GetTempPath will usually create the temporary file in a directory owned by the user, with good ACLs. I say usually because services running as SYSTEM write to the system s temporary directory (usually C:\Temp), even if the service is impersonating the user. However, on Windows XP and later, the LocalService and NetworkService service accounts write temporary files to their own private temporary storage.

However, these two functions together do not guarantee that the filename will be difficult to guess. In fact, GetTempFileName creates unique filenames by incrementing an internal counter it s not hard to guess the next number!

note

GetTempFileName doesn t create a difficult-to-guess filename; it guarantees only that the filename is unique.

The following code is an example of how to create temporary files that meet requirements 1 and 2:

 #include <Windows.h> HANDLE CreateTempFile(LPCTSTR szPrefix) { // Get temp dir. TCHAR szDir[MAX_PATH]; if (GetTempPath(sizeof(szDir)/sizeof(TCHAR), szDir) == 0) return NULL; // Create unique temp file in temp dir. TCHAR szFileName[MAX_PATH]; if (!GetTempFileName(szDir, szPrefix, 0, szFileName)) return NULL; // Open temp file. HANDLE hTemp = CreateFile(szFileName, GENERIC_READ GENERIC_WRITE, 0, // Don t share. NULL, // Default security descriptor CREATE_ALWAYS, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED FILE_ATTRIBUTE_TEMPORARY FILE_FLAG_DELETE_ON_CLOSE, NULL); return hTemp == INVALID_HANDLE_VALUE ? NULL : hTemp; } int main() { BOOL fRet = FALSE; HANDLE h = CreateTempFile(TEXT( tmp )); if (h) { // // Do stuff with temp file. // CloseHandle(h); } return 0; }

This sample code is also available on the companion CD in the folder Secureco\Chapter 16\CreatTempFile. Notice the flags during the call to CreateFile. Table 16-1 explains why they are used when creating temporary files.

Table 16-1 CreateFile Flags Used When Creating Temporary Files

Flag

Comments

CREATE_ALWAYS

This option will always create the file. If the file already exists for example, if an attacker has attempted to create a race condition the attacker s file is destroyed, thereby reducing the probability of an attack.

FILE_ATTRIBUTE_NOT_CONTENT_INDEXED

The file will not be indexed by the content-indexing service. You don t want sensitive temporary data accidentally listed in searches!

FILE_ATTRIBUTE_TEMPORARY

This option can give the file a small performance boost by attempting to keep the data in memory.

FILE_FLAG_DELETE_ON_CLOSE

This option forces file deletion when the last handle to the file is closed. It is not 100 percent fail-safe because a system crash might not delete the file.

Once you have written data to the temporary file, you can call the MoveFile function to create the final file, based on the contents of the temporary data. This, of course, mandates that you do not use the FILE_FLAG_DELETE_ ON_CLOSE flag.

Finally, if you are truly paranoid and you want to satisfy the second requirement, you can make it more difficult for an attacker to guess the temporary filename by creating a random prefix for the filename. The following is a simple example using CryptoAPI. You can also find this code on the companion CD in the folder Secureco\Chapter 16\CreateRandomPrefix.

//CreateRandomPrefix.cpp #include <windows.h> #include <wincrypt.h> #define PREFIX_SIZE (3) DWORD GetRandomPrefix(TCHAR *szPrefix) { HCRYPTPROV hProv = NULL; DWORD dwErr = 0; TCHAR *szValues = TEXT( abcdefghijklmnopqrstuvwxyz0123456789 ); if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE) return GetLastError(); for (int i = 0; i < PREFIX_SIZE; i++) { DWORD dwTemp; CryptGenRandom(hProv, sizeof DWORD, (LPBYTE)&dwTemp); szPrefix[i] = szValues[dwTemp % lstrlen(szValues)]; } szPrefix[PREFIX_SIZE] = \0 ; if (hProv) CryptReleaseContext(hProv, 0); return dwErr; }



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