flawopen.com/Command Injection/C#
Imagine a secretary who runs errands. If an untrusted visitor hands the secretary a memo saying 'Deliver mail AND transfer bank funds', command injection is the secretary executing both without questioning the paper.
In .NET, launching external tools using System.Diagnostics.Process with concatenated strings assigned to ProcessStartInfo.Arguments causes command injection when user input contains shell delimiters.
Critical vulnerabilities in Windows desktop applications and ASP.NET management portals have resulted in full SYSTEM privilege escalation via unquoted command paths and argument injection.
Microsoft Security Response Center (MSRC) advisories.// Concatenating into Arguments string
var psi = new ProcessStartInfo
{
FileName = "cmd.exe",
// Attacker input: "test.txt & net user /add evil Password123!"
Arguments = $"/c type {userInput}",
RedirectStandardOutput = true
};
Process.Start(psi);
// Using ArgumentList (.NET Core / .NET 5+) without shell
var psi = new ProcessStartInfo
{
FileName = "notepad.exe"
};
// Arguments added individually to ArgumentList are never parsed as shell commands
psi.ArgumentList.Add(userInput);
Process.Start(psi);
In .NET Core, ArgumentList properly escapes each argument according to the Win32 / POSIX command-line conventions before passing it to the operating system's CreateProcess API.
If FileName is set to cmd.exe, Windows will parse the arguments using its command shell rules regardless of whether you use ArgumentList.
Windows cmd.exe and powershell.exe support command chaining with &, &&, and | just like Linux shells.
grep -rn "ProcessStartInfo.*Arguments\s*=" --include="*.cs" .
ProcessStartInfo.ArgumentList.Add() instead of ArgumentsFileName to cmd.exe or powershell.exe with user inputsYou must manually escape quotes with backslashes according to the Win32 CommandLineToArgvW rules, or upgrade to .NET 6/8+ to use ArgumentList.