Service not running for Impersonated user with CreateProcessAsUser [C#] - c#

There is a LocalSystem Service (Job.exe) which performs a certain absolutly required task (key), this service is run for all users (at least when they logon).
There is another LocalSystem Service (Serv.exe) which uses CreateProcessAsUser(...) to launch a process as a different (admin) user.
There are 2 accounts, USER (which is the one logged-on) and ADMIN.
So this is the scenario ...
User logs in to USER account (non-admin) and both LocalSystem Services (Job.exe & Serv.exe) start and work without any problems... Then at a certain point Serv.exe calls CreateProcessAsUser() using the ADMIN account in order to launch an administrative task (note that USER is currently logged in).
So far everything is fine - but now a problem happens - the process run by CreateProcessAsUser(...) under the ADMIN is not subject to the LocalSystem service JOB.exe - for example if JOB.exe monitors file-system changes and logs them if I launch a task with CreateProcessAsUser(...) under ADMIN that changes files I would assume JOB.exe would log these - but it does NOT ...
So it looks like JOB.exe is NOT running in the context of the ADMIN account when launched using CreateProcessAsUser(...), this is a big deal for me - I need to ensure JOB.exe LocalSystem service is absolutly always running - even when CreateProcessAsUser(...) is used...
Is there anything I can do to solve this problem? any help would be much appreciated.
Can I load the environment? profile? something to kick-in JOB.exe so that it actually works?
Thanks,

You could try running the process as an admin by putting it in an exe and then using the C# Process object to kick it off, using code similar to the below:
process.StartInfo.FileName = toolFilePath;
process.StartInfo.Arguments = parameters;
process.StartInfo.WorkingDirectory = Path.GetDirectoryName(toolFilePath);
process.StartInfo.Domain = domain;
process.StartInfo.UserName = userName;
process.StartInfo.Password = decryptedPassword;
process.Start();
process.WaitForExit();
process.Close();

Related

How can a C# program run another program with admin privileges?

I have a problem with this situation:
I made 2 programs:
The first one just print an output saying that was launched with admin provileges or not, and the second one, execute the first program with admin privileges and without use the UAC. The trouble is that the second program can't launch the first with admin privileges i don't know why.
This is my code:
Code of the first program:
// This only prints if you start as administrator or not.
bool isElevated;
WindowsIdentity identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
isElevated = principal.IsInRole(WindowsBuiltInRole.Administrator);
Console.WriteLine("I got admin privileges?: "+isElevated);
Code of the second program:
// This execute the first program with admin privileges without UAC
string username = "myuser";
SecureString userpass = new SecureString();
userpass.AppendChar('m');
userpass.AppendChar('y');
userpass.AppendChar('p');
userpass.AppendChar('a');
userpass.AppendChar('s');
userpass.AppendChar('s');
Process program = new Process();
program.StartInfo.UserName = username;
program.StartInfo.Password = userpass;
program.StartInfo.FileName = "Path/First_program.exe";
program.StartInfo.UseShellExecute = false;
program.Start();
PD: I don't want the user to open the UAC, thats why i already insert the username and the password.
Thanks in advance.
You have half of the answer. The other half is that the program must request to be executed with elevated privileges. By default, Windows programs run in a "Basic" trust level, regardless of the true level of permissions possible under the user. To gain access to administrative powers, the program must request elevation, which by definition will involve UAC.
Programs like yours can request elevation using the runas verb in the ProcessStartInfo, or by specifying requireAdministrator elevated permissions in the manifest of either application (assuming you control them). Either way, if UAC is enabled, the user will get a prompt.
The only way to circumvent this is to set up the program that would otherwise require elevated permissions as a Windows service, configured in services.msc to run with administrative permissions. You'll get one UAC prompt when installing/registering the service to run in this way, and from then on the service can perform that task without any further UAC action. You can then use various communication technologies, from named pipes to true network comms like TCP, to signal the service that it should do what you want.

Register dll to gac as another user

I have an application that requeres to register a dll into a gac on a client computer everytime a new dll is deployed the problem is that the client computers only have restricted users with UAC turned on.
The application knows the credentials of a user that has admin rights.
The problem is if I have processStartInfo.UseShellExecute = false; then I can't get trough the UAC getting the error "The requested opperation requires elevation"
and if I have processStartInfo.UseShellExecute = true; then it does not allow to run the whole thing as a different user: "The process object must have UseShellExecute property set to false in order to start the process as a user"
internal static void Register(String assemblyName)
{
ProcessStartInfo processStartInfo = new ProcessStartInfo(lcDir + "gacutil.exe", string.Format("/i {0}.dll", assemblyName));
processStartInfo.UseShellExecute = false;
processStartInfo.WorkingDirectory = lcDir;
processStartInfo.UserName = lcUser;
processStartInfo.Password = Password;
processStartInfo.Domain = lcDomain;
processStartInfo.Verb = "runas";
Process process = Process.Start(processStartInfo);
process.WaitForExit();
}
I would like to know what the "Best practice" for that kind of thing is? I know the whoe concept looks to windows like a virus.
What I would like to achive the following:
User dosen't need to know an account with admin rights
The credencal's of the admin user are saved in the program's database
As much as possable Automated registration.
You should run this part of your code as Administrator.
What you need is impersonation.
See this article
Aricle Impersonation on Code project
You are not meant to embed such user strings within an application for security reasons.
The design idea is that you deploy using System Management Services or similar to manage the deployment (which sucks).
I got round it my using private assemblies, very similar to the way unix works.
If you are looking to add class support in SQL Native Client, then you will find it is an uphill struggle to get deployed each time.
If you know a local administrator name and password, you could use a central deployment solution and not try to get your app to impersonate an administrator.

Start process from System Account with a specific User Name

I'm developing a windows service in C#.net, Account: LocalSystem, System: Windows XP SP3
I want this service to check for all currently logged users if a specific application is running and if not - start this application AS corresponding user name.
I provide domain, name, password, but Start() throws Win32Exception
exception "Access is denied"
process.StartInfo.Domain = domain;
process.StartInfo.UserName = name;
process.StartInfo.Password = password;
process.StartInfo.FileName = fileName;
process.StartInfo.UseShellExecute = false;
process.Start();
The user whose credentials I provide is in administrator group - the application successfully runs if started manually.
Is this accomplished in a different way?
Thank you!
How are you checking for applications which are running? In Windows Vista and newer, there is separation between the services and desktops. This may mean that you cannot access the desired information and the service is bombing out for that reason. There is an 'allow interaction with desktop' or similar check box in the service dialog. You might want to try enabling that.

Why can't my ASP.NET web service kick off a process, but my .NET console app can?

This is code from a class library:
proc.StartInfo = new ProcessStartInfo(CmdPath, "+an -b");
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.UseShellExecute = false;
proc.Start();
proc.WaitForExit();
This works perfectly as I would expect when called from a console test app. When I take the same library and call the method from an ASP .NET web service it just hangs.
Is there something I am missing here, perhaps permissions? The ASPNET service has access to the folder where the EXE is, and I see it running in Task Manager, though it isn't doing anything.
If anyone could tell me what I'm doing wrong, I would appreciate it. Thanks.
EDIT: Sorry for the lack of information. CmdPath goes to the command line interface for our scheduling software. I'm passing in commands based on the documentation they provided. I have one method to get a list of jobs, and another method to run a job. ...hmm idea. The client normally uses Active Directory to login, I think impersonation is going to be necessary. Going to test now.
EDIT 2: Ok, now the client is blowing up with AccessViolation issues. This is obviously a permissions thing. If the software uses integrated AD authorization, and I impersonate my AD account, will that be sufficient? I'm doing impersonation using the tag in web.config.
I think you will face a lot of problems launching an executable server side using the ASPNET identity, have you tried impersonating an identity with appropriate priveleges (this does work btw), but again launching an executable on the server side is probably not a good idea to begin with.
The ASP.Net user account probably doesn't have permissions to execute. Can you give a bit more information as to why you are trying to do this as there may be a better way of doing it.
It could be a permissions issue. The ASPNET service may have permissions to the executable, but does it have permissions for everything the executable does.
For example, if the executable copies files, does the ASPNET account have full rights to the source and destination paths of those files? The same questions need to be asked of everything the executable does.
If you need to get around this, you can use impersonation, or assign the web site to run under a different account in IIS, but those are not recommended practices, and more trouble than they're worth in most cases.
By default the ASP.NET worker process has less security than most local account (certainly an account that a developer uses or the logged in account on a server.)
There are two main ways to move forward:
Give the asp.net process more priviledges. See This Link for a good explanation of how to do that.
Have asp.net run under an account with more priviledges. See This Link for a good explanation and how to get that process running under a different account.
Either will work for you.
When you redirect standard output don't you need to use ReadToEnd to read the response from StandardOutput?
You probably should check what is your executable performs, cos ASP.NET works under user with limited rights (NETWORK SERVICE on IIS 6.0) and you executable also gets this rights and runs under same user. As far as you waiting on until it finishes its work, probably something wrong in the executable you are trying to run. I suggest you to make a simple experiment - switch your WebApplication to build-in in VS web server, called "Casini" and check your code behavior. By means of this you can prove yourself that it's not ASP.NET's fault. If I am right the only thing you will need to do is to investigate problems of you executable and determine what rights it needs.
Instead of Impersonation or giving Asp.net more privileges, how about launching the process under different credentials.
In the sample below, UserWithVeryLimitedRights would be a new account that you create with just enought rights to run the app.
Doing so may minimize the security risks.
ProcessStartInfo StartInfo = new ProcessStartInfo();
SecureString ss = new SecureString();
string insecurePassword = "SomePassword";
foreach(char passChar in insecurePassword.ToCharArray()) {
ss.AppendChar(passChar);
}
StartInfo.RedirectStandardInput = true;
StartInfo.RedirectStandardError = true;
StartInfo.RedirectStandardOutput = true;
StartInfo.CreateNoWindow = true;
StartInfo.UseShellExecute = false;
StartInfo.Password = ss;
StartInfo.UserName = #"UserWithVeryLimitedRights";
StartInfo.FileName = #"c:\winnt\notepad.exe";
Process.Start(StartInfo);

Write Access to Program Files folder

my application include a self-updater executable that is used to update the application.
One of the first steps the updater is performing is to check that it does have write permission to the application folder
IPermission perm = new FileIOPermission(FileIOPermissionAccess.AllAccess, _localApplicationCodebase);
if (!SecurityManager.IsGranted(perm))
{
OnProgressChanged("Security Permission Not Granted \n The updater does not have read/write access to the application's files (" +
_localApplicationCodebase + ")",MessageTypes.Error);
return false;
}
OnProgressChanged("Updater have read/write access to local application files at " + _localApplicationCodebase);
return true;
When executing under Win7/Vista, this code pass (meaning that according to CAS, the code does have write access), however when I try to write files, I got an Access Denied (and I confirmed that the files are NOT in use)
I understand that Vista/Win7 UAC is preventing users from writing files in the program files folders. However, what I don't understand is why the permission is granted if in reality it is not
Regards,
Eric Girard
PS : If I run the same code using 'Run As Administrator', it works fine
The important thing to know about UAC is that by default, no code runs with Administrator privileges and thus cannot write to the Program Files directory. Even if you are logged in as an administrator, the apps are launched with standard user privliges.
There are two ways around this. You can have the user start the app with the Run As Administrator menu item. But this relies on the user to remember something. The better was is to embed a manifest into your executable that requests administrator privileges. In the manifest, set requestedExecutionLevel to requireAdministrator. This will cause UAC to prompt the user for admin credentials as soon as the app starts.
As Daniel said, the best solution is to put the updating functionality in a separate application. Your primary app will have an manifest that sets the requestedExecutionLevel to "asInvoker" and your updater app with request "requireAdministrator". Your primary app can run with standard privileges. But when the update needs to happen, use Process.Start to launch the updater application that requires the user to enter the admin credentials.
The best way to write an auto updater is to have a secondary application. The first program calls the second with elevated privileges, prompting UAC. Then the second application can install the patches.
I'm not sure if this is what you're trying to do, but I've found this post helpful. The included code let's you detect if you're app is running on Vista, if UAC is enabled and if user is elevated.
http://www.itwriting.com/blog/198-c-code-to-detect-uac-elevation-on-vista.html
then restart your app with runas to let user elevate permissions
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.Verb = "runas";
processInfo.FileName = Application.ExecutablePath;
Process.Start(processInfo);

Categories