A little over a year ago I set out to determine exactly why, prior to Window Vista, the Power Users security group was considered by most to be the equivalent of the Administrators group. I knew the answer lay in the fact that default Windows permissions allow the group to modify specific Registry keys and files that enable members of the group to elevate their privileges to that of the Local System or Administrators group, but I didn’t know of any concrete examples. I could have manually investigated the security on every file, directory and Registry key, but instead decided to write a utility, AccessChk, that would answer questions like this automatically. AccessChk quickly showed me directories, files, keys, and even Windows services written by third parties, that Power Users could modify to cause an elevation of privilege. I posted my findings in my blog post The Power in Power Users.
Since the posting, AccessChk has grown in popularity as a system security auditing tool that helps identify weak permissions problems. I’ve recently received requests from groups within Microsoft and elsewhere to extend its coverage of securable objects analyzed to include the Object Manager namespace (which stores named mutexes, semaphores and memory-mapped files), the Service Control Manager, and named pipes.
When I revisited the tool to add this support, I reran some of the same queries I had performed when I wrote the blog post, like seeing what system-global objects the Everyone and Users groups can modify. The ability to change those objects almost always indicates the ability for unprivileged users to compromise other accounts, elevate to system or administrative privilege, or prevent services or programs run by the system or other users from functioning. For example, if an unprivileged user can change an executable in the %programfiles% directory they might be able to cause another user to execute their code. Some applications include Windows services, so if a user could change the service executable they could obtain system privileges.
These local elevation-of-privilege and denial-of-service holes are unimportant on single-user systems where the user is an administrator, but on systems where a user expects to be secure when running as a standard user (like Windows Vista), and on shared computers like a family PCs that have unprivileged accounts, Terminal Server systems, and kiosk computers, they break down the security boundaries that Windows provides to separate unprivileged users from each other and from the system.
In my testing I executed AccessChk commands to look for potential security issues in each of the namespaces it supports. In the commands below, the -s option has AccessChk recurse a namespace, -w has it list only the objects for which the specified group – Everyone in the examples – has write access, and -u directs AccessChk to not report errors when it can’t query objects for which your account lacks permissions. The other switches indicate what namespace to examine, where the default is the file system.
File system: accesschk everyone -wsu “%programfiles%”
File system: accesschk everyone -wsu “%systemroot%”
Registry: accesschk everyone -kwsu hklm
Processes: accesschk everyone -pwu *
Named Objects: accesschk everyone -owu basenamedobjects
Services: accesschk everyone -cwu *
I ran similar commands looking for write access from the Authenticated Users and Users groups. An output line, which looks like “RW C:Program FilesVendor”, reveals a probable security flaw.
To my surprise and dismay, I found security holes in several namespaces. The security settings on one application’s global synchronization and memory mapping objects, as well as on its installation directory, allow unprivileged users to effectively shut off the application, corrupt its configuration files, and replace its executables to elevate to Local System privileges. What application has such grossly insecure permissions? Ironically, that of a top-tier security vendor.
For instance, AccessChk showed output that indicated the Users group has write access to the application’s configuration directory (note that names have been changed):
RW C:Program FilesSecurityVendorConfig
RW C:Program Files SecurityVendorConfigscanmaster.db
RW C:Program Files SecurityVendorConfigrealtimemaster.db
Because Malware would run in the Users group, it could modify the configuration data or create its own version and prevent the security software from changing it. It could also watch for dynamic updates to the files and reset their contents.
For the object namespace, it reported output lines like this:
RW [Section] basenamedobjects12345678-abcd-1234-cdef-123456789abc
RW [Mutant] basenamedobjects87654321-cdab-3124-efcd-6789abc12345
I executed handle searches in Process Explorer to determine which processes had these objects open and it reported those of the security software. Sections represent shared memory so it was likely that the security agent, running in user login sessions, was using it to communicate data to the security software’s service process that was running in the Local System account. Malware could therefore modify the contents of the memory, possibly triggering a bug in the service to that might allow the malware to obtain administrative rights. At the minimum it could manipulate the data to foil the communication.
“Mutant” is the internal name for Windows mutexes, and the security software’s service was using the mutex for synchronization. That means that malware could acquire the mutex and block forward progress by the service. There were more than few of these objects with wide-open security that could potentially be used to compromise or disable the security software.
In the wake of my discovery, I analyzed the rest of my systems, as well as trial versions of other popular security, game, ISP and consumer applications. A number of the most popular in each category had problems similar to those of the security software installed on my development system. I felt like I was shining a flashlight under a house and finding rotten beams where I had assumed there was a sturdy foundation. The security research community has focused its efforts uncovering local elevations via buffer overflows and unverified parameters, but has completely overlooked these obvious problems – problems often caused by the software of security ISVs, or in some cases, their own.
Why are these holes created? I can only speculate, but because allowing unprivileged groups write-access to global objects requires explicit override of secure defaults, my guess is that they are common in software that was originally written for Windows 9x or assumed a single administrative user. When faced with permissions issues that crop up when migrating to a version of Windows with security, or that occur when their software is run by standard user accounts, the software developers have taken the easy way out and essentially turned off security.
Regardless of the reason, it’s time for software vendors – especially those of security applications - to secure their software. If you discover insecure software on your system please file a bug with the publisher, and if you are a software developer please follow the guidance in "Writing Secure Code,” by Michael Howard and David LeBlanc.