Invoking a script as part of a web api method : how bad an idea is it? - powershell

I have a powershell script (but I think these considerations could be extended to any script that requires a runtime to interpret and execute it) that does what I also need to expose to a web application front end as a REST API to be called and I've been asked to call directly the script itself from the web method but although technically feasible, having a web api method that starts a shell/process to execute the script and redirecting stdin/stdout/stderr looks like a very bad practice to me. Is there any specific security risk in doing something like this?

Reading this question brings to mind how many of the OWASP Top Ten Security Vulnerabilities it would expose your site to.
Injection Flaws - This is definitely a high risk. There are ways to remediate it, of course. Parameterizing all input with strongly-typed dates and numbers instead of strings is one method that can be used, but it may not fit with your business case. You should never allow user-provided code to be executed, but if you are accepting strings as input and running a script against that input, it becomes very difficult to prevent arbitrary code execution.
Broken Authentication - possibly vulnerable. If you force a user to authenticate before reaching your script (you probably should), there is a chance that the user reuses their credentials elsewhere and exposes those credentials to a brute force attack. Do you lock out accounts after too many tries? Do you have two-factor authentication? Do you allow weak passwords? These are all considerations when you introduce a new authentication mechanism.
Sensitive data exposure - likely vulnerable, depending on your script. Does the script allow reading files and returning their contents? If not now, will it do so in the future? Even if it's never designed to do so, combined with other exploits the script might be able to read a file from a path that's outside the web directory. It's very difficult to prevent directory traversal exploits that would allow a malicious user access to your server, or even the entire network. Compiled code and the web server prevent this in many cases.
XML External Entities - possibly vulnerable, depending on your requirements. If you allow user-provided XML, the bad guy can inject other files and create havoc. This is easier to trap when you're using standard web tools.
Broken Access Control - definitely vulnerable. A Web API application can enforce user controls, and set permission levels in a C# controller. Exceptions are handled with HTTP status codes that indicate the request was not allowed. In contrast, Powershell executes within the security context of the logged in user, and allows system-level changes even if not running escalated. If an injection flaw is exploited, the code would be executed in the web server's security context, not the user's. You may be surprised how much the IIS_USER (or other Application Pool service account) can do. For one, if the bad guy is executing in the context of a service account, they might be able to bring down your whole site with a single request by locking out that account or changing the password - a task that's much easier with a Powershell script than with compiled C# code.
Security Misconfiguration - likely vulnerable. A running script would require it's own security configuration outside whatever framework you are using for the Web API. Are you ready to re-implement something like OAuth Claims or ACLs?
Cross-Site Scripting - likely vulnerable. Are you echoing the script output? If you're not sanitizing input and output, the script could echo some Javascript that sends a user's cookie content to a malicious server, giving them access to all the user's resources. Cross site request forgery is also a risk if input is not validated.
Insecure Deserialization - Probably not vulnerable.
Using Components with Known Vulnerabilities - greatly increased vulnerability, compared to compiled. Powershell grants access to a whole set of libraries that would otherwise need explicit references in a compiled application.
Insufficient Logging & Monitoring - likely vulnerable. IIS logs requests by default, but Powershell doesn't log anything unless you explicitly write to a file or start a transcript. Neither method is designed for concurrency and may introduce performance or functional problems for shared files.
In short, 9 out of the top 10 Vulnerabilities may affect this implementation. I would hope that would be enough to prevent you making your script public, at the very least. Basically the problem is that you're using the tool (Powershell) for a purpose it wasn't intended to fulfill.

Related

Trigger reboot and script execution, securely

I am using PowerShell to manage Autodesk installs, many of which depend on .NET, and some of which install services, which they then try to start, and if the required .NET isn't available that install stalls with a dialog that requires user action, despite the fact that the install was run silently. Because Autodesk are morons.
That said, I CAN install .NET 4.8 with PowerShell, but because PowerShell is dependent on .NET, that will complete with exit code 3010, Reboot Required.
So that leaves me with the option of either managing .NET separately, or triggering that reboot and continuing the Autodesk installs in a state that will actually succeed.
The former has always been a viable option in office environments, where I can use Group Policy or SCCM or the like, then use my tool for the Autodesk stuff that is not well handled by other approaches. But that falls apart when you need to support the Work From Home scenario, which is becoming a major part of AEC practice. Not to mention the fact that many/most even large AEC firms don't have internal GP or SCCM expertise, and more and more firm management is choosing to outsource IT support, all to often to low cost glorified help desk outfits with even less GP/SCCM knowledge. So, I am looking for a solution that fits these criteria.
1: Needs to be secure.
2: Needs to support access to network resources where the install assets are located, which have limited permissions and thus require credentials to access.
3: Needs to support remote initiation of some sort, PowerShell remote jobs, PowerShell remoting to create a scheduled task, etc.
I know you can trigger a script to run at boot in System context, but my understanding is that because system context isn't an actual user you don't have access to network resources in that case. And that would only really be viable if I could easily change the logon screen to make VERY clear to users that installs are underway and to not logon until they are complete and the logon screen is back to normal. Which I think is really not easily doable because Microsoft makes it near impossible to make temporary changes/messaging on the logon screen.
I also know I can do a one time request for credentials on the machine, and save those credentials as a secure file. From then on I can access those credentials so long as I am logged in as the same user. But that then suggests rebooting with automatic logon as a specific user. And so far as I can tell, doing that requires a clear text password in the registry. Once I have credentials as a secure file, is there any way to trigger a reboot and one time automatic logon using those secure credentials? Or is any automatic reboot and logon always a less than secure option?
EDIT: I did just find this that seems to suggest a way to use HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon without using a plain text DefaultPassword. The challenge is figuring out how to do this in PowerShell when you don't know C#. Hopefully someone can verify this is a viable approach before I invest too much time in trying to implement it for testing. :)
And, on a related note, everything I have read about remote PowerShell jobs and the Second Hop Problem suggests the only "real" solution is to use CredSSP, which is itself innately insecure. But it is also a lot of old information, predating Windows 10 for the most part, and I wonder if that is STILL true? Or perhaps was never true, since none of the authors claiming CredSSP to be insecure explained in detail WHY it was insecure, which is to me a red flag that maybe someone is just complaining to get views.

Passing Parameters and Running Powershell Script

I'm unsure if what I'm trying to do is possible. I have a PowerShell script that takes three arguments. In a perfect world, I'd collect the necessary information in a web form and pass it to the script, which would then run.
I don't know if this is even possible, but I can't find anything that definitively tells me no. I'd need it to be cross-browser capable (we have some Macs) so I can't just do an IE-only fix.
This is also internal only, so I'm less concerned about some security risks. It will be behind our firewall.
Thanks.
Not sure to understand the question, but for collecting the necessary information in a web form and pass it to the script, which would then run I user PowerShell Web Server (tag : poshserver in stackoverflow). Sources are available, so I even implements Jobs for long scripts.

Office 365 Powershell authentication without storing credentials

I want to provide some administrative services that will be implemented against the Office365 PowerShell, but I don't want to store decryptable administrators credentials - is there any option for authenticating without direct usage of the credentials? I am thinking about something like OAuth or another application key system.
Not 100% clear from the question but since you don't want to store creds I assume that this will be running on client computers rather than on systems that are directly under your control. I can think of two options but they both add considerably to the complexity of a script like this.
Option 1
Split your script into 2 pieces, one set up as a web listener on a server that is running with elevated privileges and the other running on the system where you want the script to be placed that makes REST calls to your web listener, this lets you only expose the functions that you actually want the lower-privileged script to have access to without having to deal with storing the creds. This is more complex to set up but doesn't require anything third-party to be in place.
Option 2
Use a privledged identity management system(I'm most familiar with CyberArk but any of them should be ok for this purpose) to store the creds, You would then sign your script with a certificate and set the identity manager to only allow a process signed with that cert and connecting from a known valid IP to access the credential, again using a web call. This is easier to do once you get the PIM installed but that can be a massive headache to do properly, not to mention expensive.
Hope I understood the problem correctly and that one of these methonds helps you.

Why it's not enough to prevent SQL injection from front-end?

All most all the resources about preventing SQL injection are talking about preventing it from fron-end and back-end ,with database level. Why do we need to do all those things?
Is it not enough to do it from front end, by just preventing the user from sending malicious SQL codes as inputs.
Because most client-side code can be bypassed since it executes on the client's machine. Basically any code that protects against bad input on the client-side is there to provide better feedback for an honest user and also to reduce low-hanging fruit type of attacks.
The back-end code is there to make sure any malicious user who bypassed your front-end security (with a crafted http request or w/e) will not be able to inject bad input into one of your SQL dynamic query. This is usually achieved by sanitizing input on the back-end and using parameterized queries.
Just because you button up your front-end doesn't guarantee SQL Injection safety. All the front end does is show pretty things to the user. The back end is where all the work is done and because the front-end must talk to the back-end in some way means you have a potential security issue.
I don't know if your application will be Winforms or a Web application, but that doesn't matter. I can use a program such as Process Explorer to manipulate the data that gets sent to your back-end, if its a Windows application.
If its a web application, then, similarly, I can use a tool such as Fiddler to manipulate the data that gets sent to your back end.
Moral of the story is always button up your back end and never let your back end assume that the data its getting from the front end is hunky dory!
Defense in-depth is a really, really good thing. Consider this, your app takes values as parameters to a query or perhaps even take user input to form a query. You do the right thing at the app level to correctly escape the input so injection attempts do nothing there and data is safely read or written to the database. Now, what if
the data that is written to the database itself is malicious code? The next stored procedure that reads from the table may now be executing random code.
the application code passes the "safe" data to the backend which is then used in a stored procedure or function (e.g. de-serialize, cast, etc...). Once again, you could be executing malicious code.
You could argue that instead of escaping the input, you could parse the input at the app level to strip/reject certain value, strongly type, regex everywhere, etc... but there are many situations where these restriction cannot be implemented because the app is intended to support free-flow text that may legitimately have suspicious looking characters especially if you support international character sets. (E.g. names, descriptions, notes, etc...).
Finally, do/should/can DBAs really count on the app or app dev to get everything right every time?

REST: how to tell server to do some background process

I am building a client-side product with REST. All user interaction will be done with a browser (the config stuff will be on a server running on localhost). I want everything to be REST compliant, even though the application will be running on a client's machine on localhost and will never be accessible from the outside.
The commands are pretty simple:
update
restart
sync
Here's what I've come up with:
POST to / with 'action' parameter (JSON) detailing specifics
PUT a new resource
subsequent GET requests will return the status
when the command is complete, the resource is deleted
What would be the most RESTful way to implement this?
Note:
I'm not asking for scrutinization of my software architecture. I have reasons for choosing a REST interface instead of a unix domain socket, CLI interface, or even a regular GUI interface. The justification would overcomplicate the question and make it too localized.
I have had the same need on a couple of different projects (both client only and server) and I am looking for community input on best practices.
I would POST to a /process resource with the appropriate parameters necessary to start the process, then I would have it return a Location header to that resource that actually represents the process status (/process/123). You can then use GET on that process to get the latest information about it.
I would not automatically delete the process, because if you do that, the client will not know if the process finished properly or not, just simply that it finished (well, stopped running).
Noting that, the client can certainly DELETE the resource when it is done, or you can clean it up later after some reasonable time where whoever was interested in it is likely not to be any more.