Launching an administrative interactive process when a standard user is logged on - windows

I have a system service which creates a helper interactive process as administrator so that it can access some desktop-related resources, including the BlockInput() function and NVIDIA's NVAPI functions, which cannot be run from a service. When the logged on user was a member of Administrators, the following worked:
Set privilege levels, including SE_TCB_NAME
Get active session ID with WTSGetActiveConsoleSessionId()
Get logged on user from session ID with WTSQueryUserToken()
GetTokenInformation() with TokenLinkedToken
DuplicateTokenEx() with SecurityImpersonation
Launch process with CreateProcessAsUser()
However, when I have the current logged on session be a standard user instead of one in Administrators, step 4. fails, presumably because the standard user doesn't have an administrative level token linked with it. What's the solution here? I assume I need to get the token of one of the administrator users, but how do I do that? And if that user is not the logged on one, can it still access functionality interactive with the current desktop?

You can duplicate your own token, then change the session on the duplicated token using the SetTokenInformation function to put it into the interactive session.
As you note, running as SYSTEM in an interactive session is discouraged because it gives the interactive user openings to attack your process, potentially gaining elevated privileges. (Search for "shatter attack" for more information.) However, this concern applies equally well to a process running as an administrative user in a non-administrative user's session.
Ideally, you should use a non-administrative process in the interactive session, to perform functions which require an interactive session, while using the service to perform functions which require administrative privilege. There shouldn't be any functions that require both, but if NVAPI breaks this rule, there's not much you can do about it.
Consider launching the process into a specially created (and appropriately secured) workstation in the interactive user's session in order to minimize this risk.

Related

What's "Replace a process level token" for anyway?

Let me start by saying I know next to zero about Windows. My understanding is that processes in Windows get their privileges from a process-level token, which normally would identify the user started the process, but may differ as is common for system tasks, correct? This is somewhat akin to Linux processes having real and effective user and group IDs (it may not be appropriate to make analogies to Linux, but it's all I know). Also, as far as I know, a user can run a process as another user using runas.exe (similar to sudo in Linux). And of course they'll be prompted for the credentials of the user they want to run the process as, and as long as they know the credentials no special permissions are needed, correct?
Now, there is a user right called "Replace a process level token", which according to the docs:
Users with the Replace a process level token user right can start processes as another user if they know the user’s credentials.
Emphasis above is mine. So my question is: if someone knows the credentials for a given user, they can always run a process as them (either using runas.exe or just by logging in as them). What's the purpose of the "Replace a process level token" user right, and what's the security impact of it?

Win32 Prevent Process from Seeing or Closing Processes from other sessions

When running under Citrix or RDP as an admin, I can see, terminate or otherwise manipulate processes created by other users, or in other sessions. Admins need to be able to do this from time to time so I can't remove that capability from Admin logins, but I'd like to restrict it on certain processes.
Is there a way to change the security and/or privileges of the current process or a process I launch, so that it can no longer see or otherwise manipulate other user's processes? I'd be happy to either change the rights of the currently executing process (which is mine), or launch my process using some method that denies the privilege to the target executable. It's the inverse of Run as Admin.
I thought that AdjustTokenPrivileges might be the key, but I can't seem to find any privileges to remove that relate to seeing other users' processes in the Privilege Constants list.
CreateProcess with an appropriate lpSecurityDescriptor seems like it might do the trick, but I haven't been able to find a good example of the security descriptor, or anything that relates to other users' processes.
Anyone know the secret sauce? Thanks

CreateProcessAsUser not from a service

I want to run an application under another user account's (non-elevated) credentials while that user is already logged-in. Specifically, I want my application's installer (which runs under any administrator account) to spawn processes into each logged-in user's desktop session. These processes communicate with a service and display windows on the desktop for the user to interact with.
Ordinarily, from a service running as LocalSystem, the approach is WTSQueryUserToken -> CreateProcessAsUser. However, WTSQueryUserToken won't run outside of the LocalSystem account (with SE_TCB_NAME privilege), which makes that approach fail here.
If the user weren't logged in already, I could just register the application to run under HKLM\...\Run, so that any logged-in user will get a copy of the application when they log in. But if the user's already logged-in, that doesn't work either (at least, not until they log out and log back in again).
I can see two possible answers:
You can't do this. Sorry.
You can get a token from somewhere else (maybe enumerate explorer.exe processes and pull the access token from each one?), call DuplicateTokenEx, then pass to CreateProcessAsUser. I tried this approach and consistently received "access denied" when trying to OpenProcessToken on a process running under another user session, even with the debug privilege enabled and the process opened with PROCESS_ALL_ACCESS.
What do you think?
If the answer is #1 ("you can't do this"), then what is the recommended best practice for spawning non-elevated processes to mediate between a service and the user? Is it best practice for the service to spawn these processes into each session via CreateProcessAsUser? Or is it best practice for the non-elevated processes to be run separately (e.g. via HKLM\...\Run or HKCU\...\Run)?

Is there a way to have multiple windows logins go to single session?

In windows 7, is there a way to have every login go to the same user session. So when a person is met with the login screen, they login and can continue working on that same user session. I am asking this because each user has their own login, but on this machine I need a program to be running across all user sessions. Since that doesn't seem feasible, I was just going to have them all login to the same user session.
Is this possible?
The appropriate way to solve this would be to have the program run as a service, and have a client UI that loads on startup 'hook' into the service process. Loading multiple users to the same session space would effectively violate the entire windows security model.
So, you either need to use a shared user for this, or a shared process (either local as a service, or remote as a server)
So, there's one possible way you might be able to get this to work, and that's to set this up as an interactive service. Definitely not a secure way to keep your system, but if you are able to make it work, it should work for your purposes:
Interactive services (in particular, read 'using an interactive service'):
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683502(v=vs.85).aspx
Making srvany.exe (to run non-services as a service) on Windows7/Windows 2008:
http://social.technet.microsoft.com/Forums/en-US/winserverMigration/thread/98a97aee-c62b-4683-94ab-3777899cf7de/

Sessions, Window stations and Desktops

Sessions, Window Stations and Desktops.
A session consists of all process and
other system objects that represent a
single user's logon session. Sessions
contain Window Stations and Window
Stations contain desktops.
The above is from http://blogs.technet.com/b/askperf/archive/2007/07/24/sessions-desktops-and-windows-stations.aspx
(Similar articles say the same thing, e.g. blogs.technet.com/b/askperf/archive/2007/04/27/application-compatibility-session-0-isolation.aspx and blogs.msdn.com/b/ntdebugging/archive/2007/01/04/desktop-heap-overview.aspx)
I've always understood Sessions and logon sessions to be one and the same thing.
However, reading p. 474, Russinovich and Solomon, Windows Internals, 5th edition, it says (penultimate paragraph):
The CreateProcessWithLogon function
also creates a token by creating a new
logon session with an initial process,
which is how the Runas command
launches processes under alternative
tokens.
So Runas creates a new logon session. If we use Runas to run Notepad under a different user's credentials we see it appear on the desktop. So Notepad is running on the same desktop as everything else. (This is, as far as I understand it, the default desktop in Window Station Winsta0; the interactive window station.) So what we have now are two logon sessions associated with the same Session (the thing that contains window stations). So Sessions and logon sessions would not appear to be one and the same.
Can anybody confirm this please?
Confused
There are indeed two types of sessions here. Here's my understanding of how they work.
A logon session[2] is managed by the Local Security Authority[2], and manages the scope of a user logon. These are created primarily by the winlogon process, but also secondarily by API functions such as LogonUser, CreateProcessAsUser, and CreateProcessWithLogonW, or by applications that use these functions, such as the runas command.
A logon session isn't tied to any specific Object Manager[2] concepts as window stations and desktops. It's basically just a block of information containing the logon SID and some cached security information about the account. This block of information, this logon session, is what an access token points to.
The other type of session is sometimes called a Terminal Services session, Terminal Server session, Remote Desktop session, logon session (as confusing as that is), user logon session, or user session. Usually, though, it's just called a "session", without further qualification.
This is the type of session that you'll usually hear about, and is what window stations belong to. This type of session came about to support multiple interactive GUI logons, as provided by Terminal Services (now known as Remote Desktop), and is now also used to support Fast User Switching. Sessions provide the necessary isolation between the Object Manager objects associated with each user logon.
I don't spend much time messing with all this stuff, so I'm a little fuzzy on some of the details, but I think this is a pretty fair representation of the overall picture. I hope it clears things up a bit.

Resources