0

I have an ASP .NET WEb Forms project, and I want to execute power-shell script to update hosts file.

private void ExecutePowerShellScript(string scriptToExecute)
{
    using (PowerShell powershelInstance = PowerShell.Create())
    {
        var authManger = powershelInstance.Runspace.RunspaceConfiguration.AuthorizationManager;
        powershelInstance.AddScript(scriptToExecute);

        Collection<PSObject> results = powershelInstance.Invoke();

        if (powershelInstance.Streams.Error.Count > 0)
        {
            throw powershelInstance.Streams.Error[0].Exception;
        }

        foreach (var result in results)
        {

        }
    }

}

There is the script:

 $hostsPath = "$env:windir\System32\drivers\etc\hosts";
 $hosts = get-content $hostsPath; 
 [System.Collections.ArrayList]$arr = $hosts;
 $arr.Add(someValueHere);
 $arr | Out-File $hostsPath -enc ascii;
 # returns results;
 $arr;
 # end of the script";

I tried this: Invoke(Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted);

then this paste Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted in the beginning of the script. Use this Set-ExecutionPolicy Unrestricted - same and same error. ccess to the path C:\Windows\System32\drivers\etc\hosts' is denied.

The script works perfectly if I ran into console application.

Update: I am running Visual Studio as administrator.

Update 2: OK, now I am using the ImpersonatedUser ,but another exception occur. "Requested registry access is not allowed."

StackTrace:

at System.ThrowHelper.ThrowSecurityException(ExceptionResource resource)
at Microsoft.Win32.RegistryKey.OpenSubKey(String name, Boolean writable)
at System.Environment.GetEnvironmentVariable(String variable, EnvironmentVariableTarget target)
at System.Management.Automation.ModuleIntrinsics.SetModulePath()
at System.Management.Automation.ExecutionContext.InitializeCommon(AutomationEngine engine, PSHost hostInterface)
at System.Management.Automation.AutomationEngine..ctor(PSHost hostInterface, RunspaceConfiguration runspaceConfiguration, InitialSessionState iss)
at System.Management.Automation.Runspaces.LocalRunspace.DoOpenHelper()
at System.Management.Automation.Runspaces.RunspaceBase.CoreOpen(Boolean syncCall)
at System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace rsToUse, Boolean isSync)
at System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings)

at System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection1 input, PSDataCollection1 output,

using (ImpersonatedUser impersonatedUser = new ImpersonatedUser(username, domain, password))
{
    using (PowerShell powershelInstance = PowerShell.Create())
    {
        powershelInstance.AddScript(scriptToExecute);

        //When the .Invoke() method is called, an exception with message "Requested registry access is not allowed." was thrown.
        Collection<PSObject> results = powershelInstance.Invoke();

        if (powershelInstance.Streams.Error.Count > 0)
        {
            throw powershelInstance.Streams.Error[0].Exception;
        }
    }
}
mihkov
  • 983
  • 9
  • 34

2 Answers2

1

Your ASP.NET executes the PowerShell script with the credentials of the worker process of the application pool, which is probably not administrative account (unless you changed it).

Modifying the hosts file is restricted to administrative accounts only, and you should consider very carefuly before you change the credentials of the worker process.

If you want to make this change then follow the instructions here: https://technet.microsoft.com/en-us/library/cc771170(v=ws.10).aspx

Again, this change can affect make your application more vulnerable to security exploits (since any exploit found in your application can be used with administrative privileges).

You may also need to turn off UAC (User Account Control) if its turned on.

Another way, is by using impersonation for temporarily elevation of your privilages. You can see a sample of a class that allow you this (wrap evething up) here: https://blogs.msdn.microsoft.com/joncole/2009/09/21/impersonation-code-in-c/

Hope this helps.

Shahar Gvirtz
  • 2,278
  • 1
  • 15
  • 17
  • you can use impersonation, but the risks are still the same. I added it to my answer. – Shahar Gvirtz Apr 19 '16 at 16:00
  • Make sure the user you impersonated to is administrator account, that you ran powershell as this user and changed the executionpolicy and check if it helps. – Shahar Gvirtz Apr 20 '16 at 07:14
  • I think it's administrator , it's the only one user that I have. You mean to pass "Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted" in the invoke method ? – mihkov Apr 20 '16 at 07:22
  • Check if the user is in the Administrators group on your server. I mean log-in as this user (if it's not your regular user) and run the exact command you wrote once. Did you disable the UAC too? – Shahar Gvirtz Apr 20 '16 at 07:24
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/109631/discussion-between-mihkov-and-shahar). – mihkov Apr 20 '16 at 07:31
  • I have tried almost everything, no more ideas. Turning off UAC doesn't help, also using a `RunspaceFactory.CreateRunspace()` and calling the `.Open()` method throws a same exception on **Update 2**, and finally try with `SPSecurity.RunWithElevatedPrivileges(() => { mycode }` not working. Any Other suggestions.? – mihkov Apr 20 '16 at 08:57
0

I found some other solution, but maybe it's not the best. In IIS server just add a new Application pool. In the advanced settings change the identity to custom account and enter your credentials to windows. Use the new application pool to the site.

mihkov
  • 983
  • 9
  • 34