Question:
I have a windows service that downloads a script and then runs it.
I’ve been trying to make my windows service more secure, making it accept only signed power-shell scripts.
I have ran the Set-ExecutionPolicy AllSigned command on the server, and this works in the windows power shell command prompt.
However, my code still runs both signed and unsigned scripts, even if the set-executionpolicy is set to restricted.
I have tried two approaches:
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
1 2 3 4 5 6 7 8 9 10 |
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration); runspace.Open(); RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace); Pipeline pipeline = runspace.CreatePipeline(); pipeline.Commands.AddScript(@"Set-ExecutionPolicy AllSigned"); pipeline.Commands.AddScript(@"Get-ExecutionPolicy"); pipeline.Commands.AddScript(script); Collection |
And another approach:
1 2 3 4 5 6 7 8 |
using (PowerShell ps = PowerShell.Create()) { ps.AddCommand("Set-ExecutionPolicy").AddArgument("Restricted"); ps.AddScript("Set-ExecutionPolicy Restricted"); ps.AddScript(script); Collection } |
In both situations the code runs unsigned scripts as well.
Have I missed something?
Answer:
I found the solution. The only way to restrict the code from running unsigned scripts was to check the scripts myself with Get-AuthenticodSignature:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public bool checkSignature(string path) { Runspace runspace = RunspaceFactory.CreateRunspace(); runspace.Open(); RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace); Pipeline pipeline = runspace.CreatePipeline(); pipeline.Commands.AddScript(String.Format("Get-AuthenticodeSignature \"{0}\"", path)); Collection Signature check = (Signature)results[0].BaseObject; runspace.Close(); if (check.Status == SignatureStatus.Valid) { return true; } return false; } |
Thanks,
Dan