Calling OpenWindowStation from a service running under a "user" account - c++

My service start an interactive client process with something really similar to this: https://msdn.microsoft.com/en-us/library/windows/desktop/aa379608(v=vs.85).aspx
It works when the service Log On as Local System, and it work if it's running under an Administrator account with the SE_ASSIGNPRIMARYTOKEN_NAME and SE_INCREASE_QUOTA_NAME privileges.
My issue is when using a Standard User account OR Local Service, it fails at OpenWindowStation with error code 5 (ACCESS DENIED).
// Get a handle to the interactive window station.
hwinsta = OpenWindowStation(_T("winsta0"), // the interactive window station
FALSE, // handle is not inheritable
READ_CONTROL | WRITE_DAC); // rights to read/write the DACL
Is it possible to call OpenWindowStation from a Standard User account or my service must run under an Administrator account? I tried almost all Local Policies without success
Thanks!

Unfortunately it can't be done, it seems that only an Administrator can open the interactive station.

Related

How to lower permissions of a user process started from the system service?

In my local system service I may start a UI process that should run with credentials of the logged on Windows user, but at times, when there's no logged on user, it should be able to start in the Winlogon or "secure desktop" as well.
Thus, I'm using the following construct to prep the user token for it:
//The following pseudo-code snippet is run from the local system service
HANDLE hSelfToken = NULL;
HANDLE hToken2 = NULL;
::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, &hSelfToken);
//Remove most of privileges & create restricted token
::CreateRestrictedToken(hSelfToken,
DISABLE_MAX_PRIVILEGE | LUA_TOKEN,
0, NULL,
0, NULL, 0, NULL,
&hToken2);
//Set user session ID for the token where the process will run
::SetTokenInformation(hToken2, TokenSessionId, &dwSessionId, sizeof(dwSessionId));
//The 'hToken2' is later used to call CreateProcessAsUser() to start a user UI process
This works great, except that in despite of having pretty much no privileges and no elevation, my UI process that is started with this method still receives too many of the system service's "rights." For instance, it can create a file in C:\ root folder, or open HKLM registry key for writing.
So I'm curious, what else shall I do to lower the child process' privileges?

CreateProcessAsUser creates blank/black window

I'm using CreateProcessAsUser to create a process under user-specified credentials.
I'm posting what are hopefully the relevant parts of the code. Let me know if you want to see anything more.
First LogonUser to get the token:
result = LogonUser(
username,
wcschr(username, '#') ? NULL : (domain ? domain : L"."),
password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hrunastoken);
I then load the profile, set the lpDesktop value of the STARTUPINFO structure to NULL (which makes it use the desktop of the calling process), and call CreateProcessAsUser:
result = CreateProcessAsUser(
hrunastoken,
NULL,
apptorun,
NULL,
NULL,
FALSE,
CREATE_UNICODE_ENVIRONMENT,
envblock ? envblock : NULL,
NULL,
&si,
&pi);
This works fine - it logs in and creates the process successfully, and the process "works". The problem is that the windows it creates are black, as in this screenshot of a notepad process started with my program:
Possibly relevant context:
My account is a local account on a Windows 7 machine with full admin rights, and I am logged on with that account. I used psexec (Sysinternals utility) to open a command prompt running interactively under the local system account. I am launching my program from that command prompt. The credentials I am passing to it are from my account.
I have not done anything with permissions to windowstations/desktops; I assume the process I create should have rights to those as the process is being created in my session and using the same account I'm already logged in with - albeit going through the SYSTEM account first. Using Process Explorer, I don't see any difference in the permissions on the values and handles to windowstation/desktop by the process opened via my program vs opened normally. Maybe that's completely irrelevant.
I also cannot use CreateProcessWithLogonW function because it must work when run from the SYSTEM account - that function as well as the "runas" program that comes with Windows don't work under SYSTEM.
Funnily enough, I can't use my current method to open processes unless I'm running it under the SYSTEM account, as "a required privilege is not held by the client", so I can't compare the windows created when starting my program under my account vs the SYSTEM account...
The default DACL for window stations and desktops grant full access to the logon SID (which is unique to the current logon session) rather than to the user's SID. (The user's SID also appears in the DACL for the window station but has only limited permissions. It does not appear in the desktop DACL.)
The call to LogonUser generates a new session (and associated logon SID) rather than reusing the existing one, so your process does not have access to the desktop, and only has minimal access to the window station. (Actually I'm slightly puzzled as to how the process manages to run at all; when I tried to reproduce your results the process exited immediately with exit code 0xC0000142, as expected.)
The second piece of code in this answer shows how to change the DACL on the window station and desktop to allow the process to run properly. (This may not be the best solution, however, depending on your specific goals.)

Account Locking Not Working in WSO2 Identity Server 5.0.0

I tired to lock user account using the admin console UI as described in http://isurad.blogspot.com/2014/09/how-to-lock-user-account-in-wso2.html. I made http://wso2.org/claims/identity/accountLocked = true. But still I can log in to the console using locked account.
Also tried to lock user account using the web service. Even this prints in the console,
{org.wso2.carbon.identity.mgt.services.UserIdentityManagementAdminService} - User account unconfirmed1 locked
Still I can log in to the console using locked account. What has gone wrong here?
The operation via the admin console is cached and is currently set to 15 mins. Hence the account lock should have worked but you need to wait 15 mins for this to come into effect. The web service calls should be immediate though.

How to know whether I have admin authority in windows?

Is there any APIs in windows to detect whether the current user(current now) has the admin authority?
BOOL IsHasAuthority()
{
}
Many Thanks!
How to Determine Whether a Process or Thread Is Running As an Administrator
Use this solution when you are writing
an application that must determine
whether any of the following is true:
The current user can perform administrative tasks. The current
user is a member of the
Administrators group. A supplied token handle represents an
administrator with an elevated token.
A token handle represents a user who is a member of the
Administrators group.
The program is running with an elevated token or needs to spawn a
child program that is elevated so it
can perform administrative tasks.
You can use the Windows API function CheckTokenMembership(). The MSDN documentation for that function has an example demonstrating how to check for membership in the Administrators local group.

OpenProcess / SetProcessAffinityMask on process started by my service

In my manager.exe, I'm trying to change the CPU usage of my worker.exe, which is started by my service.exe. Service.exe is running under the System Account, while manager.exe is running under the logged in user's account.
When I call OpenProcess in manager.exe with worker.exe's PID, I get NULL for procHandle:
HANDLE procHandle = OpenProcess(PROCESS_SET_INFORMATION, 0, pid);
Using GetLastError() I see that I got an Access Denied error.
Any ways around this? Can I somehow modify worker.exe to grant other processes full control over itself?
You shouldn't have to call OpenProcess.
The service should already have a full-permission handle to the worker from when it called CreateProcessAsUser or CreateProcessWithLogonW. Use DuplicateHandle to make a version of that handle suitable for use by the manager process, and then have the service send that handle to the manager. The service already has a handle to the manager, right? It will need that for DuplicateHandle.
Or have the manager ask the service to change the worker process.