M2Team / Privexec

Run the program with the specified permission level (C++20 required)
MIT License
319 stars 52 forks source link

How to grant AppContainer capabilities? #31

Open forderud opened 3 years ago

forderud commented 3 years ago

I first want to thank you for sharing this project that makes it much easier to investigate AppContainer isolation on Windows! However, I am struggling to understand how to grant AppContainer capabilities like "removable media" ( WinCapabilityRemovableStorageSid), "internet client" (WinCapabilityInternetClientSid) and similar to my applications. Don't really understand why it doesn't work. See examples below.

I've already verified in Process Explorer that the enabled capabilities are correctly propagated to the security settings for the launched process. The problem therefore appear more fundamental somehow. Any clue about why this doesn't work?

Removable media example

image image image

Network access example

image image

STATUS UPDATE: Client-side socket connections will actually be enabled if using the WinSock API directly.

fcharlie commented 3 years ago

@forderud

Network access:
Ping.exe is an independent program. To execute it, cmd needs to be able to read the corresponding directory and be able to create processes.

forderud commented 3 years ago

Ping.exe is an independent program. To execute it, cmd needs to be able to read the corresponding directory and be able to create processes.

I don't think that is the problem here. Running ping.exe works fine, and will display the help page. Starting other in-built windows applications like notepad.exe also seem to work fine from the command prompt running within an AppContainer. The capabilities are then automatically propagated to the child processes.

fcharlie commented 3 years ago

@WildByDesign seems to be more experienced in this, can you help me answer with @forderud ?

forderud commented 3 years ago

Status update: I've just verified that the WinCapabilityInternetClientSid capability will actually enable client-side socket connections when using the WinSock API directly. The ping problem was therefore probably due to the special ICMP packets used by ping (or similar).

Still, my problem of gaining access to removable storage remain. Any suggestions on how to get this capability "working" would be highly appreciated.

WildByDesign commented 3 years ago

I tested out the removableStorage capability with all of my understanding and failed as well. There are some capabilities that work well and some (typically restricted capabilities) that do not work. Unfortunately, it seems that removableStorage is one that does not work.

The only work-around that I could find for successfully allowing your AppContainer sandboxed applications to access files on removable drives was to format the removable drives as NTFS and adding the group ALL APPLICATION PACKAGES to the DACLs on the files or folders.

Some icacls examples:

icacls "D:" /grant *S-1-15-2-2:(OI)(CI)(F) /T
icacls "D:" /grant *S-1-15-2-1:(OI)(CI)(F) /T

Those are based on the SIDs for "ALL RESTRICTED APPLICATION PACKAGES" (LPAC) and "ALL APPLICATION PACKAGES" respectively. Those commands would allow any and all programs running in AppContainer or LPAC to access.

Or you could be more specific and precise and only allow that one AppContainer to access based on it's own SID.

icacls "D:" /grant *S-1-15-2-3622619446-392274758-2533929289-2204876399-3375125215-4247762128-2478433618:(OI)(CI)(F) /T

Regarding the network question, I also had issues running ping and nslookup and other network tools from AppContainer sandbox. AppContainer blocks access to some lower level networking hardware by default. nslookup would work, but no luck with ping. I believe that you are right about being ICMP related. But from my limited searching this ping from AC issue seems to be a bug within the Windows OS itself which seems to still not be fixed. According to: https://github.com/dotnet/runtime/issues/21606#issuecomment-315474922 and https://github.com/dotnet/runtime/issues/21606#issuecomment-315475932

I apologize that I was not able to be of more help.

forderud commented 3 years ago

Thanks a lot for very helpful advise @WildByDesign . I hereby confirm being able to grant AppContainer access to selected NTFS folders. 👍

However, my application also need access to removable USB sticks, which are typically FAT32 formated. Any idea on how to achieve that?

WildByDesign commented 3 years ago

@forderud You're welcome. Unfortunately, I don't think that is possible to use some of these app capabilities from an "AppContainer Launcher" type of program. Some of these capabilities enforce the need for special certificates and are verified through RuntimeBroker.exe.

That would require the app to be packaged as a true UWP app or potentially packaging a regular desktop app into UWP via Desktop Bridge or whatever the name of the project from Microsoft is that deals with that. I don't have any experience with that at the moment. I am curious about it, for sure, but I have not yet had the time to learn more about it.

forderud commented 3 years ago

I understand @WildByDesign . This issue can then probably be closed, since my problems appear to be caused by Windows limitations, and not due to problems with the code in this repo.

WildByDesign commented 3 years ago

I have continued to do some research on this topic because I still have a lot of curiosity in figuring out which Capabilities work, which don't work, and most importantly, why they don't work. Many of these capabilities have become more locked down with each iteration of Windows 10 releases and the underlying AppModel/AppContainer capability structure.

For removableStorage (and also documentsLibrary, musicLibrary, picturesLibrary, etc.), it seems that they require more declarations in the Package.appxmanifest files which initialize apps. Those capabilities require declaring fileTypeAssociation and/or fileOpenPicker to specify which files types the app is allowed to access. Without these declarations, these capabilities wont work.

Example snippet from Package.appxmanifest file:

      <Extensions>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name=".jpg">
            <uap:SupportedFileTypes>
              <uap:FileType>.jpg</uap:FileType>
              <uap:FileType>.doc</uap:FileType>
              <uap:FileType>.ini</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileOpenPicker">
          <uap:FileOpenPicker>
            <uap:SupportedFileTypes>
              <uap:SupportsAnyFileType/>
            </uap:SupportedFileTypes>
          </uap:FileOpenPicker>
        </uap:Extension>
      </Extensions>

I don't know if Privexec/Appexec can support parsing this from the Package.appxmanifest file or, particularly, I don't know if an application launcher program such as Privexec/Appexec can initialize these declarations and launch an app with these declarations and capabilities functioning as intended. It may be required that apps that use these capabilities specifically be AppModel/UWP apps because there seems to be a lot of checks and balances in the system to determine this. I have tried so many tricks within the registry and such and all of my attempts to trick this has failed so far, unfortunately.

In the past few days, I have also tested some things with Visual Studio 2019 and it's Windows Application Packaging Project template that allows converting desktop apps (7-Zip, Notepad++, etc.) into AppModel/UWP apps. I also tested MSIX Packaging Tool for the same purpose. Both methods converted desktop apps into AppModel/UWP apps and both allowed for proper use of Capabilities and the necessary declarations. That was good. But the bad thing is that those desktop apps converted into AppModel/UWP apps do not (and cannot) run in AppContainer (Low IL) sandbox. Working capabilities, yes. AppContainer sandbox, no. So that defeated the purpose for me and I lost interest in that method.

So I am out of options at the moment but will continue researching this. I want to look into NtObjectManager (https://github.com/googleprojectzero/sandbox-attacksurface-analysis-tools) soon because the author of that PowerShell tool is the main sandbox genius behind Google Chrome.

Also, the most recent release of NtObjectManager (1.1.29) has some interesting things that I have not yet played around with:

  • Added proper enumeration of AppContainer profiles and support creating with capabilities.
  • Added Get-AppModelApplicationPolicy.
  • Added Start-AppModelApplication.

But I have no experience with PowerShell in general so my progress understanding NtObjectManager is slow.

WildByDesign commented 3 years ago

There might be a possible way to achieve this, but only on Windows 10 versions 2004, 20H2 and newer. Essentially, what we are lacking is a PackageIdentity in the process token.

PackageIdentity is what needs to be verified in process token and confirmed through AppModel system to allow many Capabilities and also lots of other features. It can allow traditional win32 apps to access UWP/WinRT/modern features and API.

Features that require package identity https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/modernize-packaged-apps

Identity, Registration and Activation of Non-packaged Win32 Apps https://blogs.windows.com/windowsdeveloper/2019/10/29/identity-registration-and-activation-of-non-packaged-win32-apps/

Activation via CreateProcess

The activation path for UWP applications today ensures the app has PackageIdentity in its process token. This is used by UWP APIs to identify the caller and refer to later – either to perform a callback or to look up state that was configured during deployment. Because of this requirement, calling CreateProcess() on a UWP exe will fail as the CreateProcess() pipeline was not enlightened about Identity. In order to support Sparse Packages with an External Location, we leverage the classic Win32 application.manifest to provide Identity in CreateProcess() scenarios.

At their core, these features are about providing a foundation for non-packaged Win32 processes to use our latest APIs and features.

Grant identity to non-packaged desktop apps https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/grant-identity-to-nonpackaged-apps

You can grant identity (PackageIdentity) to traditional win32 apps by creating what is called a Sparse Package to go along with your app. The Sparse Package is what does the verification with the system of your PackageIdentity and once verified by the system allows for the win32 app for accessing the additional UWP APIs, features, including Capabilities.

So while you can do this for a traditional win32 app successfully, I do not know how exactly this might work for a "app launcher" type of program like Privexec/AppExec. I don't understand it from a technical perspective. I don't know if that means that Privexec/AppExec would needs its own Sparse Package, or if any of the apps that it launches would also need their own Sparse Packages too.

Some additional reading:

Creating a sparse signed Win32 app package https://andrewleader.medium.com/creating-a-sparse-signed-win32-app-package-9809320cfaab

fcharlie commented 3 years ago

@WildByDesign Frankly, there's some hassle in simulating this process in AppExec or wsudo, and if users don't have a Windows SDK installed, which means they don't have MakeAppx.exe and MakeCert .exe on their computers, the first step is difficult to take.

The other thing is, I've been busy with other things lately and I don't have enough time to study this.

WildByDesign commented 3 years ago

@fcharlie I apologize, but I have made a mistake with regard to Sparse Packages. They cannot be run in AppContainer. They do register Package Identity, but unfortunately they cannot be used to run AppContainer.

Source: https://nicksnettravels.builttoroam.com/trust-identity-and-appcontainer-for-windows-apps/

Win32 with Sparse Package

Unpackaged Win32 application with package that has allowExternalContent set to true in the package manifest (referred to as a Sparse Package). Application needs to register the Sparse Package on first run (and subsequently unregister as part of clean up).

Integrity Level: Medium AppContainer: No Has Identity: Yes

Sorry for the inconvenience.

DrusTheAxe commented 1 year ago

but I have made a mistake with regard to Sparse Packages. They cannot be run in AppContainer.

https://nicksnettravels.builttoroam.com/trust-identity-and-appcontainer-for-windows-apps/ is incorrect (though the fault's really with the underlying blog post). The "Win32 with Sparse Package" case falsely assumes if a package has an External Location then the manifest'd application must have uap:RuntimeBehavior=win32app (and uap:TrustLevel=appContainer). That's incorrect - whether a package has an ExternalLocation and how its processes behave at runtime (RuntimeBehavior, TrustLevel etc) are independent matters.

See https://github.com/microsoft/WindowsAppSDK/discussions/2195 and https://github.com/microsoft/WindowsAppSDK/discussions/2195 for more information

fcharlie commented 1 year ago

but I have made a mistake with regard to Sparse Packages. They cannot be run in AppContainer.

https://nicksnettravels.builttoroam.com/trust-identity-and-appcontainer-for-windows-apps/ is incorrect (though the fault's really with the underlying blog post). The "Win32 with Sparse Package" case falsely assumes if a package has an External Location then the manifest'd application must have uap:RuntimeBehavior=win32app (and uap:TrustLevel=appContainer). That's incorrect - whether a package has an ExternalLocation and how its processes behave at runtime (RuntimeBehavior, TrustLevel etc) are independent matters.

See microsoft/WindowsAppSDK#2195 and microsoft/WindowsAppSDK#2195 for more information

Thank you, I will revisit this when I have time.

WildByDesign commented 1 year ago

@forderud I just came across this today. Link: https://github.com/microsoft/SandboxSecurityTools/tree/main/LaunchAppContainer

I haven’t tested it yet but I will later tonight. You have to specify Capabilities by their SIDs from what I can tell.

forderud commented 1 year ago

Thanks a lot for the tip @WildByDesign . Very nice to have some code from Microsoft on programmatic AppContainer process creation. 👍

I've just submitted https://github.com/microsoft/SandboxSecurityTools/pull/5 to allowing string-based capability names and https://github.com/microsoft/SandboxSecurityTools/issues/6 to ask how to grant removableStorage access. Crossing my fingers and hoping for some helpful feedback.

WildByDesign commented 1 year ago

You’re welcome. I was hoping that those capabilities would have worked, hoping that the Microsoft implementation may have had some sort of internal way to validate them. But unfortunately I was wrong in my assumptions there.

Your named capability commit there is a great addition there. I will keep my fingers crossed as well that they may provide an answer regarding removableStorage and other capabilities not working. An official Microsoft answer would be fantastic.

liumingedwin commented 6 months ago

Amazing solution. a special way to create an online-judge.