CoRegisterClassObject acess class from different integrity level or privileges - windows

I'm using WinRT for showing ToastNotification. While working on this, I stumbled across the more generic problem that when a class factor is registered via
::CoRegisterClassObject(
callbackGuid,
winrt::make<NotificationCallbackFactory>().get(),
CLSCTX_LOCAL_SERVER,
REGCLS_SINGLEUSE,
&registration))
from a server process running with admin rights, a client process running with normal rights cannot instantiate it. The call
CoCreateInstanceEx(callbackGuid, NULL, CLSCTX_LOCAL_SERVER, pcsi, 1, &mq);
fails with error 80040154 Class not registered. I know that from a security standpoint this makes sense, but I was wondering if there is a way to bypass the check without using changing the running privileges of my process and without using global modifiers like CoInitializeSecurity. Basically I need a way to say "this class is accessible to everyone". Also I don't have a AppID.
EDIT: I forgot to say that the final solution must be on the server side, because for the original task of the Toast Notification I have no control on the client

COM weighs 3 main factors when deciding whether a running out-of-proc server is visible to a client attempting to activate that server’s CLSID: the configuration of the CLSID (typically in the registry), the server identity (as described by its token), and the client identity. The main security concern you’re trying to evaluate at that point is not access, as implied by the original question. Access is controlled by launch permissions (part of the CLSID configuration) and access permissions (configured via CoInitializeSecurity), and the server can use those security descriptors to describe which clients are allowed to respectively activate and call them. Those permissions can be made extremely broad, if the server so chooses. But they’re not relevant if the server isn’t even visible to the client.
The security concern you’re dealing with when evaluating activation visibility is actually squatting: can the client trust that the server is who they expect it to be?
If the CLSID configuration describes exactly what the server identity should be (e.g. a RunAs=System CLSID), then COM can reject any servers trying to CoRegister with an inappropriate identity; since there’s no squatting risk to any clients at that point, you can make that server visible to all clients. But at the other extreme, if the CLSID configuration doesn’t constrain the server identity at all, then making the server visible to a broad range of clients would have a significant squatting risk.
That latter case is referred to as “Activate-As-Activator” (AAA), because the server is only visible to the client (i.e. activator) if their identities match. If the CLSID has no configuration at all, or if the configuration doesn’t sufficiently constrain server identity, the CLSID is considered activate-as-activator. Since the server is only visible to clients with sufficiently similar identities, a non-admin client won’t be able to activate an admin server (or vice versa for that matter). You can’t prevent squatting attacks by verifying the server identity for these CLSIDs, so you can only allow activations that don’t cross any security boundary at all.
So if the server is some high-privileged known account such as System or LocalService, you would need to configure the CLSID with a RunAs APPID for that account. If the server’s identity is “the same as the client’s but elevated”, you don’t have a RunAs that describes that. What you do have for that case is the elevation moniker. You configure the CLSID as Activate-As-Activator, and add some extra configuration to make it compatible with the elevation moniker. You also need different client code which explicitly activates through the elevation moniker. And the activation would pop up a UAC prompt. Unfortunately, if you can’t alter the client code, and you’re in that latter “the same as the client but elevated” case, I don’t believe there’s any way to make the activation succeed directly. You could probably introduce another layer to make it work (original CLSID starts up an exe under the client’s token through AAA activation; then that intermediary process does an elevation moniker activation of the real CLSID running as admin). But it would be far cleaner to change the client code.

Related

Services Creating Services - Assigning SC_MANAGER_CREATE_SERVICE to a User

I'm trying to create a Windows service that has the right to create additional services. But I'd prefer not to make this service run with an Administrative login.
The users rights are otherwise quite limited - I just need it to be able to spin-up a service on request.
I've seen mention online that SC_MANAGER_CREATE_SERVICE is a permission you can now assign and/or change, but I haven't seen much on how that is done. There is mention of being able to change permissions for individual services via subinacl, via OpenSCManager and the - gulp - sc command. But these examples show how to change the permissions on a single service, not how to give a user SC_MANAGER_CREATE_SERVICE permissions.
However, I've noticed that the documentation on CreateService specifically says that it requires administrator privilages - so perhaps it's simply not possible.
Am I going to have to start the service with an admin account? Or does anyone know another trick?
See Service Security and Access Rights:
To get or set the security descriptor for the SCM, use the QueryServiceObjectSecurity and SetServiceObjectSecurity functions with a handle to the SCManager object.
Be aware that having the right to create services gives you effective administrator access, since you can create a service to run as local system. So you do need to be careful not to grant that right to accounts that untrusted users have access to, to make sure that all accounts with that right have strong passwords, and so on.
This also means that if your system service is compromised by a remote code execution vulnerability you haven't gained anything, the attacker will still be able to get control of your system. If the service is at a high risk of direct attack, it may be wise to instead have a second service that is responsible only for the tasks that require special privilege. However, for a service that is unlikely to be directly attacked, or is considered reasonably secure, running without administrator privileges (other than the ability to create services) may prevent a less severe vulnerability from being exploitable, or limit the damage caused by a non-security-related bug.
See also Granting service control manager access permission to user outside of administrator group on Server Fault, the answer shows how to change the SCM permissions from the command line.
Try opening an handle to the service control manager with the WRITE_DAC access right, and change the security of it by calling SetServiceObjectSecurity to change the dacl of the service control manager. Don't forget to do the same thing for the service registry key (HKLM\SYSTEM\CurrentControlSet\Services) using RegOpenKeyEx and RegSetKeySecurity function.
WARNING
Be aware that this is a potential security risk since it would allow a standard user account to elevate its privileges to SYSTEM.

How do I write a Windows 8 software to run with SYSTEM privileges?

I apologize for the bad phrasing in the title, but here's a little more context.
I recently bought a Windows 8 laptop and noticed that Norton was pre-installed and running with SYSTEM level privileges. Thus, it occurred to me that there must be some way for third-party applications to run with SYSTEM privileges.
However, after much googling, I could not figure out whether it was an API call or a registry setting or something else entirely that enabled Norton to do this, so I decided to ask the SO community. How can I write an application that runs with SYSTEM privileges?
Services can be configured to run as several different accounts, including LOCAL SERVICE, NETWORK SERVICE, SYSTEM, or any user's account.
Using SYSTEM isn't recommended, because any security problem can lead to complete compromise of the machine, but it is available.
This is configured by the lpServiceStartName parameter of CreateService and/or ChangeServiceConfig. Pass a NULL pointer as this parameter of CreateService, or ".\\LocalSystem" to ChangeServiceConfig, to use the local system account.
It's a bad idea to run a GUI application as local system. The best approach is to have both a GUI application (running as the logged-on user) and a service (running as SYSTEM) and have them communicate as needed using any suitable IPC method. This is probably what Norton is actually doing.
However, it is possible to get a system service to launch an application as SYSTEM in the user's session. To do this, duplicate the processes security token with DuplicateTokenEx and then use SetTokenInformation with the TokenSessionId option. This will give you a token in SYSTEM context but in the user's session which you can use to launch an executable. (There may be additional issues; for example, you might also need to change the permissions on the workstation and desktop.)

PAM "session required module" equivalent in Windows

I have this nifty PAM module that validates each session (like a desktop session) on authentication and, based on some criteria, either allows or prevents it. I would like to do the same on Windows 7.
Now, this may sound silly or trivial to no extent, but I really don't know my way around Windows systems, and would thus like a few pointers on how to achieve something similar (i.e. a service or a module that is queried when e.g. a user tries to start a session.)
I think what you are looking for is a Subauthentication Package, but you could get some mileage with a Credential Provider.
A Subauthentication Package is a dynamically linked library that the local security authority or the Kerberos Key Distribution center (KDC) will call after authentication has succeeded, but before access is granted to the user.
Windows will authenticate the user locally or through Kerberos, depending on your configuration. You must build a DLL that exports the two functions:
Msv1_0SubAuthenticationRoutine (not called for interactive logons or Kerberos)
Msv1_0SubAuthenticationFilter
You put your code in that DLL, and return STATUS_SUCCESS if the user is allowed to log on, or one of the other error codes. You cannot assume that you will have access to the password.
If you log on through Kerberos, you must register your DLL on the KDC. It makes it hard to authentication against some local information, like a hardware or biometric device.
So maybe a Credential Provider could help you, but it is not the most elegant solutions. It was designed to capture credentials and feed them to an authentication package. But Microsoft made shure a credential provider will not lock a user out, so it might not always be called (in safe mode) and the user could install another CP, etc. So I mention it for the sake of completness.

Showing Password Prompt Only Once - How to?

I'm building an Cocoa application that modifies a file on the user's operating system which requires admin permission. I have a proof of concept working which uses authopen but it doesn't deliver the UX experience I am hoping to achieve. Every time the file is modified it prompts the user to enter their password. Is there a way to have permissions granted to the application for the duration of its life?
Goal:
Application asks user for password once ever, going forth application does not prompt for password.
Next Best:
Application asks user for password once at application launch, going forth application does not prompt for password until application restart.
I'm aware of Authorization Services and the possibility of creating a Daemon which deals specifically with modifying privileged files, what I'm curious about is if either of my listed goals are even possible before diving too deep into another system.
Really appreciate any suggestions, critiques or helpful links.
Cheers,
Dustin
Yes, using Authorization Services is the way forward. You get an AuthorizationRef in your application via AuthorizationCopyRights() (which shows the UI if needed), and pass this to your helper (by packaging it up into an external form) which verifies that it actually got the necessary right before performing the privileged task. Authorization Services is able to register rights in the /etc/authorization database, so if you choose a custom right you can choose the default settings for who is allowed to acquire it, what timeout or other conditions exist and so on.
To deploy your privileged helper tool, you should use the Service Management framework, in particular SMJobBless() which verifies that the code signing identities on your client and helper match before deploying the helper as a launchd job. Then your helper can be initiated on demand by the main application.
Feel free to ask if you want clarification on any step in the answer, however I already wrote about both of these aspects of privilege separation in my book Professional Cocoa Application Security so feel free to buy a copy or two ;-).

Why running a service as Local System is bad on windows?

I am trying to find out the difference between difference service account types. I tumbled upon this question.
The answer was because it has powerful access to local resources, and Network Service should be used if possible.
But still I am not able to understand that if it has powerful access to local resources, how attacker can access the account? What are the ways to compromise the account? I understood it is all about security, but I don't know how. It could be dark hacker's world, however anybody could explain, in simple terms, why network service account is better than local account ?
Thanks in advance.
Every program you run increases the attack surface of your server.
You have to assume that a determined, malicious actor can exploit bugs or loopholes in your program to make it do anything. You mitigate that by executing your programs with the least privileges required to do their jobs.
Some of these exploits include:
Luring attacks, in which an attacker tricks your program into executing their code under the program's elevated privileges.
Buffer Overrun Attacks, in which extra data sent to a method is written into adjacent memory, which may be the target of control flow logic.
Man in the Middle attacks, where an attacker falsifies messages to your program.
Often, a given service isn't obviously vulnerable to any of these. Running under network service (or another account with reduced permissions) is a 'better safe than sorry' strategy that acknowledges two important facts of software development: programmers are fallible and attackers are inventive.
The LocalSystem account is the Windows equivilant of the *nix root account. It's even more privileged than an administrator account. When you run as LocalSystem, you have full access to every resource on the machine.
As others have written, you should write your code to run with the least possible privileges.
The primary difference between LocalService and NetworkService is that services running as NetworkService have the ability to authenticate to other machines in the domain (as the machine account I believe).
Please note that the LocalService and NetworkService accounts both have the "Impersonate" privilege which is a potentially dangerous privilege - it allows the service to impersonate the user who is calling into the service. If that user is an administrator, then even though your code is running in a low privileged service, it can do anything that the administrator does. If an attacker can exploit a buffer overflow in your least privilege service, they can hook out the APIs you use to impersonate your caller and wait until a high privileged caller calls into your service. This technique is known as "Token Kidnapping" and the MSRC has a great blog post describing the issue (and contains links that describe how to mitigate many of the other risks associated with using LocalService and NetworkService accounts).
The Local account has effectively full administrative priviledges on the local machine. Hence any code that might escape from say a buffer overrun and get itself executing has significant scope to do damage.
On the other hand, the Network Service account has by default only Guest level access to the local system. Hence even if an attacker managed to find way to send and execute code within the service that code would have limited access.
If your service has a bug, which can allow attacker to execute arbitrary code (like buffer overflow), he can do everything with your computer if service is running under Local System account, which is equivalent to Administrator account. So the lesser priveleged account your service is running, the lesser privilege the attacker can get.
The simplest scenario is when the service allows the user of the service to execute some code on command line. For example MS SQL Server has a stored procedure that allows you to run a 'command line' command (i.e. run a program).

Resources