Prompt for credentials in ASP.NET / C# page, pass to PowerShell

4.7k views Asked by At

I'm looking to build a proof of concept / demo webpage that will:

  • Run as a service (no authentication required initially)
  • Prompt for credentials (i.e. to allow providing alternate credentials, ideally capture this as System.Management.Automation.PSCredential). No authentication is required here, I just need to capture the credentials.
  • Pass credentials in to PowerShell (e.g. shell.Commands.AddArgument(pscred) )
  • Use these credentials in PowerShell (pass in as, or convert to System.Management.Automation.PSCredential)
  • To clarify: I do not want to authenticate credentials. I just want to collect them in a secure way. For all I care at the moment, it is gibberish, but gibberish that I presumably want to protect

I have an ASP.NET Web Application project with Visual C# (similar to the one here). I have the page up and running (i.e. it runs with the appropriate account, it runs PowerShell, etc.) - I want to prompt for and store credentials in a reasonably secure manner. I assume there is some standard way to do this. Or am I reading too much into this as this is a server side application?

Here are excerpts from my code thus far:

  • Default.aspx (these will be changed depending on the scenario):

    <asp:TextBox ID="Input" runat="server" TextMode="MultiLine" Width="400px" Height="73px" ></asp:TextBox>  
    <asp:TextBox ID="InputParam" runat="server" TextMode="MultiLine" Width="200px" Height="20px" ></asp:TextBox>  
    <asp:Button ID="ExecuteCode" runat="server" Text="Execute" Width="200" onclick="ExecuteCode_Click" />
    <asp:TextBox ID="ResultBox" TextMode="MultiLine" Width="700" Height="200" runat="server"></asp:TextBox>
    <asp:TextBox ID="ErrorBox" TextMode="MultiLine" Width="700" Height="200" runat="server"></asp:TextBox>
    
  • Default.aspx.cs:

    protected void ExecuteCode_Click(object sender, EventArgs e)
    {
        // Clean the Result TextBox
        ResultBox.Text = string.Empty;
    
        // Initialize PowerShell engine
        var shell = PowerShell.Create();
    
        // Add the script and an argument to the PowerShell object
        shell.Commands.AddScript(Input.Text);
        shell.Commands.AddArgument(InputParam.Text);
    
        // Execute the script
        var results = shell.Invoke();
    
        // display results, with BaseObject converted to string
        // Note : use | out-string for console-like output
        if (results.Count > 0)
        {
            // We use a string builder ton create our result text
            var builder = new StringBuilder();
    
            foreach (var psObject in results)
            {
                // Convert the Base Object to a string and append it to the string builder.
                // Add \r\n for line breaks
                builder.Append(psObject.BaseObject.ToString() + "\r\n");
            }
    
            // Encode the string in HTML (prevent security issue with 'dangerous' caracters like < >
            ResultBox.Text = Server.HtmlEncode(builder.ToString());
        }
    
        //Collect errors
        var PSErrors = shell.Streams.Error.ReadAll();
    
        if (PSErrors != null)
        {
    
            // We use a string builder ton create our error text
            var builder = new StringBuilder();
    
            foreach (var psError in PSErrors)
            {
                // Convert the exception Object to a string and append it to the string builder.
                // Add \r\n for line breaks
                builder.Append(psError.Exception.ToString() + "\r\n");
            }
            // Encode the string in HTML (prevent security issue with 'dangerous' caracters like < >
            ErrorBox.Text = Server.HtmlEncode(builder.ToString());
        }
    
    }
    
  • This code won't work from what I understand, but the concept is exactly what I am looking to do.

    PSCredential pscred = this.Host.UI.PromptForCredential("Enter username/password","", "", "");
    shell.Commands.AddArgument(pscred);
    
1

There are 1 answers

3
HAL9256 On BEST ANSWER

I think the easiest way is to use impersonation. i.e. you get the credentials of the user, and launch the powershell process as that user which allows you to execute anything you want as that user.

See:

Execute PowerShell cmdlets from ASP.NET With User Impersonation - Has steps to impersonate the current user to run PowerShell

or

How to run PowerShell scripts from ASP.NET with Impersonation - StackOverflow question on how to run PowerShell with impersonation.