diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index 49cb0a6387..0dd2764c50 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -1,542 +1,545 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 97a2e87097..25d4e8f70c 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -34,6 +34,8 @@ #include #include #include +#include +#include #endif #include "OSUtils.hpp" @@ -265,6 +267,29 @@ void OSUtils::lockDownFile(const char* path, bool isDir) #endif } +void OSUtils::secureDirectory(const char* path) +{ +#ifdef __WINDOWS__ + // Apply a protected (non-inheriting) DACL so standard users cannot create or modify + // files in this directory: SYSTEM full, Administrators modify, Everyone read+execute, + // inheritable to child files/subdirs. PROTECTED_DACL_SECURITY_INFORMATION strips any + // inherited ACE (e.g. the ProgramData 'Users:(create files)' grant that enables the + // DLL-planting LPE). Re-asserted on every service start, so it remediates upgrades and + // pre-existing installs the MSI does not re-secure. Mirrors the installer One_Dir SDDL. + PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)0; + if (ConvertStringSecurityDescriptorToSecurityDescriptorA("D:PAR(A;OICI;FA;;;SY)(A;OICI;0x1301bf;;;BA)(A;OICI;0x1200a9;;;WD)", SDDL_REVISION_1, &sd, (PULONG)0)) { + BOOL daclPresent = FALSE, daclDefaulted = FALSE; + PACL dacl = (PACL)0; + if ((GetSecurityDescriptorDacl(sd, &daclPresent, &dacl, &daclDefaulted)) && (daclPresent)) { + SetNamedSecurityInfoA((LPSTR)path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, (PSID)0, (PSID)0, dacl, (PACL)0); + } + LocalFree(sd); + } +#else + (void)path; +#endif +} + uint64_t OSUtils::getLastModified(const char* path) { struct stat s; diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index 5c3eb7f33a..5cd6b4cef9 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -178,6 +178,18 @@ class OSUtils { */ static void lockDownFile(const char* path, bool isDir); + /** + * Apply a hardened, protected ACL to a directory (Windows; no-op elsewhere) + * + * Sets an explicit, non-inheriting DACL granting full control to SYSTEM, modify to + * Administrators, and read+execute to Everyone. Re-asserting this at service startup + * closes the DLL-planting privilege-escalation class on hosts where the installer did + * not (re)secure a pre-existing working directory. + * + * @param path Directory to secure + */ + static void secureDirectory(const char* path); + /** * Get file last modification time * diff --git a/service/OneService.cpp b/service/OneService.cpp index d5d086058e..fdb1520d8a 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1114,6 +1114,10 @@ class OneServiceImpl : public OneService { virtual ReasonForTermination run() { try { + // Re-assert the protected working-directory ACL on every start. The MSI does not + // re-secure a pre-existing directory, so a host upgraded from a vulnerable build + // would otherwise keep the bad ACL. No-op on non-Windows. + OSUtils::secureDirectory(_homePath.c_str()); { const std::string authTokenPath(_homePath + ZT_PATH_SEPARATOR_S "authtoken.secret"); if (! OSUtils::readFile(authTokenPath.c_str(), _authToken)) {