Under a restricted/local user account, how can that user run an application that has admin privileges without having to enter a username/password (the application in question has access to the username/password of an admin account (stored as encrypted) for it to use) (see below for why).
I've tried various incarnations of LogonUser
, ImpersonateLoggedOnUser
, etc to give the application the rights of an admin user, but it appears that a restricted process cannot create a token with rights greater than itself, contrary to the MSDN documentation (see Odd behavior of windows Impersonation - the code here demonstrates the issue), even when calling APIs like LogonUser
with admin credentials, they only give filtered tokens.
Calling APIs like CreateProcessWithLogonW
or CreateProcessAsUser
to start the application with admin credentials suffer the same fate; fails with ERROR_ELEVATION_REQUIRED
or ERROR_PRIVILEGE_NOT_HELD
from a restricted user process.
APIs like ShellExecute
will prompt the user for admin credentials, which the user won't have.
Using runas
with /savecred won't elevate either, and that's not safe at all anyway.
I'm considering having to make a service for the machine which the application will IPC to when it starts as a restricted user, and the service will restart the process with the admin credentials, but there must be an easier way? Or maybe it can work with the above APIs and I've missed some detail for this situation?
Perhaps there's even a non-programatic way to do this that I don't know? Set it as a startup process with credentials somehow? The user would still need to be able to start/stop it if required.
I'd really appreciate any knowledge on this, been scratching my head for a while!
Why?
The user has a login to one machine on the supplied offline system/network, and a front end C++ application on that machine is the only way for the user to control other software/machines in the wider system servers.
The user's account now needs to be a restricted/local account (was previously admin), but the C++ application requires admin privileges. We don't want the user to have access to the username/password of admin accounts, but the front end needs to run as admin.
It's quite a legacy application/system (was built on Windows XP), so re-writing the whole thing to run as the current Windows security model wants (admin API calls via IPC/RPC to a system process) would be infeasible. I know it would be the 'right' thing to do and I would do that if making this ground up, but time/budget contsraints...
Edit:
#include <Windows.h>
#include <stdio.h>
void fail(wchar_t * err)
{
DWORD dw = GetLastError();
printf("%ws: %u\n", err, dw);
ExitProcess(1);
}
int main(int argc, char ** argv)
{
HANDLE hToken = NULL;
if (!LogonUser(
"user",
"domain",
"password",
LOGON32_LOGON_BATCH,
LOGON32_PROVIDER_DEFAULT,
&hToken))
{
fail(L"LogonUser");
}
PROCESS_INFORMATION pi = { 0 };
STARTUPINFOW si = { 0 };
si.cb = sizeof(STARTUPINFOW);
if (!CreateProcessWithTokenW(
hToken,
LOGON_WITH_PROFILE,
L"C:\\windows\\system32\\notepad.exe",
NULL,
0,
NULL,
NULL,
&si,
&pi
))
{
fail(L"CreateProcessWithTokenW");
}
return 0;
}
CreateProcessWithTokenW
fails with ERROR_PRIVILEGE_NOT_HELD
.