Browse Source

Merge branch 'memcrashed' of stefan.schmidt/ID2T-toolkit into master

Carlos Garcia 6 years ago
parent
commit
066750ac79

+ 1 - 0
code/Attack/AttackParameters.py

@@ -11,6 +11,7 @@ class Parameter(enum.Enum):
     IP_DESTINATION = 'ip.dst'  # destination IP address
     IP_DNS = 'ip.dns'  # IP address of DNS server
     HOSTING_IP = 'hosting.ip'
+    IP_VICTIM = 'ip.victim'
     # recommended type: MAC address ------------------------------
     MAC_SOURCE = 'mac.src'  # MAC address of source
     MAC_DESTINATION = 'mac.dst'  # MAC address of destination

+ 101 - 0
code/Attack/MemcrashedSpooferAttack.py

@@ -0,0 +1,101 @@
+import logging
+import random as rnd
+import typing
+
+import scapy.layers.inet as inet
+
+import Attack.AttackParameters as atkParam
+import Attack.BaseAttack as BaseAttack
+import ID2TLib.Utility as Util
+import ID2TLib.Memcached as Memcd
+
+logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
+
+
+class MemcrashedSpooferAttack(BaseAttack.BaseAttack):
+    def __init__(self):
+        """
+        Creates a new instance of the "Memcrashed" Memcached amplification attack.
+        """
+        # Initialize attack
+        super(MemcrashedSpooferAttack, self).__init__("Memcrashed Attack (Spoofer side)",
+                                               "Injects the spoofer-side of a Memcached amplification attack",
+                                               "Resource Exhaustion")
+
+        # Define allowed parameters and their type
+        self.supported_params.update({
+            atkParam.Parameter.IP_SOURCE: atkParam.ParameterTypes.TYPE_IP_ADDRESS,
+            atkParam.Parameter.MAC_SOURCE: atkParam.ParameterTypes.TYPE_MAC_ADDRESS,
+            atkParam.Parameter.IP_DESTINATION: atkParam.ParameterTypes.TYPE_IP_ADDRESS,
+            atkParam.Parameter.MAC_DESTINATION: atkParam.ParameterTypes.TYPE_MAC_ADDRESS,
+            atkParam.Parameter.IP_VICTIM: atkParam.ParameterTypes.TYPE_IP_ADDRESS,
+            atkParam.Parameter.INJECT_AT_TIMESTAMP: atkParam.ParameterTypes.TYPE_FLOAT,
+            atkParam.Parameter.INJECT_AFTER_PACKET: atkParam.ParameterTypes.TYPE_PACKET_POSITION,
+            atkParam.Parameter.PACKETS_PER_SECOND: atkParam.ParameterTypes.TYPE_FLOAT,
+            atkParam.Parameter.ATTACK_DURATION: atkParam.ParameterTypes.TYPE_INTEGER_POSITIVE
+        })
+
+    def init_params(self) -> None:
+        """
+        Initialize the parameters of this attack using the user supplied command line parameters.
+        Use the provided statistics to calculate default parameters and to process user
+        supplied queries.
+        """
+        # By default, the most used IP is the attacker
+        most_used_ip = self.statistics.get_most_used_ip_address()
+        self.add_param_value(atkParam.Parameter.IP_SOURCE, most_used_ip)
+        self.add_param_value(atkParam.Parameter.MAC_SOURCE, self.statistics.get_mac_address(most_used_ip))
+
+        # Target (i.e. amplifier) is a random public IP
+        self.add_param_value(atkParam.Parameter.IP_DESTINATION, self.generate_random_ipv4_address('A'))
+        self.add_param_value(atkParam.Parameter.MAC_DESTINATION, self.generate_random_mac_address())
+
+        # IP of the victim which is supposed to get hit by the amplified attack
+        self.add_param_value(atkParam.Parameter.IP_VICTIM, self.generate_random_ipv4_address('A'))
+
+        self.add_param_value(atkParam.Parameter.PACKETS_PER_SECOND, (self.statistics.get_pps_sent(most_used_ip) +
+                             self.statistics.get_pps_received(most_used_ip)) / 2)
+        self.add_param_value(atkParam.Parameter.ATTACK_DURATION, rnd.randint(5, 30))
+        self.add_param_value(atkParam.Parameter.INJECT_AFTER_PACKET, rnd.randint(0, self.statistics.get_packet_count()))
+
+    def generate_attack_packets(self) -> None:
+        ip_attacker = self.get_param_value(atkParam.Parameter.IP_SOURCE)
+        mac_attacker = self.get_param_value(atkParam.Parameter.MAC_SOURCE)
+        ip_amplifier = self.get_param_value(atkParam.Parameter.IP_DESTINATION)
+        mac_amplifier = self.get_param_value(atkParam.Parameter.MAC_DESTINATION)
+        ip_victim = self.get_param_value(atkParam.Parameter.IP_VICTIM)
+
+        pps = self.get_param_value(atkParam.Parameter.PACKETS_PER_SECOND)
+
+        timestamp_next_pkt = self.get_param_value(atkParam.Parameter.INJECT_AT_TIMESTAMP)
+        self.attack_start_utime = timestamp_next_pkt
+
+        attack_duration = self.get_param_value(atkParam.Parameter.ATTACK_DURATION)
+        attack_ends_time = timestamp_next_pkt + attack_duration
+
+        _, src_ttl, _ = self.get_ip_data(ip_attacker)
+        sport = Util.generate_source_port_from_platform('linux')
+
+        # Use MAC of the actual source, but the IP of the victim
+        attacker_ether = inet.Ether(src=mac_attacker, dst=mac_amplifier)
+        attacker_ip = inet.IP(src=ip_victim, dst=ip_amplifier, ttl=src_ttl, flags='DF')
+
+        while timestamp_next_pkt <= attack_ends_time:
+            request_udp = inet.UDP(sport=sport, dport=Memcd.memcached_port)
+            request_memcd = Memcd.Memcached_Request(Request=b'stats\r\n', RequestID=inet.RandShort())
+            request = (attacker_ether / attacker_ip / request_udp / request_memcd)
+            request.time = timestamp_next_pkt
+
+            self.packets.append(request)
+
+            timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps)
+
+    def generate_attack_pcap(self) -> typing.Tuple[int, str]:
+        # store end time of attack
+        self.attack_end_utime = self.packets[-1].time
+
+        # write attack packets to pcap
+        pcap_path = self.write_attack_pcap(self.packets)
+
+        # return packet count and path
+        return len(self.packets), pcap_path

+ 18 - 0
code/ID2TLib/Memcached.py

@@ -0,0 +1,18 @@
+import scapy.packet as packet
+import scapy.fields as field
+import scapy.layers.inet as inet
+
+
+memcached_port = 11211
+
+
+class Memcached_Request(packet.Packet):
+    namez = "Memcached UDP request packet"
+    fields_desc = [field.ShortField("RequestID", 0),
+                   field.ShortField("SequenceNumber", 0),
+                   field.ShortField("DatagramCount", 1),
+                   field.ShortField("Reserved", 0),
+                   field.StrField("Request", "\r\n")]
+
+
+packet.bind_layers(inet.UDP, Memcached_Request, dport=11211)

+ 15 - 0
code/Test/test_MemcrashedSpooferAttack.py

@@ -0,0 +1,15 @@
+import Test.ID2TAttackTest as Test
+
+sha_default = "065e7de040fb41bcaad81b705fb70f3e07807f0d3dc1efe0f437929ff33b49f8"
+sha_ips_not_in_pcap = "46c015fde4509227ee70fbe1557fe0efd3ac76abf58e00dcbbcf09d0b950fb5f"
+
+
+class UnitTestMemcrashedSpooferAttack(Test.ID2TAttackTest):
+    def test_memcrashed_spoofer_default(self):
+        self.checksum_test([['MemcrashedSpooferAttack']], sha_default)
+
+    def test_memcrashed_spoofer_ips_not_in_pcap(self):
+        self.checksum_test([['MemcrashedSpooferAttack', 'ip.src=1.1.1.1', 'ip.dst=2.2.2.2']], sha_ips_not_in_pcap)
+
+    def test_memcrashed_spoofer_order(self):
+        self.order_test([['MemcrashedSpooferAttack']])