SecLab
Injection & Output EncodingwalkthroughDifficulty 3/524 min

Command injection: do not go through a shell

Objective: After this lesson you can invoke an external program with no shell in between, and know why shell escaping is a dead end.

V1CWE-78A05:2025command-injection
Step 1 of 5 · read5 min

The shell is an interpreter you did not need

Command injection has a property that makes it more serious than any other injection: it is not confined to one subsystem. SQL injection gives an attacker the database account's privileges. Command injection gives them the application process's — meaning every file it can read, every API it can call, and an outbound connection.

But this lesson is not about severity. It is about something simpler: in almost every case, you did not need a shell.

When you write Process.Start("bash", $"-c \"convert {file} out.png\"") you are doing two things: invoking convert, and starting a full interpreter to parse a command string first. The second is the thing you did not need and the thing that creates the hole. A shell is what understands ;, |, &&, $(...), ` `, > and *` — and each of those is an escape route.

If you invoke convert directly with an argument array, no shell exists, so no character carries special meaning. ; rm -rf / becomes a very strange filename, and convert reports that it cannot find it.

This is the same principle as SQL parameterisation, and it is worth stating plainly because it recurs at every interpreter:

InterpreterWrong wayRight way
SQLConcatenate into the statementParameters
ShellConcatenate into a command lineAn argument array, no shell
HTMLConcatenate into markupEncode for the context
XMLThe default parserDisable external entities

Why shell escaping is a dead end, even with a library for it: escape correctly for which shell? bash, sh, cmd.exe and PowerShell have four different rule sets, and cmd.exe is famously impossible to escape correctly in all cases. Remove the shell and the question stops existing.

View path

Comments

Join the discussion
Sign up to comment

Commenting needs an account with at least one completed lesson. That condition is what keeps this thread worth reading: every point belongs to someone who can be asked back, and reputation accrues over time.

Sign upSign in

You can still read every comment below without an account. Signing in brings you back to this exact spot, not to the top of the page.

Loading comments…