主动信息搜集:Scapy完成基于TCP、UDP的主机发现
在内网中,好的信息搜集能力能够帮助开发者更快地拿到权限及达成目标。内网里数据多种多样,需要根据需求寻找任何能对下一步渗透行动有所帮助的信息。现介绍搜集信息的一种方法,基于TCP、UDP的主机发现。这是一个位于传输层的主机发现,可以用来探测远程主机存活、端口开放、服务类型以及系统类型等信息,相比于三层主机发现更为可靠,用途更广。
运 行 环 境:
OS:macOS Monterey Version 12.3.1(英文版)
IDE:PyCharm 2020.1
相关代码如下:
一、TCP(Transfer Control Protocol, 传输控制协议)
TCP连接是一种面向连接的、可靠的传输通信协议,位于IP层之上,应用层之下的中间层。每一次建立连接都基于三次握手通信,终止一个连接也需要经过四次握手,建立完连接之后,才可以传输数据。当主动方发出SYN连接请求后,等待对方回答TCP的三次握手SYN+ACK,并最终对对方的SYN执行ACK确认。这种建立连接的方法可以防止产生错误的连接,所以TCP是一种可靠的传输协议。因此我们可以利用TCP三次握手原理进行主机存活的探测。当向目标主机直接发送ACK数据包是,如果目标主机存活,就会返回一个RST数据包以终止这个不正常的TCP连接。也可以发送正常的SYN数据包,如果目标主机返回SYN/ACK或者RST数据包,也可以证明目标主机为存活状态。其工作原理主要依据目标主机响应数据包中的flags段,如果flags字段有值,则表示主机存活,该字段通常包括SYN、FIN、ACK、PSH、RST、URG六种类型。SYN表示建立连接,ACK表示应答,PSH表示包含DATA数据传输,RST表示连接重置,URG表示紧急指针。现借助Scapy库来完成,在安装好Scary的终端输入Scary运行程序。本例中远程主机IP地址为192.168.68.150,flag标志为A表示给目标主机直接发送ACK应答数据包,通过sr1()函数将构造好的数据包发出。
1. 启 动 命 令
(venv) (base) liuxiaowei@MacBookAir 渗透测试框架 % sudo scapy
启动界面如下图:
2. 相 关 代 码
>>> ip=IP()
>>> tcp=TCP()
>>> r=(ip/tcp)
>>> r[IP].dst='192.168.68.150' # 目标IP 192.168.68.150
>>> r[TCP].flags='A' # 直接给目标主机发送ACK应答数据包
>>> a=sr1(r) # 通过sr1()函数将构造好的数据包发出
Begin emission:
Finished sending 1 packets.
...*
Received 4 packets, got 1 answers, remaining 0 packets
>>> a.display() # 通过a.display()函数查看目标主机的返回数据包信息
运行结果如下:
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 40
id = 50034
flags = DF
frag = 0
ttl = 64
proto = tcp
chksum = 0x6d19
src = 192.168.68.150
dst = 192.168.68.242
\options \
###[ TCP ]###
sport = http
dport = ftp_data
seq = 0
ack = 0
dataofs = 5
reserved = 0
flags = R # 表示远程主机给源主机发送了一个REST,由此可以验证远程目标主机为存活状态
window = 0
chksum = 0xa4a3
urgptr = 0
options = ''
###[ Padding ]###
load = '\x00\x00\x00\x00\x00\x00'
通过a.display()函数查看目标主机的返回数据包信息, 此时发现flags标志位为R,表示远程主机给源主机发送了一个RST。由此可以验证远程目标主机为存活状态。
## 二、UDP(User Datagram Protocol, 用户数据报协议)
UDP协议是一种利用IP提供面向无连接的网络通信服务。UDP会把应用程序发来的数据,在收到的一刻立即原样发送到网络上。即使在网络传输过程中出现丢包、顺序错乱等情况时,UDP也不会负责重新发送以及纠错。当向目标发送一个UDP数据包以后,目标是不会发回任何UDP数据包的。不过如果目标主机处于活跃状态,但是目标端口是关闭状态时,会返回一个ICMP数据包,这个数据包的含义为unreachable。如果目标主机不处于活跃状态,这时是收不到任何响应数据的。利用UDP原理可以实现探测存活主机。现借助Scapy库来完成,在安装好Scary的终端输入Scary运行程序。本例中远程主机IP地址为192.168.68.150,端口dport可以为任意值,此例设为7345, 通过sr1()函数将构造好的数据包发出。
1. 相 关 代 码
>>> ip=IP()
>>> udp=UDP()
>>> r = (ip/udp)
>>> r[IP].dst='192.168.68.150' # 目标IP 192.168.68.150
>>> r[UDP].dport=7345 # 目标主机的dport值7345
>>> a=sr1(r) # 通过sr1()函数将构造好的数据包发出
Begin emission:
Finished sending 1 packets.
......*
Received 7 packets, got 1 answers, remaining 0 packets
>>> a.display() # 通过a.display()函数查看目标主机的返回数据包信息
运行结果如下:
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 56
id = 8025
flags =
frag = 0
ttl = 128
proto = icmp
chksum = 0x1093
src = 192.168.68.150
dst = 192.168.68.242
\options \
###[ ICMP ]###
type = dest-unreach # 目标不可达
code = port-unreachable # 目标端口不可达
chksum = 0x7f0
reserved = 0
length = 0
nexthopmtu= 0
unused = ''
###[ IP in ICMP ]###
version = 4
ihl = 5
tos = 0x0
len = 28
id = 1
flags =
frag = 0
ttl = 64
proto = udp
chksum = 0x6ff7
src = 192.168.68.242
dst = 192.168.68.150
\options \
###[ UDP in ICMP ]###
sport = domain
dport = 7345
len = 8
chksum = 0xd81e
通过a.display()函数查看目标主机的返回数据包信息, 此时发现返回的信息中存在ICMP的应答信息,“type = dest-unreach”表示目标主机不可达,“code=port-unreachable”表示目标主机端口不可达。由此可以验证远程目标主机为存活状态。若目标主机不为存活状态,则不会收到目标主机的响应数据包。