November 06, 2003

Secure Coding: Spawning external processes securely in Windows

Today I thought I would give everyone a good secure coding tip as it relates to executing external processes programmatically under Windows. Recently I was reviewing different ways to do this through .NET for C#, and started digging deeper into the Windows API to follow the execution path of the various calls.

Most developers use ShellExecute. It seems harmless enough as in the docs it is explained as a wrapper around the CreateProcess() API call. But thats wrong. It might wrap the CreateProcess() call, but it does so in a way that exposes your code to the potential of tainted data injection, or more to the point misdirection threats.

ShellExecute() uses the built in file association data stored in the registry to determine which process will be passed to CreateProcess. So if you feed it *.DOC file and Word is installed, it will execute Word accordingly. The problem with this is that an attacker could modify the association and point it to their malicious program. In doing so, you increase the attack surface of your application as you have untrusted data determining your code execution path. Very bad. Very bad indeed.

A more secure way to do this is to call CreateProcess() directly. But I wouldn't even recommend that. What I would recommend would be to use the the CreateProcessAsUser() API. It is similar to CreateProcess() but you can force the new process to run in the security context of the user you truely want to execute as. You can create a security descriptor to tie this down even further, and even use a restricted token to ensure this new process has only the required access to do its task. Remember, all code execution should be ran with least privilege whereever possible. If you would like to learn more on how to do this, check out the CreateRestrictedToken() API.

If you need to spawn secondary processes in Windows, forget using ShellExecute(). Instead, use CreateProcessAsUser(). If yer in C#, you will need to P/Invoke this, but thats not all that hard.

Posted by SilverStr at November 6, 2003 11:08 AM | TrackBack
Comments

This is bullshit. If an attacker can modify the association with .doc on your machine. You are already owned. There are dangers with ShellExecute but you don't mention them. Most of the dangers revolve around the attacker setting the value of the lpfile param.

Posted by: aj at November 29, 2003 10:15 AM

Thats a nice assumption, but incorrect in context. A power user, (or even a limited account for that matter in certain cases) can easily modify their own file associations, which means so too can the attacker. You are not OWNED because of this interaction.

However, the fact that it can be modified covertly and then executed allows for an attack vector of an unsafe code execution path that the unsuspected user will run. That is the bigger threat... and the one I was trying to point out.

You are right in pointing out that the lpfile param is quite dangerous, but I felt I didn't need to muddy up the waters any more since I was already recommending NOT to use it.

I notice you don't disagree with the fact using ShellExecute is a bad thing, when there are safer functions like CreateProcessAsUser(). Although we disagree on what is a bigger threat when using ShellExecute, the fact remains that there are safer, and better alternatives. That was the point of my post.

To each his own. Thanks for commenting on my blog. Good insight here.

Posted by: SilverStr at November 29, 2003 05:40 PM

Do you know if it is possible to redirect browser, IE, to URL at another application directory on same IIS server using CreateProcessAsUser?

I'm using LogonUser() to authenticate on anonymous aspx page and want to redirect authenticated user to secure page. So far, only works with Server.Transfer with same app directory.

Thanks!

Posted by: Mark Peacock at December 8, 2003 07:23 AM