Gain an in-depth understanding of the controversial vulnerabilities between Google and Microsoft: NtApphelpCacheControl Vulnerability Analysis

Source: Internet
Author: User

Gain an in-depth understanding of the controversial vulnerabilities between Google and Microsoft: NtApphelpCacheControl Vulnerability Analysis

Cause:

James Forshaw, a new member of the Google Project Zero Team, submitted "Windows: Elevation of Privilege inahcache. sys/NtApphelpCacheControl "security issue. After Google's vulnerability publication deadline (90 days), that is, December 29, 2014 (January 1, December 30 Beijing Time), details of this issue were disclosed.

There are a lot of debates on this vulnerability. Many viewers are arguing about how Microsoft and Google treat security vulnerabilities, and whether the 90-day public policy is reasonable, many technical personnel are also arguing about whether this security issue is a strict Privilege Escalation Vulnerability. One of the main reasons for the latter is that James Forshaw used this vulnerability to hijack the ComputerDefaults program automatically elevation of permissions at the UAC default level, this allows you to silently start a high-level program from the integrity level under the default UAC settings.

Generally, Microsoft's security response center (MSRC) does not consider that UAC prompts with integrity levels to high integrity levels by default to bypass security vulnerabilities.

However, MSRC has recently introduced security issues that can penetrate the InternetExplorer protection mode (PM) or enhanced protection mode (PEM) sandbox (in fact, from low integrity level penetration to medium integrity level issues) fix as Security Vulnerabilities (such as CVE-2014-6349 ). Therefore, we first shelve the Security Vulnerability dispute and thoroughly analyze the principles and problems involved in this vulnerability.

Vulnerability analysis, causes, and Utilization

The basic cause of this vulnerability is that the simple description of Google has been quite accurate. In short, it is called by the NtApphelpCacheControl System. When the caller simulates the System permission, the caller's Token is not correctly identified, so that the interface originally provided only to the Administrator and system programs can be misused by low-Permission programs and the call mechanism can be used, hijacks high-Permission programs to improve permissions.

After reading this reason, you may have questions about what the system call is doing? What is Apphelp? What is the problem with Token determination? Which mechanism of Apphelp can be used and how can a high-permission process be hijacked? Next, I will introduce these content in depth and answer these questions in detail.

1. Apphelp and NtApphelpCacheControl

On Windows 8.1, NtApphelpCacheControl is a system call that can control the Apphelp rules in the system to cache data quickly.

Apphelp is a Compatibility solution introduced by Microsoft from the Windows XP operating system. Its official name is "Application Compatibility Database" (Application Compatibility Database ). This solution aims to reduce the operating system

Cost of backward compatibility, not at the operating system level, but through this compatible database engine to provide a large number of control functions including Shim (Hook, to identify and modify popular software programs with compatibility issues in real time, so that they can be compatible with new operating systems.

Microsoft officially introduced some functional documents starting from Windows 7. You can also use the official Microsoft Application Compatibility Toolkit (ACT ), you can view, modify, and add local compatibility databases on Windows 7 or later. Previously, Alex ionescu and some other domestic and foreign researchers have also studied compatibility databases and Shim mechanisms.

Various versions of the Microsoft operating system have accumulated a lot of methods and basic data for application compatibility modification, so that these applications can run smoothly in the new operating system, this plays an important role in the extensive operation and promotion of Microsoft's Operating Systems in complex environments around the world. After Windows Vista was released, it brought about a massive amount of innovation, but also caused compatibility problems in a large number of applications, which became one of the reasons for the system's criticism. To this end, in the subsequent Windows 7 operating system development process, Microsoft has paid more attention to and invested in application compatibility repair, not only collecting and compiling application compatibility repair rules more extensively, this compatibility mechanism has also been upgraded.

NtApphelpCacheControl is a new interface that supports this mechanism. This was not the first security vulnerability in the function. On the issue of Bochspwn on j00ru Syscan2013, a Race Condition Vulnerability (CVE-2013-1278) involving NtApphelpCacheControl in processing cache code was published ). While reading the following content, it is recommended that you take a look at the NtApphelpCacheControl-related content in this slides (75 ~ Page 94) and James's POC source code.

Why does Apphelp need this interface? This also needs to start from the XP system. The main database for application compatibility is actually stored in AppPatch \ sysmain under the Windows installation directory. in the sdb file, it is obviously too costly to check the data file every time the process is started or the module is loaded. To quickly handle the compatibility rules for these executable programs, you need to cache the database mechanism in the memory. In the Windows XP era, Apphelp uses a global shared Section named ShimSharedMemory to share and identify and modify the compatible data memory of executable programs between different processes.

Since Windows 2003, NtApphelpCacheControl is introduced into the system call. As the kernel entry of apphelp, ntapphelp provides a complete set of new application compatibility Database Retrieval and caching functions in the kernel, this allows applications to be isolated across sessions, and to quickly query and apply compatibility rules and solutions in the database. The cache function also minimizes performance consumption, quickly fix known programs with compatibility issues in the system.

In Windows, Windows Vista, Windows 7, and Windows 8 operating systems, NtApphelpCacheControl is implemented within the system kernel ntoskrnl. Starting from Windows, in order to reduce the upgrade cost, the kernel implements most of the calls of the system in a new kernel-mode driver ahcache. in sys, the system kernel sends a device control command to the driver to implement most of the functions of this interface. On the Windows 10 technical preview edition, we can see that this driver has undergone another major update.

The prototype of NtApphelpCacheControl is:

NTSTATUS NtApphelpCacheControl (APPHELPCOMMAND Command, PVOID CommandData );

This Command provides a series of functions for viewing, adding, and deleting application compatibility database caches. Among them, the Command enumeration function and the data structure of CommandData, J00ru topics and James's source code both provide some, but there are still many errors, you can easily see the implementation code through IDA. Here I will summarize the Command id, corresponding control code (applicable to Windows8.1), and corresponding functions of these functions and list them:

enum APPHELPCOMMAND{AppHelpCahceLookup,                //  IoControlCode: 0x220003*AppHelpCahceRemove,                //  IoControlCode:  0x220007*AppHelpCahceUpdate,                //  IoControlCode:  0x22000B*AppHelpCacheFlush                  //  IoControlCode: 0x22000F* AppHelpCacheDump,                  //  IoControlCode: 0x220013 AppHelpCacheNotifyStart ,          //  IoControlCode: 0x220017 AppHelpCacheNotifyStop,            //  IoControlCode: 0x22001BAppHelpCahceForward,               //  IoControlCode:  0x22001FAppHelpCacheQuery,                 //  IoControlCode: 0x220023AppHelpQueryModule,                //  IoControlCode: 0x220027AppHelpRefresh,                    //  IoControlCode: 0x22002BAppHelpCheckForChange,             //  IoControlCode: 0x22002FAppHelpQueryHwId,                  };

James defined the relevant structure in the source code, but it seems that he does not have a deep understanding of this structure. *: In James's POC source code, a 0 is missing for the four control codes.
 

 

AppHelpCacheLookup: searches for matched and processed records in Apphelp cache.

 

AppHelpCacheRemove: deletes matching Apphelp Cache records.

AppHelpCahceUpdate: insert records to Apphelp Cache

AppHelpCacheFlush: Flush AppHelp cache to clear the cache data of AppHelpCache (based on the Flush flag, the data in the memory may not be deleted, but some tags may be removed) and refreshed to the disk (Registry).

In James's source code, this command is useless AppHelpEnum. This is incorrect. apphelp! ShimFlushAppcompatCache-> kernelbase! BaseFlushAppcompatCache-> kernel32! BaseFlushAppcompatCacheWorker is still using this to clear shim compatible data. He may have missed out on AppHelCacheFlush. In the source code, there is a different number for the following parts of policystart \ Enum.

AppHelpCacheDump: this is a "useless" function. AppHelp will enumerate the data in the cache and will not perform any operations on the enumerated items. I guess this command is called "Dump", which may be a debugging function. So I found a checked build kernel in WDK. Indeed, in the checked build kernel, the elements in the cache will be enumerated, and records of file names to be matched will be printed one by one. In Free build, the corresponding code is removed, so it becomes a seemingly useless command. In actual checked build, microsoft developers may have corresponding tools to use this interface to conveniently observe the records in the cache.

AppHelpCacheNotifyStart/AppHelpCacheNotifyStop: These two commands are mainly used for service communication with AppHelp. The AppHelp kernel communicates with the Application Experience service through the ALPC Port \ AhcPort. These two commands are used to reconnect/Stop LPC communication of the same service.

AppHelpCacheForward: Used to queue information about the cache executable program and forward it to the Application Experience service for processing.

AppHelpCacheQuery: used to obtain data content, ShimCache statistics, and queues in the Shim Cache.

 

AppHelpQueryModule/AppHelpCacheRefresh/AppHelpCheckForChange/AppHelpQueryHwId.

 

The following describes the structure of an important data CommandBuffer in this call. The data in this structure drives most of the basic commands, such as Lookup, Remove, Update, and Forward.

The CommandBuffer structure (APPHELP_COMMANDDATA) is composed of three structs:

The first struct is used to store the entire shim cache and statistics, which is used by the AppHelpCacheQuery command;

The second struct is used to notify the API to retrieve, delete, and add project content when AppHelpCacheLookup/AppHelpCacheRemove/AppHelpCacheUpdate commands;

The third part is the AppHelpCacheForward command, which provides the forward Command to forward data to the service.

No matter which command, CommandBuffer contains three struct at the same time, this is also why the J00ru issue and James's source code both mentioned that a large amount of useless 0 data is in front of the submitted cache structure.

The following is the definition of this structure:

typedef struct APPHELP_COMMANDDATA{APPHELP_CACHE_QUERY QueryData;                  //Query full dataAPPHELP_CACHE_ENTRY EntryData ;                 //Lookup/Remove/Update entryAPPHELP_CACHE_FORWARD ForwardData;             //Data for forward} APPHELP_COMMANDDATA, *PAPPHELP_COMMANDDATA;

The structure of APPHELP_CACHE_QUERY/APPHELP_CACHE_FORWARD has nothing to do with this vulnerability, so it is left for interested readers to study.
 

 

It should be noted that the data length of QueryData will affect the subsequent EntryData (the length varies with Win7 \ Win8), while that of Win7 is 0 × 90, james provided 0 × 98 on Win8.1 (this is one of the reasons why the POC cannot work on win8.1 ). Take a look at ApphelpCacheControlValidateParameters or AhcValidateAndGetParameters.

 

Here we provide the APPHELP_CACHE_ENTRY data structure:

typedef struct APPHELP_CACHE_ENTRY{DWORD Flags ;ULONG CacheReturnFlags ;HANDLE FileHandle;HANDLE ProcessHandle ; //Only in Win8/Win8.1UNICODE_STRING FileName;UNICODE_STRING PackageFullName;    //only in Win8/Win8.1DWORD  DataBufferSize;PVOID DataBuffer;} APPHELP_CACHE_ENTRY, *PAPPHELP_CACHE_ENTRY;

FileHandle/FileName is the corresponding handle and file name of the executable program (including modules) to be processed. The file handle is provided because the kernel uses an AVL Table to store Entry data, use the FileTime of the file handle to index the Balance Tree. Among them, Flags/CacheReturnFlags indicate the functions and functions of the Cache, especially whether DataBufferSize/DataBuffer is effectively controlled and saved to the Registry during shutdown.
 

DataBufferSize and DataBuffer describe the content of Entry-related rule data.

ProcessHandle and PackageFullName are only used on Windows 8 and later operating systems.

DataBuffer can store the data structure stored by RING3. Generally, APPHELP_CACHEUPDATE is updated to the kernel cache. It is obtained by APPHELP_CACHELOOKUP and used by the Shim engine, my name is APPHELP_LOOKUP_RESULT (that is, the APPHELP_QUERY structure in James source code), as follows:

#define MAX_EXE_TAGS 16#define MAX_LAYER_TAGS 8typedef struct APPHELP_LOOKUP_RESULT{DWORD ExeTags[MAX_EXE_TAGS];DWORD ExeFlags[MAX_EXE_TAGS];DWORD LayerTags[MAX_LAYER_TAGS];DWORD LayerFlags;DWORD AppHelpTag;DWORD ExeTagsCount ;DWORD LayerTagsCount;GUID ExeGuid;DWORD Flags2;DWORD Unknown;DWORD Unknown2;GUID Guid2[16];};

 

As used in the James source code, ExeTags specifies the tag id of the solution in the sdb data. ExeTagsCount is the number of tags, up to 16, and LayerTags is the data of Layer rules.
 

Through these commands and data structures, we probably learned about the capabilities provided by NtAppHelpCacheControl. How does RING3 use it?

To put it simply, modules such as Module Loader of Ring3 call apphelp when events such as Module loading and process startup are triggered. related interfaces in dll, apphelp. the dll then calls the related APIs of BasepShim * In kernel32/kernelbase and queries whether the executable files of the module are in the cached data through the CacheLookup function in NtAppHelpCacheControl, if it exists, it will be processed according to the corresponding rules in the rule database. After the relevant data is sent to the service process through CacheForward, The CacheUpdate function will be called to cache the used data and speed up the secondary query.

Token Problems

After learning about the AppHelpCache interface and basic working principles, we can easily understand that if a program with low permissions can call the AppHelpCacheUpdate command to add a cache, it can hijack any high-Permission program, use the shim rule to modify the shim rule to improve the permission.

Let's take a look at the cause of this vulnerability, as James mentioned in his note. The cause of this vulnerability is to verify that AppHelpCacheUpdate runs the called AhcVerifyAdminContext function and verify that the Token has a problem, this function is simple. We use Hex-rays decomplier to get the pseudocode:

NTSTATUS AhcVerifyAdminContext(){  retstatus = STATUS_ACCESS_DENIED;  CurrentThread = KeGetCurrentThread();  CurrentProcess = PsGetCurrentProcess();  TokenType = 0;  TokenObj = PsReferenceImpersonationToken(CurrentThread, &CopyOnOpen, &EffectiveOnly, &ImpersonationLevel);  if ( TokenObj || (TokenObj = PsReferencePrimaryToken(CurrentProcess), TokenType = 1, TokenObj) )  {    if ( SeQueryInformationToken(TokenObj, 1, &TokenUserInformation) >= 0 )    {      if ( RtlEqualSid(_SeExports->SeLocalSystemSid, TokenUserInformation->User.Sid) || SeTokenIsAdmin(TokenObj) )      {        retstatus = STATUS_SUCCESS;      }      ExFreePoolWithTag(TokenUserInformation, 0);    }    else    {      AhcTracePrintf(0, "AhcVerifyAdminContext", 937, "Failed to query token information.\n", v5);    }    if ( TokenObj )    {      if ( TokenType == 1 )      {        PsDereferencePrimaryToken(TokenObj);            }      else      {        PsDereferenceImpersonationToken(TokenObj);      }    }  }  else  {    AhcTracePrintf(0, "AhcVerifyAdminContext", 929, "Failed to get effective token", v5);  }  return retstatus;}

 

The function is very simple. First, try to get the thread-simulated token. If the thread-simulated token does not exist, obtain the main token Object of the current process. After obtaining the token object, use SeQueryInformationToken (TokenUser) obtain the user information of the Token.
 

Next, if the following token object meets either of the following two conditions, STATUS_SUCCESS will be returned to allow the AppHelpCacheUpdate operation; otherwise, STATUS_ACCESS_DEIND will be returned to reject the operation:

 

1. the user SID of the Token matches the SID of LocalSystem.‍‍2. the Token is verified by SeTokenIsAdmin, that is, there is an enabled Adminsitrator group in the token user group.

So this comparison is what James said about verifying that the Token has a problem. The reason for the problem is as James said, because the ImpersonationLevel is not determined.

This is because the SID of the simulated Token does not determine that the Token actually has the right to the corresponding SID. For details, refer to Microsoft's MSDN explanation on SECURITY_IMPERSONATION_LEVEL.

The simulated tokens lower than SecurityImpersonation do not actually run in the security context of the simulated Client. Therefore, it is not enough to judge whether the caller has the LocalSystem permission by using the SID, the similar problem is that there are still many places in the Windows Kernel and kernel-mode drivers. Interested readers can explore some more.

Take the method of James source code as an example. After creating a download task through the BackgroundCopyManager interface of the Bits Service, the Code sets its own Notify y object as the notification interface of the task.

In this case, the service will call the corresponding object when downloading the notification, and then combase tries to call the interface function of the object through LPC callback. before calling the function, RpcImpersonateClient-> NtAlpcImpersonateClientOfPort will be used, alpcpImpersonateMessage prepares the security context specified by Alpc port for the callback interface.

Due to the allowed SecurityQos-> ImpersonationLevel simulation specified by the Bits OLE Port, after the simulation is completed, James's processing code is called. His code opens and saves the thread's token handle, A SecurityIdentification-Level Token handle is obtained. The Token is the security context of the Bits Service. Therefore, the SID of the Token is nt authority \ SYSTEM (LocalSystem)

 

Here, the Bits Service itself has no security issues, because the token obtained and simulated by ALPC is only at the SecurityIdentification level, even if the token is simulated (as James did after the Code ), it cannot work in the context of the System permission. Access to the object ACL is denied (refer to the implementation and judgment in SeAccessCheck ), it will not be recognized as admin/system (you can refer to the implementation of SeTokenIsAdmin in Windows 7 or later). However, NtAppHelpCacheControl only judges the Token SID mode, which leads to security check being bypassed, this vulnerability is also the root cause.

Exploitation of Vulnerabilities

Finally, find the sdb repository repaired by regsv32, and specify the DLL file of the High-permission access path in the startup command line. Then, regsvr32.exe will load the DLL we want to load at the high integrity level. What James's DLL Code implements is to start a calculator program.

This method has caused some controversy. Many people think that this only proves that it can bypass the pop-up box with the integrity level to the high integrity level under the UAC default level. Generally, it cannot be said that it is a security vulnerability, in addition, there have been a lot of open techniques to bypass UAC prompts.

As James said, The UAC bypass is only a convenient demonstration method. If you think about it, you can find that there are more ways to exploit this vulnerability.

Taking the sandbox (PM) of IE11 as an example, the related features required for this vulnerability (including the acquisition of BITS Token, the call of NtAppHelpCacheControl, and the acquisition of sdb tags) they can all be executed under the low integrity level of the IE11 sandbox, so once Malicious Code enters the sandbox, this vulnerability can be exploited to hijack a common medium-Integrity-level Program (or even a high-integrity, system-Integrity-level program that is often started in the system). This vulnerability may penetrate through the sandbox, execute Malicious Code outside the sandbox. After setting the Low integrity level for the test program using icacls.exe/setintegritylevel, this can be easily confirmed.

Even if an Administrator account is logged on through the Users user group account at the same time or later, because the AppHelp Cache is globally cross-Session, therefore, programs run by the Administrator may be affected by hijacking and the permissions may be elevated.

These attacks can be completed through James's test program, but one disadvantage of this attack is that a program with high permissions must be started. Is there a better way to use it?

Yes. You can see the AppHelpCacheFlush function we just introduced. The caller verification for this interface also has the same problems as AppHelpCacheUpdate, through this interface, you can directly refresh the added AppHelpCache in the memory to the Registry (AppCompatCache under HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Session Manager \ AppCompatCache ), in this way, the added rules will be loaded and applied at the next boot, so that the programs to be hijacked can be hijacked more easily after the restart.

 

At the same time, by calling some LPC/COM interfaces that are allowed to be called under low-integrity/low-Permission accounts or AppContainer integrity levels, you can also enable specific high-Permission programs, and may be hijacked.

These low-level technologies have already provided so many Tips, and the specific method requires imagination. Finally, let's take a look at the details: AppHelp rules can not only be applied to the creation of EXE processes, you can also load an application to any specified module.

Windows 7 Problems

James mentioned the problem of Windows 7 in the description. On Windows 7, the AppHelpCacheUpdate command is specially protected by a special ApphelpCacheVerifyContext check (for other interfaces protected, ApphelpCacheVerifyAdminContext, this vulnerability exists in the same way as Windows 8/8.1). This check is more rigorous and can only be passed when the primary TOKEN has the TCB privilege. The Code is as follows:

NTSTATUS ApphelpCacheVerifyContext(){  status = STATUS_SUCCESS;  if ( PsGetCurrentThreadPreviousMode() && SeSinglePrivilegeCheck(SeTcbPrivilege, UserMode)  == FALSE)    status = STATUS_ACCESS_DENIED;  return status;}
 

It seems that this check function cannot be bypassed. James also mentioned that this check will only be performed when some Flags in CommandBuffer match, maybe it can be bypassed. What is the actual situation?
 

We know from the implementation of NtAppHelpCacheControl on Win7 that this check is not performed when Bit 2 and 3 of CommandBuffer-> Flags are 1, this Entry can be added to the cache through the AppHelpCacheUpdate check.

However, when we look at the implementation of AppHelpCacheLookup, it is not difficult to find that, only when the entry-> Flags bit 0 is 1, Lookup returns CommandBuffer-> DataBuffer and DataBufferSize for the caller, as mentioned in section 1, these two fields describe the APPHELP_LOOKUP_RESULT data structure. Without this data, we cannot specify the rules to be applied.

Therefore, at least according to the current analysis, we cannot modify the Flags method to add our Hijacking data to the cache and take effect, currently, this vulnerability cannot be exploited on Windows 7.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.