Recently, we have been conducting an analysis concerning the new Windows 8 security features. There are few documents available in Internet about this topic and no one of them explains the entire implementations in detail.

The paper has been divided in two parts because of the complexity of the topic. Microsoft engineers have done an impressive job by improving their Operating System security. They  implemented the so called “mitigations”. The term is used to indicate a new specific security feature that has the aim to make more difficult a possible attack.

There are several new Security mitigations: disabled Null Page allocation, Win32k System call mitigation, “Int 0x29” Security Assertions (on double linked list, GS cookie), Non-executable non paged pool, Intel SMEP technology, Intel Secure Key technology, and so on. The reader may find a lot of useful information on the following analysis paper done by MJ0011 (presented at Hitcon 2012 security conference): http://hitcon.org/2012/download/0720A5_360.MJ0011_Reversing Windows8-Interesting Features of Kernel Security.pdf

Despite the effectiveness of these mitigations, we think that the most important new characteristic is the  AppContainers sandbox. We will talk about it in this analysis.

Windows 8 Sandbox: AppContainer & Lowbox tokens

As the reader may know, the Google Chrome browser implements a great Sandbox for web pages environment, which, even if consumes a lot of system resources, it properly works: if an attacker finds a vulnerability and succeeds in his exploitation, he will get the machine control, but only in a sandboxed environment with minimal user rights and privileges. In this environment context, the attacker can do few operations: it is prevented to open a file, to read and write, to open another process. Basing on this idea, Microsoft has conducted a research and implemented its concept of Sandbox. The AppContainer and the Lowbox tokens have been thought to implement an OS Sandbox.

If you have ever developed a new Metro style application, you already know that a Metro app runs in a sandboxed context (AppContainer): if you deploy your app, you have to declare your app “Capabilities”. At present, Windows 8 defines only a small set of capabilities.

If, for instance, a Metro app was able to read and write the user documents, it should declare and enable the SECURITY_DOCUMENTS_LIBRARY capability in its manifest file. All this kind of requirements are documented in the MSDN for Metro-style applications.

All the Metro style applications run in a context of an AppContainer, with a Lowbox token. We are going now to analyse how this sandbox has been implemented for Metro application, and especially how Lowbox tokens are created, used and destroyed. We will try to extend the AppContainer model to all others standard Win32 executable too, even if Microsoft states that the Sandboxed environment is available only for new Metro style applications.

Metro Application VS2012 development environment – AppPackage Capabilities snapshot

AppPackage Capabilities snapshot

AppContainers Implementation

Brief introduction of Metro Apps  and new Start Menu

The new Metro style Start menu is managed entirely by the Explorer component. At start-up time, this Windows process decides if it has to create a new Start menu by doing the following check:

If the check returns TRUE, then Explorer will send a message to its other instances to properly show “Libraries” window (created and drew from a new Thread).

Otherwise it will start creating the Desktop, the Tray bar and finally the new “Immersive Launcher” start menu.

The new start menu is created registering a lot of Window classes (in our tests we have counted about 45 different classes). The creation process is quite entirely managed by SHDesktopMessageLoop  Shell32 routine. Analysing the creation and drawing modality of new Metro interface done by Explorer process is beyond the scope of this article. We would only like to highlight some essential implementation details:

  • Metro style interface management is implemented, in addition to the Explorer process, also in a lot of System libraries, like Shell32, ExplorerFrame and, the most important one, Twinui. The Explorer process depends on them.

  • The Explorer process deeply uses some MS technology, like COM+ and RPC, to communicate to other needed processes

  • The New Metro applications sandboxing and launching is administrated by the “BrokerInfrastructure” System service and by WWAHost process. Without these two components, all Metro applications could not execute. We are going to show how they interact with Explorer process.

When the user launches a Metro application, clicking his own tile in Start menu, Explorer sends an RPC message to the Broker service (that runs in “svchost.exe” process context). The broker service starts its job by checking RPC parameters and, if it is all ok, it impersonates RPC Security token (of Explorer process). Then it resolves target Metro application “AppPackage” information, and adds its security attributes to impersonation token (“WIN://SYSAPPID” attribute stores App Package Id, and “WIN://PKG” stores Package name). Each registered Metro application has indeed an AppPackage context, used to save a lot of information, as the application name, the version, the capabilities and so forth.

Now the token is ready to be transformed in an AppContainer. The new token will be called  Lowbox Token. The broker service may create also, if necessary, a new Lowbox token and starts WWAHost process with a particular command line used to communicate target Metro application DLL. Most of the default Metro applications are  indeed DLL libraries hosted by WWAHost process.

Process Explorer snapshot, showing Broker service that has launched “News”  Metro application in an AppContainer environment (WWAHost process

Process Explorer snapshot, showing Broker service that has launched “News”
Metro application in an AppContainer environment (WWAHost process

 

In the beginning was CreateProcess API

In this subsection we are going to describe entire AppContainer process token creation.

The broker service indeed exploits CreateProcessAsUser API to do actual token creation. This API is used when an application would like to launch a target process in another Security context (on behalf of another user or with an impersonation token). This system interface already existed in Windows 2000, but now, in Windows 8, its functionality has been improved.

Broker service indeed launches the WWAHost process specifying a new structure in CreateProcessAsUser tenth parameter: STARTUPINFOEX. According to MSDN documentation, this structure is defined as follow:

 

lpAttributeList is an opaque attribute list structure pointer. Microsoft has provided some subsidiary system procedures to create and update the list. The only official documentation existing is the one we proposed (except for some attributes documentation).The broker service includes only one attribute in list: PROC_THREAD_ATTRIBUTE_PACKAGE_FULL_NAME. Its value is a pointer to the full Metro application Package name.

Analysis of “CreateProcessAsUser” call

Analysis of “CreateProcessAsUser” call

CreateProcessAsUser is only a stub: it actually demands the entire work to its internal function CreateProcessInternalW. The latter begins with some parameters checks, it initializes its stack variables, and then it determines if EXTENDED_STARTUPINFO_PRESENT flag is present in dwCreationFlags parameter. If so, it uses BasepConvertWin32AttributeList to safely retrieve a copy of Package full name string. Then it continues processing each of the specified flags (we are not interested on details). If the package name is valid CreateProcessInternal verifies if g_bElevationPresent kernel32 symbol is set to 1: otherwise it tries to enable it with the aid of ApiSetQueryApiSetPresence function (this API seems to be able to load needed dependencies). All App Package information are retrieved thanks to BasepAppXExtension Kernel32 exported function. This is one of the key routines: its task is to open App Package and retrieve all information about it (like Capabilities, working directory and so on…). This is an internal OS function. Indeed it starts by checking the license tampering status, then it verifies the following condition:

  • AppContainer token creation must be done from a process living in logon Session 0 (System security context)

  • The calling process current token (primary or impersonation) must have SysAppId and Pkg Security attributes set

If one of these two conditions is not satisfied, then the procedure fails with a STATUS_NOT_SUPPORTED error.

Otherwise, the current token owner SID is retrieved (with GetTokenInformation Win32 API) and converted to string. This will be used to open the AppPackage registry key: AppXMiniRepository::OpenPackageKey internal function accepts the user SID string as a parameter, it builds the AppPackage registry key in the following way:

HKEY_USERS\<User SID>\Software\Classes\Local Settings\Software\Microsoft\Windows\ CurrentVersion\AppModel\Repository\Packages\<AppContPckName>

where:

  • “AppContPckName“ is the complete name of AppPackage (for example “Microsoft.BingNews_1.2.0.135_x64__8wekyb3d8bbwe”); this name will become the “Moniker”

  • “User SID“  is the SID of the user that owns the token impersonated by the Broker service

  • “HKEY_USERS\<User SID>“ is the link target of HKEY_CURRENT_USER key (indeed Broker service runs in System security context, and it has not the “CurrentUser” key mapped)

and it opens it.

Control returns to GetPackageInformationForCreateProcess procedure that obtains all the necessary information reading the App Package registry key values like “PackageRootFolder” (Metro application root folder), “PackageState”, “PackageSid” (AppContainer SID). Finally it parses each of the AppContainer capabilities, reading the “CapabilitySids” and the “CapabilityCount” registry values.

The App package state is verified and all its dependencies are loaded… If it all went right, BasepAppXExtension returns to caller (CreateProcessInternalW) with a structure containing all the necessary information:

  • App container SID and associated security capabilities

  • App Package name and full path

  • Dependency packages full path and names

A snap of “CreateProcessInternal” system routine code

A snap of “CreateProcessInternal” system routine code

Now the CreateProcessInternal jumps to the main user-mode internal routine that creates LowBox token: BasepCreateLowBox.

User-Mode LowBox Token Creation deep analysis

The Lowbox token creation begins in BasepCreateLowBox routine. Its prototype is the following:

 

First of all the parameters are checked: whether the original Token handle is NULL, the current process token is retrieved with the aid of NtOpenProcessToken native API; if the original token is already an AppContainer, then the token is checked and duplicated with BasepCreateTokenFromLowboxToken routine and finally the function exits.

In spite of we are now supposing, the majority of Lowbox token creation code is located  in user-mode. Indeed if the original token is not an AppContainer, and all the checks mentioned succeed, a lot of things happen: control is transferred to BasepCreateLowBoxObjectDirectories procedure. This one accepts as an input the App Container SID and the token handle. If routine succeeded, it returns the following output:

BasepCreateLowBoxObjectDirectories obtains the session ID from the original token, it converts App Container SID to string and it starts to build App container directory objects strings. Indeed each of the App Containers sandbox environments is based on Logon session boundaries. That’s why two identical App Containers can be in two different sessions.

“\Sessions\<ID>\BasedNamedObjects” directory is opened (where <ID> is token Session ID) with NtOpenDirectoryObject native API; its DACL is retrieved with the Original token owner user SID.

The App Container Security descriptor is built with BasepBuildPackageSecurityDescriptor, starting with obtained data. The Kernel32 module builds SID with the aid of Rtl (Runtime library) internal security functions (like RtlAllocateAndInitializeSid, RtlAddAce, RtlSetDaclSecurityDescriptor and so on…); we won’t provide here the details, we’ll only show the new SID. For further details, please contact me ([email protected]). The new SID is composed as follow:

  • All Access control entries of “\Sessions\<ID>\BasedNamedObjects”

  • Access allowed App Container SID ace – List, Add Object, Add Subdir, Delete, Read Control, Special authorization permissions

  • Access allowed App Container SID ace, Inherit only ACE – Delete, Query state and data, Modify state, Special authorization permissions

The code execution flows then it returns to the BasepCreateLowBoxObjectDirectories function. At this point the routine opens “\Sessions\<ID>\AppContainerNamedObjects” the directory object, and creates a subdirectory in it (exploiting NtCreateDirectoryObjectEx  native API) called as the App Container SID and protected by the Security descriptorjust created. From now we will call the latter directory on the App Container base directory. The directory is also protected with a Low integrity level ACE placed in its SACL by BasepSetKernelIntegrityLabel routine. BasepSetKernelIntegrityLabel exploits again  the Rtl* internal security functions to complete its job (in summary RtlAllocateAndInitializeSid builds the low level mandatory SID; an ACL is then built containing low level SID. RtlCreateSecurityDescriptor creates the Security descriptor that contains ACL. ACL indeed is tied to Security descriptor SACL with RtlSetSaclSecurityDescriptor routine; and finally NtSetSecurityObject sets target object security information).

 Snapshot of “News” Windows 8 Metro application App Container directories

Snapshot of “News” Windows 8 Metro application App Container directories

The process of the AppContainer directory object creation is repeated for “RPC Control” subdirectory object, starting from “\RPC Control” global directory… This time a lightly different low integrity Security descriptor (built again with BasepBuildPackageSecurityDescriptor routine) is applied from what we have seen above.

BasepCreateLowBoxSymbolicLinks routine is subsequently called: its job is to create “Global”, “Local” and “Session” symbolic link in the  App container base directory. It does so using NtCreateSymbolicLinkObject native API. The purpose of these links is the same as the non App Container counterparts.

The execution flow returns to BasepCreateLowBoxObjectDirectories which proceeds in AppContainer named pipe creation. This pipe is used in order to communicate with the Broker service and with the system management functions. It has the following name schema: “Sessions\<ID>\AppContainerNamedObjects\ <AppContainerSID>“. The named pipe is protected by the Security descriptor of AppContainer base directory with 3 additional ACEs:

  • All access allowed ACE granted to Administrators group

  • Generic read and generic execute access granted to Everyone group

  • Generic read and generic execute access granted to NT AUTHORITY\RESTRICTED

At this point the BasepCreateLowBoxObjectDirectories routine job is complete. Execution control is returned to BasepCreateLowBox  that now can actually create Lowbox token with the NtCreateLowBoxToken Kernel mode native API.

When the token is successfully created by the kernel-mode routine, the target process is created as usual but attached to the Lowbox token. Every object and resource that the new process is going to use, it will be placed in AppContainer directory instead of regular locations.

 

Kernel-Mode LowBox Token Creation deep analysis

The Kernel mode lowbox token creation starts in NtCreateLowBoxToken exported native API. As a user mode counterpart, the API accepts an original token, and transform it in a Lowbox one. This function only does what is absolutely necessary to access directly the Token object. The rest of the work is done in user-mode, as we have already seen. Indeed the procedure assumes that the AppContainer base directory, the symbolic links, the capabilities and all the package data is already retrieved.

Its function prototype is the following:

Now we are going to describe how the function works.

First of all, as usual, the parameters are checked and captured, and, whether the API is called form the user-mode, the memory is probed. The Current process security context is checked (primary or impersonating token is obtained with SeCaptureSubjectContext routine and analysed), and, if it all is ok, the original token kernel object is retrieved with ObReferenceObjectByHandle Kernel routine. The so called “capture process” checks specifically if App Container SID and each capability SID in array is valid (RtlIsPackageSid and RtlIsCapabilitySid verify the Sid size, the integrity, the package authority ID, and the sub-authority count).

Now begins the Lowbox token creation: SepDuplicateToken, as the name implies, creates a copy of the original token; we will call this copy “Lowbox” token. To  ? properly form Lowbox token, NtCreateLowBoxToken first setsthe  token mandatory policy to “No write up” (modifying “MandatoryPolicy” and “ModifiedId” Kernel Token structure data members; see here for an extensive description of Mandatory labels and policies). Then it exploits SepLocateTokenIntegrity routine to proper localize and set the token integrity level (stored in Token object as Group SID) value to Low (Rid value: 0x1000 – SECURITY_MANDATORY_LOW_RID).

The Privilege restriction takes place: all the token privileges are stripped except for SeChangeNotifyPrivilege and SeIncreaseWorkingSetPrivilege that later will be both disabled. SepSetTokenCapabilities procedure is called to attach each capability in array to Lowbox token: the Kernel token object has indeed three data member related to capabilities: “Capabilities”, “CapabilitiesCount” and “CapabilitiesHash”. All of these are updated by SepSetTokenCapabilities. Noteworthy is the hash value: RtlSidHashInitialize function initializes and updates the capabilities hash with the aim to hinder a possible external alteration and This makes the entire architecture quite secure.

When SepSetTokenCapabilities ends its job, the execution control is transferred to SepSetTokenLowboxNumber routine. It has to generate a local per-session Lowbox Token number, and to store it, together with the App Container SID and a Reference counter, in a per-session hash-table, indexed by the global kernel symbol “g_SessionLowboxArray” (stores hashes that points to SEP_LOWBOX_NUMBER_ENTRY structure). This way Windows kernel can fast(?) the lookup Lowbox tokens and Package SIDs based only on an AppContainer Number and Session ID. When the Lowbox number is correctly generated, an associated SEP_LOWBOX_NUMBER_ENTRY structure is created; the Kernel token object “LowboxNumberEntry” data member is updated to point (?) to the brand-new structure.

SepSetTokenLowboxHandles routine does quite the same work we have already seen for the token unique per-session number, but this time for the AppContainer directories and symbolic-links handles created by user-mode BasepCreateLowBoxObjectDirectories procedure, and delivered to the kernel API in lowBoxStruct parameter. A SEP_LOGON_SESSION_REFERENCES structure, that describes the current logon session, is obtained from the Lowbox token kernel object. In this structure is located the per-session Lowbox handles hash-table. This table indexes SEP_LOWBOX_HANDLES_ENTRY items. Each item stores an App Container SID, a reference counter and obviously the Lowbox handles table. SepGetLowBoxHandlesEntry adds and retrieves one item from hash-table, which SepSetTokenLowboxHandles compiles with a proper Lowbox data. This way, and with the same modality already seen, Windows kernel can fast(?)the lookup AppContainer handles table with only Package SID and session ID. Once it has finished, SepSetTokenLowboxHandles updates the Kernel token object “LowboxHandlesEntry” member with a pointer to brand-new SEP_LOWBOX_HANDLES_ENTRY data structure.

LowBox Kernel token object state after SepSetTokenLowboxHandles

LowBox Kernel token object state after SepSetTokenLowboxHandles

The Kernel Lowbox token creation job is quite ended: SepSetTokenPackage copies and sets App container package SID to the relative Token kernel object “Package” data member.

The Token object security context is modified: a full-access allowed ACE with AppContainer SID is added to the token default DACL. This way every object created under the Low-Box security context has by default all access granted by the App Container environment. Even the security descriptor that protects the Lowbox Token is modified:

  • A full-access allowed ACE to AppContainer SID is added

  • A TOKEN_QUERY access allowed ACE to built-in Administrator group is added

The lowbox token is therefore fully accessible only by Owner, SYSTEM account (entity inherited) and AppContainer environment. Administrators group can query only the Lowbox token.

The process is complete: ObInsertObjectEx validates and inserts Lowbox token into the Object manager namespace, and it returns an associated user-handle value (valid only for calling process). The Resources are freed and the execution control returns in user-mode.

Sandboxed Environment – What does it mean?

If you are here it means that you have understood the LowBox token creation and implementation. But there’s still a question that need to be answered:  How is a Sandbox environment managed? What about the other OS functionalities?

If the reader is curious he can try to understand Google Chrome Sandbox documentation, or maybe its source code.

An application launched under a LowBox token acts in a completely different way respect to a normal program:

  • First of all, the LowBox application can only read and write the directories, the files, and the objects that have an explicit ACE in their DACL, that allows the access to the AppContianer SID. Otherwise an ACCESS_DENIED error is returned (SeAccessCheck kernel routine implement this behaviour); even an Everyone access allowed ACE denies access to the object. It’s important to note that this assertion is totally true even for Windows registry. Our tests indeed have confirmed that no kind of Virtualization has been developed for AppContainer registry access

  • Every operation system component, whether detects that calling thread is under the Lowbox security context, checks if the token has the necessary capabilities to execute that particular block of code.

To identify properly an AppContainer security context and determine if the caller can require a particular System service, Windows OS executes the following pseudocode:

We made some tests to spot the different behaviour showed by standard Windows Win32 API if called from an AppContainer security context. We will see now how to launch the standard Win32 application under an AppContainer.

Our test done for INTERNET_CLIENT and PRIVATE_NETWORK_CLIENT_SERVER capabilities in network communications shows that this the capabilities checks code is implemented in network AFD kernel driver. Our Win32 application has tried to connect to the Internet and download a file, but it didn’t work without the associated enabled capabilities. The fact that the checks are implemented in Kernel mode makes the entire Sandbox much more powerful.

Unfortunately,  we did not identify where  the Capability check of the following Metro application code snippet is performed:

 

We have also tried to translate the above snippet in Win32 code, using the standard CreateFile API or some COM+ interfaces. The Results are the same: every attempt to open and read “Test.txt” file located in “User document” folder requires an explicit ACE attached to it, that allows access to AppContainer SID, even if DOCUMENTS_LIBRARY capability is enabled in the Lowbox token. Therefore, based on our quick analysis, it seems that this time Microsoft has implemented the Capability check code in mscorlib.dll Net framework main library. We don’t know why, maybe we didn’t take some aspect into consideration.

By the way understanding how every capability is checked in various operating System components can be definitively a good Research project. If some reader would like to investigate on this, please contact me ([email protected]).

Saferbytes Win32 Appcontainer applications

We have seen that to properly create a Lowbox token and to launch a Win32 application under a sandboxed environment, we have to do many things: to add the proper security attributes to the token, to create and modify the Package registry keys and, most important, we have to inject our code in a system service due to the session 0 isolation.

While analysing the CreateProcessInternalW internal function we found another way to launch an application under an AppContainer. The New STARTUPINFOEX structure can contain even an instance of PROC_THREAD_SECURITY_CAPABILITIES attribute. Therefore we have to define only an App Container SID and a list of capabilities that our AppContainer will have enabled (take a look at the documented SECURITY_CAPABILITIES structure). Unfortunately it is not so simple.

TokenExtCreateEnvironment kernel32 routine, that is called immediately when BasepCreateLowBox returns, lookups App Container “moniker” from system registry with the aim to create a sandboxed environment.

The AppContainerLookupMoniker retrieves the calling thread token User Sid, and together with the Lowbox package SID, opens the following registry key:

HKEY_USERS\<User SID>\Software\Classes\Local Settings\Software\Microsoft\Windows\ CurrentVersion\AppContainer\Mappings\<AppContSid>

Next it reads “Moniker” value. The moniker is the human readable App Container name. Moniker name is needed to create Sandboxed environment. Indeed TokenExtCreateEnvironment function creates the target application “Environment block” starting from system environment, but modifying the following  three variables:

  • “LocalAppData” is set to  “<original LocalAppData>\Packages\<Moniker name>\AC”

  • “Temp” and “Tmp”, are both set to “<original LocalAppData>\Packages\<Moniker name>\AC\Temp”

We can easily deduce that the folder locate in “c:\Users\<UserName>\AppData\Local\Packages\<Moniker name>” will become the main working path for the sandboxed environment (this is not a necessary condition however); and the registry key “HKCU\Software\Classes\Local Settings\Software\Microsoft\Windows\ CurrentVersion\AppContainer\Storage\<AppContSid>” will became the main working registry key. These two directories need a proper ACE to be correctly accessible as we have seen before (there are no exception from sandbox model)

So, in order to create an AppContainer sandbox for our Win32 application we acted as follows:

  1. Create “Moniker” registry key and append an Access allowed ACE with Lowbox package SID in its DACL

  2. Create sandbox main directory and registry key, and append a proper ACE as seen before

  3. Create and compile a proper SECURITY_CAPABILITIES structure containing App Container SID and all enabled capabilities

  4. Finally call CreateProcessAsUser Windows API

At the end, if it all has been done in the right way, the results are good, as showed in the picture below:

Our test application launched in a Sandbox environment

Our test application launched in a Sandbox environment

The picture shows even what we have already analysed: PRIVATE_NETWORK_CLIENT_SERVER capability allows our application to communicate with an external server, whereas DOCUMENTS_LIBRARY seems to not work.

Conclusions

Our analysis and tests show that Microsoft engineers have made a great job in creating a Sandboxed environment for their Operating System new applications type. We have seen that it’s possible to create an OS based sandboxed environments even for standard Win32 programs. The main problem is that there no documentation about it. We are wondering why MS doesn’t release a proper documentation about the AppContainer and the Lowbox tokens.

Furthermore we have concluded that in current OS implementation there are only few capabilities available. We hope that Microsoft could release a complete set of capabilities for each Operating system component in the next Windows 8.1 OS.

I developed a simple application able to define an AppContainer package, to create  a proper directories and objects, and to launch standard Win32 applications under an OS sandboxed environment.

We will release this in a few weeks, basing on the readers’ requests.

Snapshot of Saferbytes AppContainer launcher application

Snapshot of Saferbytes AppContainer launcher application

For today that’s all folks! We will review others Windows 8 Security capabilities in next part of analysis.

A quick note: according to Davide LeBlanc thoughts (thanks for the hint), we have to clarify that Microsoft has not been inspired by Google for its sandbox.
Reading developer’s blog post series about Sandbox, we can understand that there were some ideas regarding a software Sandbox at least starting from year 2008.