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.
Related
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.
We have a piece of software used in our business that requires admin rights to run. However the staff are not allowed access to accounts with admin rights. This is within a windows 7 environment.
We have set-up a local admin accounts on the required computers through GPO.
The aim of the software I am creating to to launch the software that requires admin rights as this local admin account.
So far the software is working correctly in that it is launching the software as the account but it is still giving the errors that it gives when it does not have admin rights. If you right click and runas on the software and type in the account details manually it works fine.
SecureString pwd = new SecureString();
foreach (char c in "somepassword") { pwd.AppendChar(c); }
var psi = new ProcessStartInfo
{
FileName = location,
UserName = "localadminaccountname",
Domain = Environment.MachineName,
Password = pwd,
UseShellExecute = false,
Verb = "runas"
};
try
{
Process.Start(psi);
}
There is an exception catch statement with error reporting included with the code. There are no exceptions thrown when Process.Start(psi) is called. (Updated)
Thanks.
EDIT
The company build of windows 7 has User Access Control set to "Never Notify" so no UAC pop-up is shown when Process.Start(psi) is called.
If UAC is set to "Never Notify" then it is disabled - the user runs with the maximum set of privileges.
That means that if the user is an admin account, using the "runas" verb is unnecessary. It also means that if the user is NOT an admin account, it's possible that your application may stil fail to work (because the user can't elevate and OTS (over-the-shoulder) elevation is disabled.
Have you tried setting 'Load user profile' true for the IIS app pool? I had a similar situation. This worked for me.
Refer for more info:
Security exceptions in ASP.NET and Load User Profile option in IIS 7.5
I tried
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = filename,
UserName = "System",
UseShellExecute = false,
},
};
process.Start();
but it yields
Win32Exception was unhandled
Login failed: unknown user name or wrong password
I will have to use CreateProcessAsUser?
How can I get the appropriate parameters to pass to that method?
The System accounts password is maintained interally by Windows (I think) i.e. attempting to start a process as the System account by supplying credentials in this way is ultimately destined to failure.
I did however find a forum post that describes a neat trick that can be used to run processes under the system account by (ab)using windows services:
Tip: Run process in system account (sc.exe)
Alternatively the Windows Sysinternals tool PsExec appears to allow you to run a process under the System account by using the -s switch.
The Username should be LocalSystem if you want to run your process with high privileges (it's a member of Administrators group) or LocalService for normal privileges
EDIT: My mistake LocalSystem & LocalService are not regulary users and, therefore, they cannot be provided as a username. Kragen's solution is the right one
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();
I have problem with starting processes in impersonated context in ASP.NET 2.0.
I am starting new Process in my web service code. IIS 5.1, .NET 2.0
[WebMethod]
public string HelloWorld()
{
string path = #"C:\KB\GetWindowUser.exe";
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WorkingDirectory = Path.GetDirectoryName(path);
startInfo.FileName = path;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
startInfo.ErrorDialog = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
Process docCreateProcess = Process.Start(startInfo);
string errors = docCreateProcess.StandardError.ReadToEnd();
string output = docCreateProcess.StandardOutput.ReadToEnd();
}
The "C:\KB\GetWindowUser.exe" is console application containing following code:
static void Main(string[] args)
{
Console.WriteLine("Windows: " + WindowsIdentity.GetCurrent().Name);
}
When I invoke web service without impersonation, everything works fine.
When I turn on impersonation, following error is written in "errors" variable in web service code:
Unhandled Exception: System.Security.SecurityException: Access is denied.\r\n\r\n at System.Security.Principal.WindowsIdentity.GetCurrentInternal(TokenAccessLevels desiredAccess, Boolean threadOnly)\r\n at System.Security.Principal.WindowsIdentity.GetCurrent()\r\n at ObfuscatedMdc.Program.Main(String[] args)\r\nThe Zone of the assembly that failed was:\r\nMyComputer
Impersonated user is local administrator and has access to C:\KB\GetWindowUser.exe executable.
When I specify window user explicitly in ProcesStartInfo properties Domain, User and Password, I got following message:
http://img201.imageshack.us/img201/5870/pstartah8.jpg
Is it possible to start process with different credentials than ASPNET from asp.net (IIS 5.1) ?
You have to put privileged code into the GAC (or run in Full trust).
The code in the GAC must assert the XXXPermission, where XXX is what ever permission you are requesting, be it impersonation, access to the harddrive or what have you.
You should revert the assert immediately afterwords.
You should make sure that the API on your DLL that you put in the GAC has no opportunities for abuse. For example, if you were writing a website for letting users backup the server via a command line application, your API should old expose a method like "BackUp()" and not "LaunchAribitraryProcess(string path)"
The web.config file must have impersonation set up as well, or you will run into NTFS permission problems as well as CAS.
Here is the complete explanation.
You might also try wrapping your code inside
using (Impersonator person = new Impersonator("domainName", "userName",
"password")
{
// do something requiring special permissions
}
as mentioned in
http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework.windowsforms/topic62740.aspx
What exactly are you trying to do? I can't quite see what the point of your code is in creating a different executable. It looks rather odd. Perhaps it would be more helpful to state the busines problem you are trying to solve first.
It looks like you're trying to have the IIS service impersonate a user with higher privileges than the service itself (in this case, an administrator). Windows blocks this as a security hole, since at that point you're basically begging someone to take over your system. There may be a way to work around this limitation, but don't do that--it's for your own good.
Instead, have IIS impersonate a user with limited permissions, who has exactly the rights that you need it to have. E.g. create a user account that owns only the folders that you want your web service to write to, or whatever other combination of rights is appropriate. If impersonating a limited user, you won't see this error code, but should still be able to call the benign executable you have here.