2

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.

parrowdice
  • 1,902
  • 15
  • 24
  • need understand that when you use interactive logon - you anyway got restricted token (if uac active and you not use built-in administrator account). not admin token. but you can use `LOGON32_LOGON_BATCH` or `LOGON32_LOGON_NETWORK` option in `LogonUserW` call and than use `CreateProcessWithTokenW` - this will be work.. if your new process not required UI – RbMm Jun 26 '20 at 19:42
  • @RbMm thank you. The front end process does need a UI though – parrowdice Jun 26 '20 at 19:57
  • as else one solution you can pass built-in administrator account (enable it first if need). problem that by default system disable admin group and most privileges in case interactive logon. – RbMm Jun 26 '20 at 20:00
  • @RbMm I tried `LogonUser` with `LOGON32_LOGON_BATCH` and `CreateProcessWithTokenW`, but it still fails with `ERROR_PRIVILEGE_NOT_HELD`. – parrowdice Jun 28 '20 at 12:19
  • no, `LogonUser` with `LOGON32_LOGON_BATCH` and `CreateProcessWithTokenW` will be work well, if you pass admin cred and no errors in code. but this is ok only for process without ui – RbMm Jun 28 '20 at 12:22
  • @RbMm I've edited the post to show the code for your suggestion. The code fails with `ERROR_PRIVILEGE_NOT_HELD`, even for notepad, not just processes that require elevation. When you say "for process without UI", are you referring to the calling process, or the target process? The calling process has a UI. I can get by with the target process not having a UI, I can just delegate the privileged calls to that process. – parrowdice Jun 28 '20 at 12:53
  • of course i mean target process. – RbMm Jun 28 '20 at 12:55
  • yes, my mistake (i test from admin process). really `CreateProcessWithTokenW` fail if your process not have `SE_IMPERSONATE_PRIVILEGE` (and only already elevated processes have it). you fail here - https://i.imgur.com/fGcGeEH.png – RbMm Jun 28 '20 at 13:18
  • `CreateProcessWithLogonW` + `LOGON_WITH_PROFILE` works for me, could you please also share your sample with `CreateProcessWithLogonW`? – Drake Wu Jun 29 '20 at 08:33
  • @DrakeWu-MSFT Thank you. `CreateProcessWithLogonW` does create a process for me too, but only when the target process doesn't require elevation. E.g. it will start notepad.exe, but not msconfig.exe which will fail with `ERROR_ELEVATION_REQUIRED`. – parrowdice Jun 29 '20 at 08:59

0 Answers0