Jump to content

SYSTEM user RunAs local administrator problem


Recommended Posts

Hello!

Me and my colleague are working on a project where we need to automate the installations of various programs. We are using a software called WPKG (http://wpkg.org/) to manage the packages for each computer in the project.

We use AutoIT to automate the installations which do not provide a built-in silent mode. We also use AutoIT to make sure that the the installation commands for the software packages are executed as a privileged user on the domain so we can access the network shares which holds the required installation files.

Now, when the package manager (WPKG) executes the installation commands, they are executed in the context of the local "SYSTEM" user. Since this user does not have any access to the network shares or such, we have made a very simple Runner script using AutoIT, which basically determines the account credentials for the domain user, and executes @CmdLineRaw through RunAsWait with this information. The line of code used for this is:

; ... Retrieval of account credentials.

$logon_flag = 5
$exit_code = RunAsWait($USERNAME, $DOMAIN, $PASSWORD, $logon_flag, $CmdLineRaw, @WorkingDir)
If $exit_code == 0 And @error <> 0 Then
    Exit -13
EndIf

Exit $exit_code

Now, here is our problem:

When we run this script manually, without going through the package manager (WPKG), then it seems to work just fine. (In this case the Runner script is executed as a domain user.)

However, when we run it through the package manager, and thus the Runner script is executed in the context of the local SYSTEM user, then we get exit code -13 all the time. We have checked the @error macro, and it has value 1. (@extended is 0 if it's of any use.)

We have also tried to execute it as the local Administrator user, but that gave the same result.

Some additional information:

WPKG offers an option to specify which user to execute the script(s) as, and if we use the domain user here, and without using the Runner script, then everything works. This means that there is nothing wrong with the actual scripts being executed, but something with the Runner script.

Unfortunately the domain security does not allow us to specify the account credentials of this domain user like this in the production environment, which is why we needed to create the Runner script in the first place.

We did find this thread, which sounds like it might be the same, or at least a similar problem:

http://www.autoitscript.com/forum/index.php?showtopic=6544

It is however listed as fixed, and we are not using RunAsSet, but we are still experiencing this problem.

We would appreciate all the help that we could get.

Thanks in advance!

Yours, Jiddo.

Link to comment
Share on other sites

Oh, I should probably also mention that we are using Windows XP SP2 since that thread seems to indicate that there is some XP SP2-specific behavior when it comes to using RunAs functions.

Yours, Jiddo.

Link to comment
Share on other sites

Please, we would really appreciate any help or suggestion on this! We would even be grateful for any hints on alternate approaches or workarounds!

Yours, Jiddo.

Hi,

$logon_flag = 5

which version of AutoIT you are using. Haven't found logonflag 5 in AutoIT 3.3.0.0 and 3.3.1.1.

You should try it with $logonflag = 4. (see help RunAsWait)

which basically determines the account credentials for the domain user

Is this an 'installation domain account? If not, how you get the password of the logged on user?

;-))

Stefan

Edited by 99ojo
Link to comment
Share on other sites

Hi!

Thanks for your reply!

We are using AutoIT v3.3.0.0. We have tried all the listed logon flags, but none of them seemed to work. Then we found some reference about someone with a similar problem who solved his problem by using logon flag 5, as a combination of flags 1 and 4 (Interactive logon with profile and Inherit the calling processes environment instead of the user's). This was just an experimental value tho, and we did get the same result with all the other flags. We have especially tried it with flag 1.

At the time when the scripts are executed, there are no logged in users (the WPKG service executes installation scripts before the users are able to log in on the system). The WPKG service (and the scripts) are executed as the Local SYSTEM user. The domain user that we use the credentials of in the RunAs function is a user in our domain, with administrative rights to all the computers. (This user will not be logged in/active when the script are excuted.)

The account credentials are currently fetched from a web server in the network in order to be up to date. (A safer method for getting the credentials might/will be deviced later in the project.)

UPDATE:

We have found this, which might apply to our problem:

http://support.microsoft.com/kb/294676

Especially interesting is this section from "Troubleshooting":

* The Run As command cannot be used from the LocalSystem account in Windows XP Service Pack 2.

I would guess that this is what's causing the problems, but then again, we also seem to have the exact same problem when testing this on a Windows 2000 SP4 computer. Any ideas?

Yours, Jiddo.

Edited by Jiddo
Link to comment
Share on other sites

Hi!

Thanks for your reply!

We are using AutoIT v3.3.0.0. We have tried all the listed logon flags, but none of them seemed to work. Then we found some reference about someone with a similar problem who solved his problem by using logon flag 5, as a combination of flags 1 and 4 (Interactive logon with profile and Inherit the calling processes environment instead of the user's). This was just an experimental value tho, and we did get the same result with all the other flags. We have especially tried it with flag 1.

At the time when the scripts are executed, there are no logged in users (the WPKG service executes installation scripts before the users are able to log in on the system). The WPKG service (and the scripts) are executed as the Local SYSTEM user. The domain user that we use the credentials of in the RunAs function is a user in our domain, with administrative rights to all the computers. (This user will not be logged in/active when the script are excuted.)

The account credentials are currently fetched from a web server in the network in order to be up to date. (A safer method for getting the credentials might/will be deviced later in the project.)

UPDATE:

We have found this, which might apply to our problem:

http://support.microsoft.com/kb/294676

Especially interesting is this section from "Troubleshooting":

I would guess that this is what's causing the problems, but then again, we also seem to have the exact same problem when testing this on a Windows 2000 SP4 computer. Any ideas?

Yours, Jiddo.

Hi,

just for testing purpose:

What about running the WPKG service with the administrative account?

You also should think about updating your XP Environment to SP3 and your W2K to XP (W2K is running out of support for patches!!!!!)

;-))

Stefan

Link to comment
Share on other sites

We have tried running as the local Administrator user in two ways:

1. We tried changing the "Log on as" user for the WPKG service (in the Computer Management -> Services list) to the local computer Administrator user.

2. We have tried specifying the WPKG execution context user as the local computer Administrator user.

The problems we had were:

1. The WPKG service crashed when trying to start up. It seems like the service itself needs to run as the Local SYSTEM user in order to function at all.

2. This seemed to give the same result as using the Local SYSTEM user.

Unfortunately OS version decisions are out of our control since we are doing this project for a quite large company, which has specific deals with HP to provide their computers. Requesting a change in OS/Service Pack versions would be a quite difficult process if it is even possible.

The Windows 2000 machine is just a work station and will not be used/needed in the production environment. We just tested it on this machine in an attempt to isolate the problem. It is not important to get it working on Windows 2000. XP is really all that matters.

Yours, Jiddo.

Link to comment
Share on other sites

We have tried running as the local Administrator user in two ways:

1. We tried changing the "Log on as" user for the WPKG service (in the Computer Management -> Services list) to the local computer Administrator user.

2. We have tried specifying the WPKG execution context user as the local computer Administrator user.

The problems we had were:

1. The WPKG service crashed when trying to start up. It seems like the service itself needs to run as the Local SYSTEM user in order to function at all.

2. This seemed to give the same result as using the Local SYSTEM user.

Unfortunately OS version decisions are out of our control since we are doing this project for a quite large company, which has specific deals with HP to provide their computers. Requesting a change in OS/Service Pack versions would be a quite difficult process if it is even possible.

The Windows 2000 machine is just a work station and will not be used/needed in the production environment. We just tested it on this machine in an attempt to isolate the problem. It is not important to get it working on Windows 2000. XP is really all that matters.

Yours, Jiddo.

Hi,

1. The WPKG service crashed when trying to start up. It seems like the service itself needs to run as the Local SYSTEM user in order to function at all.

Be sure, that the user has the right to logon as service!!!! See MMC Snap In -> Group Policy -> Local Computer Policy -> Computer Configuration -> Windows Settings -> Security Settings -> Local Policy -> User Rights Assignment -> Log on as a service

$exit_code = RunAsWait($USERNAME, $DOMAIN, $PASSWORD, $logon_flag, $CmdLineRaw, @WorkingDir)

What is your $CmdLineRaw and your @WorkingDir?

It seemed, that @WorkingDir might be an Networkshare. If yes, the local systemaccount and the local administrator could have no access.

Link to comment
Share on other sites

Be sure, that the user has the right to logon as service!!!! See MMC Snap In -> Group Policy -> Local Computer Policy -> Computer Configuration -> Windows Settings -> Security Settings -> Local Policy -> User Rights Assignment -> Log on as a service

The MMC console is completely new to us, but we looked it up, and the local Administrator user does in fact have "Log on as a service" rights.

What is your $CmdLineRaw and your @WorkingDir?

It seemed, that @WorkingDir might be an Networkshare. If yes, the local systemaccount and the local administrator could have no access.

@WorkingDir is C:\WINDOWS\System32

$CmdLineRaw is different for each command. One example is:

"\\path-to-network-share\WPKG\software\printer\printer-delta3.exe" check

Yours, Jiddo.

Link to comment
Share on other sites

We have now tried to execute the scripts as the desired user by using the psexec tool instead of RunAsWait. It currently looks like this:

$user = $DOMAIN & "\" & $USERNAME
$cmd = "C:\Program Files\wpkg\psexec.exe"
$args = '\\' & @ComputerName & ' -accepteula -u ' & $user & ' -p ' & $PASSWORD & ' ' & $CmdLineRaw

$exit_code = ShellExecuteWait($cmd, $args, "")

Somehow this solution seems to be working just fine on our Windows 2000 machine, but it does not work at the XP ones. When we execute it on the XP machine, through the WPKG service (and thus as the LocalSystem user), then we get exit code 5 from psexec. This error code seems to mean "Access is denied." It still works when executing it as a normal user tho, so the account credentials is correct.

If RunAsWait is hard or impossible to fix, would it perhaps be easier to make this psexec solution working instead?

Yours, Jiddo.

Edited by Jiddo
Link to comment
Share on other sites

The MMC console is completely new to us, but we looked it up, and the local Administrator user does in fact have "Log on as a service" rights.

@WorkingDir is C:\WINDOWS\System32

$CmdLineRaw is different for each command. One example is:

Yours, Jiddo.

Hi,

this is a bad nut....

The WPKG service crashed when trying to start up. It seems like the service itself needs to run as the Local SYSTEM user in order to function at all

Have a look at System Eventlog. Maybe the error code gives you a hint (google for errorcode or post it).

"\\path-to-network-share\WPKG\software\printer\printer-delta3.exe" check

1) Be sure, that the 'running' user has at least read and execute permission on the share

2) Debugging: Just put a MsgBox (0,"", $USERNAME & @CRLF & $DOMAIN & @CRLF & $PASSWORD & @CRLF & $CmdLineRaw) before your RunAs Line

;-))

Stefan

Link to comment
Share on other sites

Have a look at System Eventlog. Maybe the error code gives you a hint (google for errorcode or post it).

We found the following in the system logs:

WPKG Service trying start...

WPKG Service->RegisterServiceCtrlHandler: successfuly done

WPKG Service->SERVICE_START_PENDING: successfuly done

Starting WPKG on startup

Before create shared memory: successfuly done.

A required resource was unavailable.

Working done. Perform cleanup.

EventID: 1000

Faulting application WPKGSrv.exe, version 1.0.0.11, faulting module msvcr90.dll, version 9.0.21022.8, fault address 0x0005bb47.

And in the system logs:

EventID: 7034

The WPKG Service service terminated unexpectedly. It has done this 1 time(s).

1) Be sure, that the 'running' user has at least read and execute permission on the share

2) Debugging: Just put a MsgBox (0,"", $USERNAME & @CRLF & $DOMAIN & @CRLF & $PASSWORD & @CRLF & $CmdLineRaw) before your RunAs Line

By running user you mean Local SYSTEM, right? If so, it does not have any read access to the network share, and we have no way of granting it to him. This is the main reason why we are working on this solution in the first place. If we could in fact use the SYSTEM user to access the files, we would only need to use RunAs in one particular package, but as that is not possible we have to use it in just about all of them.

We have verified that the username, domain and password as well as $CmdLineRaw is in fact correct. For this we used a debugging method much similar to your step 2. Another fact that makes us even more sure is the fact that it works when the script is run by any domain user.

Yours, Jiddo.

Edited by Jiddo
Link to comment
Share on other sites

Oh well. Thanks for the effort.

Does anyone else have an idea of what might be wrong?

Yours, Jiddo.

Hi,

I installed only WKPG Client 1.3.6 on my WinXP SP3 machine. For changing service Account to administrative account, the User account needs at minimum 2 rights:

1) Log on as a service (you've already checked)

2) Replace a process level token

;-))

Stefan

Link to comment
Share on other sites

Actually, we decided to try our luck with a custom C++ approach to this problem, and after a while we did manage to code our own, very simple runas wrapper command which does execute properly in our environment. At least it is working well under Windows XP SP2. On Windows 2000 we are getting some mixed results however. One of our w2k machines gives a weird error when running it, but the other w2k machine handles it just fine. We have no clue why.

In this working C++ solution we are using the CreateProcessWithLogonW function, which seems to work. We also tried to use a combination of LogonUser and CreateProcessAsUser, but this turned out to be way too complicated for our rather limited C++ knowledge. The interesting thing is that CreateProcessWithLogonW is not supposed to work when executed as LocalSystem on Windows XP SP2. See the following quote from the MSDN documentation:

http://msdn.microsoft.com/en-us/library/ms682431(VS.85).aspx

Windows XP with SP2 and Windows Server 2003: You cannot call CreateProcessWithLogonW from a process that is running under the LocalSystem account, because the function uses the logon SID in the caller token, and the token for the LocalSystem account does not contain this SID. As an alternative, use the CreateProcessAsUser and LogonUser functions.

Still, for us it works just fine. Does anyone know why?

Also, since the AutoIT RunAs and RunAsWait functions does not seem to work properly when run as LocalSystem it might be good if the AutoIT developers would take a look at this problem, and our solution. Maybe future versions of AutoIT can fix this problem.

Here is the C++ code we are using:

#define _WIN32_WINNT 0x0500

#include <iostream>
#include <sstream>
#include <cstring>
#include <fstream>
#include <windows.h>

using namespace std;

void printError();
WCHAR* asciiToUnicode(const char* string);

int main(int argc, const char* argv[]) {

    if(argc < 5) {
        std::cout << "Missing one or more command line arguments." << std::endl;
        std::cout << "Usage: RunAsExecutor username domain password command" << std::endl;
        ExitProcess(1);
    }

    WCHAR* wUsername = asciiToUnicode(argv[1]);
    WCHAR* wDomain = asciiToUnicode(argv[2]);
    WCHAR* wPassword = asciiToUnicode(argv[3]);

    std::stringstream ss;
    for(int i = 4; i < argc; i++) {
        if(i != 4) {
            ss << " ";
        }
        bool quote = strchr(argv[i], ' ') != NULL;
        ss << (quote ? "\"" : "");
        ss << argv[i];
        ss << (quote ? "\"" : "");
    }

    std::cout << "The command to be executed is: " << ss.str().c_str() << std::endl;

    WCHAR* wCommand = asciiToUnicode(ss.str().c_str());

    PROCESS_INFORMATION pi;
    STARTUPINFOW si;
    DWORD exitCode;

    ZeroMemory(&si, sizeof(STARTUPINFOW));
    si.cb= sizeof(STARTUPINFOW);
    si.lpDesktop = TEXT(L"winsta0\\default");

    BOOL ret = CreateProcessWithLogonW(
                wUsername,
                wDomain,
                wPassword,
                1,
                NULL,
                wCommand,
                CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
                NULL,
                NULL,
                &si,
                &pi);

    delete[] wCommand;
    delete[] wUsername;
    delete[] wDomain;
    delete[] wPassword;

    if(ret) {
        WaitForSingleObject(pi.hProcess, INFINITE);
        if(GetExitCodeProcess(pi.hProcess, &exitCode)) {
            ExitProcess(exitCode);
        } else {
            printError();
            ExitProcess(14);
        }
    } else {
        printError();
        ExitProcess(13);
    }

    return 0;
}


void printError() {

    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf = NULL;
    DWORD dw = GetLastError();

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );

    std::cout << "Error(" << dw << "): " << (LPTSTR)lpMsgBuf << std::endl;

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);

}


WCHAR* asciiToUnicode(const char* string) {
    int length = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, NULL, 0);
    WCHAR* wcharBuffer = new WCHAR[length];
    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, wcharBuffer, length);
    return wcharBuffer;
}

Yours, Jiddo.

Link to comment
Share on other sites

You have to forgive me on this one, but what is a process level token? How do I replace it?

Yours, Jiddo.

Hi,

MMC Snap In -> Group Policy -> Local Computer Policy -> Computer Configuration -> Windows Settings -> Security Settings -> Local Policy -> User Rights Assignment

;-))

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...