The documentation of capurex, states that the function never invokes the shell.
My assumption:
Since no shell is invoked, characters like * or ; will not get interpreted and therefore can't do harm.
This is why calls to external programs are not (or less) susceptible to accidentally malformed input or intended injection attacks as shown in the example below (sorry for the German output messages):
use v5.26;
use IPC::System::Simple 'capturex';
# (very) vulnerable to shell injection
say `ls @ARGV`;
# just a visual line
say '----------';
# no shell injection "possible" (?)
say capturex('ls', @ARGV);
The output:
user@host:-$ perl shell-injection.pl -1 \*.pl \; hostname
shell-injection.pl
host
----------
ls: Zugriff auf '*.pl' nicht möglich: Datei oder Verzeichnis nicht gefunden
ls: Zugriff auf ';' nicht möglich: Datei oder Verzeichnis nicht gefunden
ls: Zugriff auf 'hostname' nicht möglich: Datei oder Verzeichnis nicht gefunden
"ls" unexpectedly returned exit value 2 at shell-injection.pl line 11.
user@host:-$
My Questions:
What terminologies can be used to describe, how the code is executed with capturex? What are examples / techniques / terms used in other languages or environments? (e.g. system call?)
Is it actually advisable to use this technique without input checking (I assume not) and if not, for what reason (attack vector)?
The best way to get informed about how capturex operates is by looking at its source.
The sub implements its own piped open in "list-form", to work around the (ancient!) v5.6.x limitations. It does so by fork-ing a process using piped open and then "manually" exec-ing the command in the child, where it can use the list-form. Then the output is read in the parent. Follow the word "pipe" in the open page, and then the link to perlipc.
So there can be no shell involved since exec in the LIST form uses execvp(3) system call to directly run the command. (What may happen when it runs with a single argument as well, if it contains no shell meta-charactes.) Thus the characters that (would) have a special meaning in the shell may be used freely as literal characters in the command.
As for the second question -- if a command is formed with user-input it must always be checked really carefully! Note that one shouldn't literally use input in a command, but rather support keywords and parameters based on which the program composes the command. Avoiding the shell of course helps but any user input must be checked.
The injection bug is more of a programming error, whereby variable interpolation isn't used right and results in an unintended command; there is no need for malicious acts there, just for the "right" input that exposes the bug.
All capturex does is save you from having to form a valid shell command. Some validation may still be needed.
What terminologies can be used to describe, how the code is executed with
capturex?
The source for the latest version of IPC::System::Simple is found here.
On non-Windows systems, capturex uses the fork and execve system calls via the open(my $pipe, '-|') and exec BLOCK LIST Perl functions respectively. This form of Perl's exec function executes the program directly rather than invoking a shell.
exec "ls foo"; # Executes /bin/sh
exec { "/bin/sh" } "/bin/sh", "-c", "ls foo"; # Equivalent to previous.
exec { "ls" } "ls", "foo"; # Executes ls
Is it actually advisable to use this technique without input checking (I assume not) and if not, for what reason (attack vector)?
What if you provide a relative path to the program to execute and the user set the PATH env var being used?
What if you provide a relative path to a file as an argument and the user set the current work directory?
What if you pass a string that starts with a -? That could be interpreted as an option rather than argument. (This is why you'd use 'ls', '--', $file instead of 'ls', $file.)
What if you pass ../../../../../../etc/passwd? That could have undesired effect if the program uses the argument in a file path.
What if you pass a regex to a program, and the regular expression would take longer than the lifespan of the universe to fail to match?
It's possible that some validation still needs to occur. All capturex does is save you from having to form a valid shell command.
It might be the receiving program's job to do the validation, it might be yours, or it might be a combination.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With