It seems that starting with Windows Vista, processes with a lower integrity level (IL) cannot send messages to processes with higher integrity levels. This makes sense from a security standpoint, but it breaks some of our interprocess communication.
We have a legacy application (Process A) that unfortunately has to run with elevated "admin" privileges (accomplished by setting its shortcut to always run as administrator). At times it needs to instantiate a separate application (Process B). As a result, Process B inherits the same elevated privileges (and IL) as Process A. Therein lies the problem. There might be other independent instances of Process B that do not have elevated privileges, and all of these Process B instances need to be able to send messages to each other. This obviously fails if one instance of Process B is elevated and another is not.
I know we can open holes in the UIPI message filter using the ChangeWindowMessageFilter
API method, but this doesn't seem like the ideal solution. Instead, I would much rather have Process A spawn Process B with reduced privileges, specifically so that it can communicate with the other Process B instances. I think by default the other Process B instances run at the "Medium" IL, so therefore I'd like Process A to spawn Process B instances with this same IL.
My searches have led me to the CreateProcessAsUser
and CreateRestrictedToken
API methods, but despite this documentation, all of the various facets of tokens and security descriptors and such is still very confusing to me.
I've also come across some threads here (Running a process with lowest possible privileges in winapi and Dropping privileges in C++ on Windows), but I can't find any good examples with code.
Can anyone provide me with some simple yet "correct" code that will help me spawn child processes using the appropriate Windows IL? Specifically, I'd like an example of how to take the existing Process A token and convert it so it has the reduced privileges (I'm pretty sure I can figure out the rest). I'm really unclear about whether I need to duplicate the process' token before modifying it as well.
Windows defines four integrity levels: low, medium, high, and system. Standard users receive medium, elevated users receive high. Processes you start and objects you create receive your integrity level (medium or high) or low if the executable file's level is low; system services receive system integrity.
The IL represents the level of trustworthiness of an object. This mechanism's goal is to restrict the access permissions for potentially less trustworthy contexts (processes, files, and other securable objects), compared with other contexts running under the same user account that are more trusted.
Safety integrity level (SIL) is defined as a relative levels of risk-reduction provided by a safety function, or to specify a target level of risk reduction. In simple terms, SIL is a measurement of performance required for a safety instrumented function (SIF).
Integrity levels define the trust between process/thread and another object (files, processes, threads) and help control what that object can or can't do on a system. A sudden change in a process's integrity level might be a sign that an adversary has obtained system privileges.
Warning! While this approach was probably more or less OK for the original poster, it isn't really a good idea in general. In particular, note (as per the comment thread) that artificially manipulated tokens have been reported to cause problems in more complicated applications, so if you are using them, be sure to stick to the basic Win32 API. There are of course also potential security implications.
In most scenarios similar to those of the OP, it would probably be preferable to replace the shortcut that launches the elevated application with a launcher application. The launcher can then remain running for as long as the elevated application is running, and provide a natural limited token for the elevated application to use to launch non-elevated processes.
There's code for launching a low integrity process, which is analogous to your case, in the Designing Applications to Run at a Low Integrity Level article in MSDN.
First, you duplicate the process token, since you can't (or at least shouldn't) mess about with a token that is already being used. Then you use SetTokenInformation with the TokenIntegrityLevel class to set the integrity level. There appears to be a bug in the example code, since the correct SID for low integrity level is S-1-16-4096 rather than S-1-16-1024, but you'll want medium integrity level anyway, which is S-1-16-8192. These can be found here.
Once you have this working (that is, once you are able to launch medium integrity processes from your high integrity process) you should try using CreateRestrictedToken to create the new token instead of DuplicateToken, and remove the Administrators token and all privileges (except SeChangeNotifyPrivilege). Otherwise, the new processes will have medium integrity but still have administrator privilege, which could make it easier for any malicious code that might be running in the same session to elevate its privileges.
I've used the approach described here to accomplish this. The basic idea is to ask Explorer to run Process B for you. Since Explorer typically runs at medium integrity level, this gives you what you want.
http://brandonlive.com/2008/04/26/getting-the-shell-to-run-an-application-for-you-part-1-why/ http://brandonlive.com/2008/04/27/getting-the-shell-to-run-an-application-for-you-part-2-how/
The first link will at least give you a good background.
We have a legacy application (Process A) that unfortunately has to run with elevated "admin" privileges (accomplished by setting its shortcut to always run as administrator).
A cleaner way to do that is set the requestedExecutionLevel to the manifest.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With