Closed Bug 1560695 Opened 5 years ago Closed 5 years ago

insufficient check for symlink attack in Mozilla Maintenance Service lead to privilege escalation (to System)

Categories

(Toolkit :: Application Update, defect)

defect
Not set
normal

Tracking

()

RESOLVED DUPLICATE of bug 1552206

People

(Reporter: diff, Unassigned)

References

()

Details

(Whiteboard: [reporter-external] [client-bounty-form] [verif?])

Attachments

(1 file)

Attached file firefox_eop.zip

Test:

  • Firefox 67.0.4 64-bits
  • Windows 10 Pro x64 1089

Description:
Mozilla maintenance service provides some service commands which can be callable from non-admin users.
One of the commands, "fix-update-directory-perms", is responsible for fixing permissions of both of files and sub-folders within its update related folder("C:\ProgramData\Mozilla") so that any users can have full access to those files and folders.

There is a TOCTOU when the service handles "fix-update-directory-perms". Exploiting this bug it's possible for non-admin users(in "Users" group) to have full access to all files within an arbitrary directory.

Looking into |SetUpdateDirectoryPermissions| below, we can find out that there's timing window [A] ~ [B] to win the race. If creating a symlink ("C:\ProgramData\Mozilla" -> target folder) is possible during between [A] and [B], the permissions of all files in the target folder are changed so that any user can have "FILE_ALL_ACCESS" permission for those files.

This is code snippet for explaining the bug.

// toolkit/mozapps/update/common/commonupdatedir.cpp

static HRESULT SetUpdateDirectoryPermissions(
const SimpleAutoString& basePath, // C:\ProgramData\Mozilla
const SimpleAutoString& updatePath,
bool fullUpdatePath, // true
SetPermissionsOf permsToSet // SetPermissionsOf::AllFilesAndDirs
)
{
...

DWORD attributes = GetFileAttributesW(basePath.String()); // file attributes of "C:\ProgramData\Mozilla"

///////////////////// [A] ////////////////////////

// 1) validBaseDir is true if it is a directory and not a symlink.
bool validBaseDir = attributes != INVALID_FILE_ATTRIBUTES &&
attributes & FILE_ATTRIBUTE_DIRECTORY &&
!(attributes & FILE_ATTRIBUTE_REPARSE_POINT);

...
// 2) generate DACL indicating that "Users" group own FILE_ALL_ACCESS
HRESULT hrv = GeneratePermissions(perms);
...

// 3) [*] Time-of-Check
if (!validBaseDir) {
MoveConflicting(basePath);
BOOL success = CreateDirectoryW(basePath.String(), &perms.securityAttributes);
...
}

if (fullUpdatePath) {
...
// 4) step into
hrv = SetPermissionsOfContents(basePath, leafDirPath, perms);
}

static HRESULT SetPermissionsOfContents(
const SimpleAutoString& basePath, // "C:\ProgramData\Mozilla"
const SimpleAutoString& leafUpdateDir,
const AutoPerms& perms) {

///////////////////// [B] ////////////////////////

DIR directoryHandle(basePath.String()); // 5) [*] Time-Of-Use
errno = 0;

for (dirent* entry = readdir(&directoryHandle); entry; entry = readdir(&directoryHandle)) {
if (wcscmp(entry->d_name, L".") == 0 || wcscmp(entry->d_name, L"..") == 0) {
continue;
}

pathBuffer.AssignSprintf(MAX_PATH + 1, L"%s\\%s", basePath.String(),  entry->d_name);
...
HRESULT hrv = SetPathPerms(pathBuffer, perms);     // 6) Set file permissions (FILE_ALL_ACCESS to users)
...

} // for loop
...
}

PoC:
I've attached a proof of concept, it's written in C.

  1. First, Open .sln with Visual Studio and build it.
  2. Make sure that firefox_eop.exe and CreateMountPoint.exe(which written by james forshaw) are in the same folder.
  3. open cmd.exe
  4. in cmd, cd to dir where firefox_eop.exe is located in.
  5. Run firefox_eop.exe in cmd (Note that You need to run this on a multi-core machine to win the race.)

PoC tries to modify the permissions of the PrintConfig.dll so that Users group have full access to the PrintConfig.dll using this vuln.

You should see the output like below

C:\Users\diff\Desktop>firefox_eop.exe
c:\windows\system32\DriverStore\FileRepository\prnms003.inf_amd64_a337db27fa50b915\Amd64\PrintConfig.dll NT SERVICE\TrustedInstaller:(F)
BUILTIN\Administrators:(RX)
NT AUTHORITY\SYSTEM:(F)
BUILTIN\Users:(RX) <-------- original permission
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(RX)

Done.

c:\windows\system32\DriverStore\FileRepository\prnms003.inf_amd64_a337db27fa50b915\Amd64\PrintConfig.dll APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(OI)(CI)(Rc,RD,REA,WEA)
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(CI)(IO)(GR)
BUILTIN\Users:(F) <--------- permission changed.
BUILTIN\Administrators:(F)
NT AUTHORITY\SYSTEM:(F)

Flags: sec-bounty?
Type: task → defect
Component: Security → Application Update
Product: Firefox → Toolkit

Matt, can you take a look at this? Thanks.

Flags: needinfo?(mhowell)
Flags: needinfo?(mhowell) → needinfo?(ksteuber)
Status: UNCONFIRMED → RESOLVED
Closed: 5 years ago
Flags: needinfo?(ksteuber)
Resolution: --- → DUPLICATE
Flags: sec-bounty? → sec-bounty-
Group: firefox-core-security
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: