Talking about Shell Injection

What is Shell injection

Shell injection is also called OS command injection, which refers to the use of vulnerabilities in the program to construct a string of malicious instructions to make the target program execute the attacker's command. Shell injection is named from the Unix shell, but most programs running on systems that allow programs to call the command line interface may inadvertently introduce shell injection-related vulnerabilities. Interfaces with potential risks of Shell injection include those in Java java.lang.Runtime.exec()and .NET System.Diagnostics.Process.Start().

Compared with vulnerabilities such as SQL injection, Shell injection is rarely mentioned, but because it can directly contact resources outside the program, it usually has a more serious impact.

This article was written because a shell injection vulnerability was discovered in a demo program written by a friend, so I rewritten the program as an example at the beginning. In the following Java code, the front-end passes the docker image name to the back-end server, and the back-end server calls the docker pullcommand to pull the corresponding image file.

String imageName = (String) params.get("imageName");
String cmd = "docker pull " + imageName;
Process process = Runtime.getRuntime().exec(cmd);
// ...

When the imageNameparameter value passed by the front end is a normal image name (for example nginx), the docker pull nginxcommand will be executed to pull the nginx image. And the imageNameparameter value passed in by the front end nginx; echo hacked, that is , when there is a malicious instruction echo hacked, the back end program will docker pull nginxexecute the echo hackedcommand after successful execution . In order to demonstrate convenience and avoid misoperation, intuitive and harmless echocommands are used here. The result of running this command directly in the terminal is as follows:

# 示例中省略了执行结果与本文无关的一些输出信息
$ docker pull nginx; echo hacked
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
hacked # <- 此处为执行恶意命令的结果

Next, we will introduce various ways of Shell injection with a PHP program from DVWA.

Shell injection method

The following is a PHP program that will accept a parameter ip from the client as the parameter of the ping command and output the result of the operation.

$target = $_REQUEST['ip'];
$cmd = shell_exec('ping -c 4 ' . $target);

echo "<pre>{
      
      $cmd}</pre>";

In this section, several Shell injection methods will be introduced through the above procedures. The examples will use commands with intuitive and harmless results as demonstrations.

  • ; Continuous instruction

When using a continuous command command1; command2, the command1command will continue to be executed after the command2command has been executed. In an example, when the parameter is input by the user 127.0.0.1; echo hacked, the program is executed first ping -c 4 127.0.0.1command, execution will proceed to complete echo hackedthe command. The output of this command running in the terminal is as follows:

$ ping -c 4 127.0.0.1; echo hacked
PING 127.0.0.1 (127.0.0.1): 56 data bytes
# ... ping的执行结果
4 packets transmitted, 4 packets received, 0.0% packet loss
hacked # <- echo hacked的执行结果
  • pipeline |

By command1 | command2using a pipe, it will complete execution command1as its output after the command2input. For example, input parameters 127.0.0.1 | grep loss, the program will ping -c 4 127.0.0.1output command as grep lossan input command. The command grep losswill output the line with loss in the output of the ping command, for example:

$ ping -c 4 127.0.0.1 | grep loss
4 packets transmitted, 4 packets received, 0.0% packet loss
  • & Background execution

Use after &the command means that the command will be executed in the background. When &other commands are followed ( command1 & command2), they will be executed in the background command1and in the foreground command2. For example, a command ping -c 4 127.0.0.1 & echo hackedwill be executed in the background ping -c 4 127.0.0.1and execute the echo hackedcommand. Generally, the result of this command is as follows:

$ ping -c 4 127.0.0.1 & echo hacked
[1] 2333 # <- ping命令的进程号
hacked # <- echo hacked的执行结果
PING 127.0.0.1 (127.0.0.1): 56 data bytes
# ... ping的执行结果

Note: The pingcommand involves network I/O, so the output is after the echocommand, not after the pingcommand is echoexecuted.

  • &&versus||

&&And ||similar, use both command1 && command2or command1 || command2. The difference between the two is && command2that the middle is command2only command1executed after the execution is successful (exit code is 0), and the || command2middle is command2only command1executed after the execution fails (the exit code is a non-zero value).

  • `command`versus$(command)

Both types of actions will execute commandcommands. When the command is command1 $(command2)the time ( command1 `command2`the same token), command2outputted as a command1parameter. Such as user input parameters is $(echo hacked), the program execution pingbefore will first execute echo hackedthe command.

In addition to the above-described manner in several shell injection, e.g. redirection ( >, , >>, <) <<and the like may also be used by an attacker.

Shell injection defense measures

  • Avoid directly executing commands entered by the user

In the program, you should try to avoid executing commands through the command line interface, or you should avoid directly using the data entered by the user as the parameters of the shell command. Like the Docker command at the beginning of the article, you can use the API interface provided by Docker to pull the corresponding image instead of using the docker pullcommand directly .

  • Verify the parameters entered by the user

As in the ping program in the above example, assuming that the parameter it needs is an IPv4 address, the format of the parameter can be checked through regularization to see if it is a valid IPv4 address string.

$target = $_REQUEST['ip'];
if (!preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $target)) {
    
    
  throw new Exception('Invalid ip');
}

$cmd = shell_exec('ping  -c 4 ' . $target);

echo "<pre>{
      
      $cmd}</pre>";
  • Filter common symbols

Mentioned above includes a filter |, &, ;and other symbols, if desired parameter comprises a particular symbol, the symbol can be escaped. For example, the echo hacked \&command will not be executed in the background, and the output result is hacked &.

  • Use black and white list mechanism

Create a black and white list to limit the parameters allowed by the command.

  • Use the transcoding method provided by the language

Some languages ​​provide methods for transcoding shell parameters, such as those in php escapeshellarg(), but they cannot be fully trusted to be safe.

  • Use the least privileged user to run the program

For example, in a web application, users with the minimum required permissions are used to run the application. This measure is not a real defensive measure. It aims to avoid a greater impact after being attacked, and it is not limited to being used to deal with Shell injection.

Reference

Guess you like

Origin blog.csdn.net/ghosind/article/details/106198393