aboutsummaryrefslogtreecommitdiff
path: root/src/burn/engine/cache.cpp
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2024-03-20 23:51:53 -0700
committerRob Mensching <rob@firegiant.com>2024-03-22 11:57:27 -0700
commitfed3d69eb4da7fa2bafdd8f555ce5869c36925f7 (patch)
treecb9bd56e7a36f118da7ad44107018b86a30fbdae /src/burn/engine/cache.cpp
parente84b6768772c01e44dd55fb583cf78388ec7e48a (diff)
downloadwix-fed3d69eb4da7fa2bafdd8f555ce5869c36925f7.tar.gz
wix-fed3d69eb4da7fa2bafdd8f555ce5869c36925f7.tar.bz2
wix-fed3d69eb4da7fa2bafdd8f555ce5869c36925f7.zip
Protect elevated working folder from malicious data
When running elevated, Burn uses the Windows Temp folder as its working folder to prevent normal processes from tampering with the files. Windows Temp does allow non-elevated processes to write to the folder but they cannot see the files there. Unfortunately, contrary to our belief, non-elevated processes can read the files in Windows Temp by watching for directory changes. This allows a malicious process to lie in wait, watching the Windows Temp folder until a Burn process is launched elevated, then attack the working folder. Mitigate that attack by protecting the working folder to only elevated users. Managed custom actions also fall back to using the Windows Temp folder in some cases and thus can be exposed in a similar fashion as an elevated Burn process. Remove that possibility.
Diffstat (limited to 'src/burn/engine/cache.cpp')
-rw-r--r--src/burn/engine/cache.cpp32
1 files changed, 29 insertions, 3 deletions
diff --git a/src/burn/engine/cache.cpp b/src/burn/engine/cache.cpp
index c0ac3ecd..358327a2 100644
--- a/src/burn/engine/cache.cpp
+++ b/src/burn/engine/cache.cpp
@@ -106,6 +106,7 @@ static HRESULT SecurePath(
106 __in LPCWSTR wzPath 106 __in LPCWSTR wzPath
107 ); 107 );
108static HRESULT CopyEngineToWorkingFolder( 108static HRESULT CopyEngineToWorkingFolder(
109 __in BOOL fElevated,
109 __in BURN_CACHE* pCache, 110 __in BURN_CACHE* pCache,
110 __in_z LPCWSTR wzSourcePath, 111 __in_z LPCWSTR wzSourcePath,
111 __in_z LPCWSTR wzWorkingFolderName, 112 __in_z LPCWSTR wzWorkingFolderName,
@@ -330,6 +331,7 @@ LExit:
330} 331}
331 332
332extern "C" HRESULT CacheEnsureBaseWorkingFolder( 333extern "C" HRESULT CacheEnsureBaseWorkingFolder(
334 __in BOOL fElevated,
333 __in BURN_CACHE* pCache, 335 __in BURN_CACHE* pCache,
334 __deref_out_z_opt LPWSTR* psczBaseWorkingFolder 336 __deref_out_z_opt LPWSTR* psczBaseWorkingFolder
335 ) 337 )
@@ -338,15 +340,32 @@ extern "C" HRESULT CacheEnsureBaseWorkingFolder(
338 340
339 HRESULT hr = S_OK; 341 HRESULT hr = S_OK;
340 LPWSTR sczPotential = NULL; 342 LPWSTR sczPotential = NULL;
343 PSECURITY_DESCRIPTOR psd = NULL;
344 LPSECURITY_ATTRIBUTES pWorkingFolderAcl = NULL;
341 345
342 if (!pCache->fInitializedBaseWorkingFolder) 346 if (!pCache->fInitializedBaseWorkingFolder)
343 { 347 {
348 // If elevated, allocate the pWorkingFolderAcl to protect the working folder to only SYSTEM and Admins.
349 if (fElevated)
350 {
351 LPCWSTR wzSddl = L"D:PAI(A;;FA;;;BA)(A;OICIIO;GA;;;BA)(A;;FA;;;SY)(A;OICIIO;GA;;;SY)";
352 if (!::ConvertStringSecurityDescriptorToSecurityDescriptorW(wzSddl, SDDL_REVISION_1, &psd, NULL))
353 {
354 ExitWithLastError(hr, "Failed to create the security descriptor for the working folder.");
355 }
356
357 pWorkingFolderAcl = reinterpret_cast<LPSECURITY_ATTRIBUTES>(MemAlloc(sizeof(SECURITY_ATTRIBUTES), TRUE));
358 pWorkingFolderAcl->nLength = sizeof(SECURITY_ATTRIBUTES);
359 pWorkingFolderAcl->lpSecurityDescriptor = psd;
360 pWorkingFolderAcl->bInheritHandle = FALSE;
361 }
362
344 for (DWORD i = 0; i < pCache->cPotentialBaseWorkingFolders; ++i) 363 for (DWORD i = 0; i < pCache->cPotentialBaseWorkingFolders; ++i)
345 { 364 {
346 hr = PathConcatRelativeToFullyQualifiedBase(pCache->rgsczPotentialBaseWorkingFolders[i], pCache->wzGuid, &sczPotential); 365 hr = PathConcatRelativeToFullyQualifiedBase(pCache->rgsczPotentialBaseWorkingFolders[i], pCache->wzGuid, &sczPotential);
347 if (SUCCEEDED(hr)) 366 if (SUCCEEDED(hr))
348 { 367 {
349 hr = DirEnsureExists(sczPotential, NULL); 368 hr = DirEnsureExists(sczPotential, pWorkingFolderAcl);
350 if (SUCCEEDED(hr)) 369 if (SUCCEEDED(hr))
351 { 370 {
352 pCache->sczBaseWorkingFolder = sczPotential; 371 pCache->sczBaseWorkingFolder = sczPotential;
@@ -373,6 +392,11 @@ extern "C" HRESULT CacheEnsureBaseWorkingFolder(
373 } 392 }
374 393
375LExit: 394LExit:
395 ReleaseMem(pWorkingFolderAcl);
396 if (psd)
397 {
398 ::LocalFree(psd);
399 }
376 ReleaseStr(sczPotential); 400 ReleaseStr(sczPotential);
377 401
378 return hr; 402 return hr;
@@ -888,6 +912,7 @@ extern "C" HRESULT CachePreparePackage(
888} 912}
889 913
890extern "C" HRESULT CacheBundleToWorkingDirectory( 914extern "C" HRESULT CacheBundleToWorkingDirectory(
915 __in BOOL fElevated,
891 __in BURN_CACHE* pCache, 916 __in BURN_CACHE* pCache,
892 __in_z LPCWSTR wzExecutableName, 917 __in_z LPCWSTR wzExecutableName,
893 __in BURN_SECTION* pSection, 918 __in BURN_SECTION* pSection,
@@ -912,7 +937,7 @@ extern "C" HRESULT CacheBundleToWorkingDirectory(
912 } 937 }
913 else // otherwise, carry on putting the bundle in the working folder. 938 else // otherwise, carry on putting the bundle in the working folder.
914 { 939 {
915 hr = CopyEngineToWorkingFolder(pCache, sczSourcePath, BUNDLE_WORKING_FOLDER_NAME, wzExecutableName, pSection, psczEngineWorkingPath); 940 hr = CopyEngineToWorkingFolder(fElevated, pCache, sczSourcePath, BUNDLE_WORKING_FOLDER_NAME, wzExecutableName, pSection, psczEngineWorkingPath);
916 ExitOnFailure(hr, "Failed to copy engine to working folder."); 941 ExitOnFailure(hr, "Failed to copy engine to working folder.");
917 } 942 }
918 943
@@ -2063,6 +2088,7 @@ LExit:
2063 2088
2064 2089
2065static HRESULT CopyEngineToWorkingFolder( 2090static HRESULT CopyEngineToWorkingFolder(
2091 __in BOOL fElevated,
2066 __in BURN_CACHE* pCache, 2092 __in BURN_CACHE* pCache,
2067 __in_z LPCWSTR wzSourcePath, 2093 __in_z LPCWSTR wzSourcePath,
2068 __in_z LPCWSTR wzWorkingFolderName, 2094 __in_z LPCWSTR wzWorkingFolderName,
@@ -2079,7 +2105,7 @@ static HRESULT CopyEngineToWorkingFolder(
2079 LPWSTR sczPayloadSourcePath = NULL; 2105 LPWSTR sczPayloadSourcePath = NULL;
2080 LPWSTR sczPayloadTargetPath = NULL; 2106 LPWSTR sczPayloadTargetPath = NULL;
2081 2107
2082 hr = CacheEnsureBaseWorkingFolder(pCache, &sczWorkingFolder); 2108 hr = CacheEnsureBaseWorkingFolder(fElevated, pCache, &sczWorkingFolder);
2083 ExitOnFailure(hr, "Failed to create working path to copy engine."); 2109 ExitOnFailure(hr, "Failed to create working path to copy engine.");
2084 2110
2085 hr = PathConcatRelativeToFullyQualifiedBase(sczWorkingFolder, wzWorkingFolderName, &sczTargetDirectory); 2111 hr = PathConcatRelativeToFullyQualifiedBase(sczWorkingFolder, wzWorkingFolderName, &sczTargetDirectory);