MVC: start process as different user - not working - c#

I need to run an executable on the server from an MVC controller. Problem: the executable sits within Program Files folder and will also read a value from registry.
I have granted execution rights on the respective folder to my application pool.
So here's my problem:
Running the exe just with Process.Start(exe) will start the executable which in turn then exits with an error because it cannot read the registry value (no access).
Assigning a local admin user to ProcessStartInfo fails:
var exe = #"C:\Program Files (x86)\[path to exe]";
var secString = new SecureString();
secString.AppendChar('character');
//...
secString.MakeReadOnly();
var procInfo = new ProcessStartInfo(exe, settingsPath)
{
UseShellExecute = false,
UserName = "[username]",
Domain = "[domain]",
Password = secString,
RedirectStandardError = true,
RedirectStandardOutput = true,
RedirectStandardInput = true,
Verb = "runas"
};
var proc = Process.Start(procInfo);
proc.WaitForExit();
This will cause a crash of conhost and the executable.
Using impersonation like this:
var impers = new ImpersonationService();
impers.PerformImpersonatedTask("[user]", "[domain]", "[password]",
ImpersonationService.LOGON32_LOGON_INTERACTIVE, ImpersonationService.LOGON32_PROVIDER_DEFAULT, new Action(RunClient));
...with the method RunClient() simply using Process.Start(exe) will do absolutely nothing! The method is run but the process is not being started. I know that the method is run because I added this line to it:
_logger.Debug("Impersonated: {0}", Environment.UserName);
Which correctly gives me the desired user name the process shall use. That user has local Admin privileges, so there should not be an issue there.
I have even tried starting a different executable from my Controller and have that one use impersonation (both variants) to start the target executable - same outcome.
So right now I'm at a dead end. Can anyone please tell me what I'm doing wrong and what I have to do to make it work?
P.S: running the target executable directly on the server when logged in as the local admin user works perfectly fine, so no prob with the exe itself.
Edit:
It seems one part of my description was incorrect: with impersonation and RunClient method I actually did not use Process.Start(exe) but this:
var procInfo = new ProcessStartInfo(exe, settingsPath)
{
UseShellExecute = false,
};
_logger.Debug("Impersonated: {0}", Environment.UserName);
var proc = Process.Start(procInfo);
Out of desperation I have now circumvented procInfo(don't actually need it) and really called
var proc = Process.Start(exe, argument);
And now the .exe starts! It seems using ProcessStartInfo overrides the impersonation for the process??
Still not OK though, as now I get an "Access denied" error. Despite being local admin. This is just weird.
Edit 2:
This is how my latest attempt went:
Switched back to calling a helper .exe, passing the same arguments later used for the actual target exe in Program Files
added a manifest to that helper exe with level="requireAdministrator"
Added Impersonation to my helper exe according to https://msdn.microsoft.com/en-us/library/w070t6ka(v=vs.110).aspx with [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")] added before the method starting the target process.
Started the process by providing ProcessStartInfo with all the jazz
Resulting code:
try
{
var secString = new SecureString();
//...
secString.MakeReadOnly();
var procInfo = new ProcessStartInfo()
{
FileName = Path.GetFileName(exe),
UserName = "[UserName]",
Domain = "[domain]",
Password = secString,
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
RedirectStandardInput = true,
Arguments = settingsPath,
WorkingDirectory = #"C:\Program Files (x86)\[rest]"
};
var proc = Process.Start(procInfo);
proc.WaitForExit();
if (proc.ExitCode != 0)
{
using (var sw = new StreamWriter(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "error.log"), true))
{
sw.WriteLine("Error running process:\r\n{0}", proc.ExitCode.ToString());
}
}
}
catch (Exception ex)
{
using (var sw = new StreamWriter(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "error.log"), true))
{
sw.WriteLine("Error running process:\r\n{0}\r\nRunning as: {1}", ex.ToString(), WindowsIdentity.GetCurrent().Name);
}
}
Resulting output to error.log:
Helper running!
[passed argument]
Error running process: System.ComponentModel.Win32Exception
(0x80004005): Access denied at
System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo
startInfo) at System.Diagnostics.Process.Start() at
System.Diagnostics.Process.Start(ProcessStartInfo startInfo) at
RunClient.ImpersonationDemo.RunClient(String settingsPath)
Running as: [correct domain user in Admin group]
So I can start the helper exe but that cannot start the real exe in Program Files due to Acess denied despite running under a local Admin account and all files access locally, not on network drives.
The logic of this eludes me.
Edit 3
Update: I have added a manifest to the target .exe also,
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
This means I now:
Call a helper exe from the controller: works
The helper .exe has a manifest to run with elevated rights (Admin)
The helper .exe uses impersonation to assume the identity of a local admin to start a process
Said process is started using a ProcessStartInfo in which username, domain, and password are additionally set to the same local admin user
The helper exe then tries to run the target exe using Process.Start(Startinfo) with the local admin user set, while still impersonating that user's windows identity
And still the error log spouts "Access denied" while correctly returning WindowsIdentity.GetCurrent().Name as that of the local admin.
And now, the greatest of all happened: I created a new local user on that server, added him to local admin group and used that user for impersonation just in case there is a problem with domain users. Guess what? Now I get an error Access denied to ...\error.log - written to the effing error log.
Really?
Edit 4
I think I'll try TopShelf to convert this shebang to a service. Hope to get this done over the weekend.

According to this article your mvc controller thread should have full-trust permission to run the process:
This class contains a link demand at the class level that applies to
all members. A SecurityException is thrown when the immediate caller
does not have full-trust permission. For details about security
demands, see Link Demands.
Seems you problem is not the user but full-trust. I do not know which version of MVC you use but you can read the articles Trust Levels and Code Access to find out the best way to configure your application. Seems you can grant full-trust permission only to specific .exe file or grant full-trust permission to application pool user (do not forget about folder permissions).
But the best approach is to write some windows service and run it instead of running some .exe file directly.

You can try trust level in web.config of your application
<system.web>
<securityPolicy>
<trustLevel name="Full" policyFile="internal"/>
</securityPolicy>
</system.web>

Related

Process.Start(); as another user works but explorer.exe iexplore.exe throws exception

I'm having problems with a program and its buttons (I know, I'm awesome lol) the buttons can be "programmed" to run programs. They also can be set to run as admin (different credentials).
If I set up simply notepad or cmd or explorer it runs like charm. But if I start iexplore it has got no admin rights.
I had problems before with running explorer.exe the solution was that I had to run it by typing the full path C:\windows\explorer.exe to be able to run it but that I solved it by setting up the VB2015 compiler (?) to Platform target: x64.
My other problem is that if I try to run dsa.msc or generally anything ends with msc it throws the following exception, even if I set up the full path to the syswow64 (or the system32) folder like c:\windows\syswow64\dsa.msc
"The specified executable is not a valid application for this OS platform."
Running the C:\Windows\System32\mmc.exe "services.msc" (or syswow64, with or without the /computer= switch) throws
"The requested operation requires elevation." which I have since I'm able to run services.msc (and all other msc-s from command line with the same user rights)
Thank you.
A beginner.
Basically you don't need to run the host app as administrator! There is a variable (inside your Process instance) called StartInfo (which is an instance of the ProcessStartInfo Class), where Verbs could be used as followed:
Process p = new Process()
{
StartInfo = new ProcessStartInfo("E:\\Users\\Temp\\app.exe")
{
Verb = "runas"
}
};
p.Start();
This will prompt the user to run the app.exe as administrator.
Edit
Running a Process as a defined user:
Process p = new Process()
{
StartInfo = new ProcessStartInfo("E:\\Users\\Temp\\app.exe")
{
Verb = "runas",
Arguments = "/user:Vira"
}
};
For more information about those RUNAS Arguments, click me! :)

Process.Start exception: "The directory name is invalid"

I have an implementation of the Process.Start method that fails on my Windows 7 Professional 64-bit development machine, while working in our Windows 2008 test environment.
const string CommandDirectory = #"C:\Program Files (x86)\Command";
var process = new Process
{
StartInfo =
{
FileName = string.Format("{1}{0}MyExecutable.exe", Path.DirectorySeparatorChar, CommandDirectory),
RedirectStandardError = true,
RedirectStandardOutput = true,
UseShellExecute = false,
UserName = userName,
Password = securePassword,
Domain = "MYDOMAIN",
},
};
process.Start();
At process.Start();, I get the following exception on my development machine:
System.ComponentModel.Win32Exception occurred
HResult=-2147467259
Message=The directory name is invalid
Source=System
ErrorCode=-2147467259
NativeErrorCode=267
StackTrace:
at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start()
InnerException:
I have tried a few things:
I have ensured that the user account I assign to the process has full rights on the path where the executable lies, as well as the %systemroot% location. I have also ensured the user has "Impersonate a client after authentication" rights in the Local Security Policy.
I have tried explicitly setting the ProcessStartInfo.WorkingDirectory to CommandDirectory. When I do this, the executable launches but immediately crashes, without explanation.
I've made this function on my development machine by removing the UserName, Password, and Domain properties such that it uses my personal credentials. But this is not practical for deployment. This makes it seem to me that it the problem is related to credentials and permissions.
Can anyone advise what I am doing wrong?
#Julien Lebosquain's comment led me to the answer. I needed to log on locally one time as the user I wanted to impersonate. This created the default user folders.
Presumably, the executable I was calling needed to write to AppData or another subfolder of the user directory.

exe file is unable to create txt file from IIS

I have created an WebApi project in which I am calling a exe namely Latlong2XY.exe which takes input file and outputfile as paramreter. And returning me a .txt as output file. When I am executing the application from VS2012 IDE it is successfully creating the required txt file. However when I publish the same application in IIS and running it then it is not able to create the txt file.
it appears IIS Express is creating the txt file while IIS is not.
It appears to be some permission issue. But does not have any clue what to do.
My code is:
int exitCode;
// Prepare the process to run
ProcessStartInfo start = new ProcessStartInfo();
// Enter in the command line arguments, everything you would enter after the executable name itself
start.Arguments = #"D:\RFD\InputFile.txt D:\RFD\Results.txt";
// Enter the executable to run, including the complete path
start.FileName = #"D:\RFD\Latlong2XY.exe";
// Do you want to show a console window?
start.WindowStyle = ProcessWindowStyle.Hidden;
start.CreateNoWindow = true;
// Run the external process & wait for it to finish
using (Process proc = Process.Start(start))
{
proc.WaitForExit();
// Retrieve the app's exit code
exitCode = proc.ExitCode;
}
IIS settings are :
Windows Authentication: disabled;
Forms Authentication: disabled;
Anon auth: enabled;
.Net Impersonation: disabled.
i'm using ASP.NET v4.0 Application pool.
You will need to give the application directory (where the hosted files are on the machine) elevated privileges. (Typically C:\inetpub\wwwroot\YourAppName)
Give the user 'IIS_USR' or something close to that name write access to the folder.
Yes., When you perform these kind of operations from "Visual Studio IDE" It will work because IDE has minimum permission to control your IO operations for (System.Diagnostics.Process.Start).
When you go to Web application hosting from IIS, unfortunately IIS doesn't have these permission settings in built. So you need to set permissions to perform windows native operations.
Note : By using this you are gonna provide your system(server) username and password as encrypted.
You can set windows authentication permission in the Web Config Using Aspnet_setreg.exe. Which will be available in internet with usage notes.
Add the below line in your webconfig:
<authentication mode="Windows"/>
<identity impersonate ="true" userName="registry:HKLM\SOFTWARE\YourAPPName\ASPNET_SETREG,userName" password="registry:HKLM\SOFTWARE\YOURAPPNAME\ASPNET_SETREG,password"/>
The similar problem i have faced during development of "windows service Re-Start from web". The Same permission issues i have resolved and got worked on this way.
This answer may not be perfect. But this is also one way to achieve the solution

Permission issue running .exe from ASP.NET web application

We have a .exe which we need to execute at the time an order is placed on a website. When
we test this locally it works fine using IIS Express. When we move it to IIS, it fails. We assume this is a permissions error as if we set the App Pool to run as the administrator then the script works again. The question we have is how do we execute the .exe as the administrator whilst the App Pool is ApplicationIdentity? We are using the following code:
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = executablePath,
Arguments = argumentList,
Domain = domain,
UserName = userName,
Password = securePassword,
UseShellExecute = false,
LoadUserProfile = true
}
};
process.Start();
process.WaitForExit();
process.Close();
The .exe is trying to write to the Users AppData folder which is why it fails. It is a 3rd party app so we cannot change the source code.
EDIT: Just to clarify also, when we specify the username and password in procmon it still appears to run from ISUR.
We fixed this by enabling User profile on IIS AppPool and setting permission for the IIS user on the folder it was trying to write to.
We sue ProcMon to find where the program was failing and the folder it was trying towrite to was C:\Windows\System32\config\systemprofile
i dont remember actually, but one of them is working 100% ( i had this issue before)
just let me know ehich one of them is the correct one.

Process start and Impersonation

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.

Categories