SQLiAttack.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. import logging
  2. from random import randint
  3. from lea import Lea
  4. from scapy.utils import RawPcapReader
  5. from scapy.layers.inet import Ether
  6. from ID2TLib.Utility import update_timestamp, get_interval_pps
  7. from definitions import ROOT_DIR
  8. from Attack import BaseAttack
  9. from Attack.AttackParameters import Parameter as Param
  10. from Attack.AttackParameters import ParameterTypes
  11. logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
  12. # noinspection PyPep8
  13. class SQLiAttack(BaseAttack.BaseAttack):
  14. template_attack_pcap_path = ROOT_DIR + "/../resources/ATutorSQLi.pcap"
  15. # HTTP port
  16. http_port = 80
  17. # Metasploit experiments show this range of ports
  18. minDefaultPort = 30000
  19. maxDefaultPort = 50000
  20. def __init__(self):
  21. """
  22. Creates a new instance of the SQLi Attack.
  23. """
  24. # Initialize attack
  25. super(SQLiAttack, self).__init__("SQLi Attack", "Injects a SQLi attack'",
  26. "Privilege elevation")
  27. # Define allowed parameters and their type
  28. self.supported_params = {
  29. Param.MAC_SOURCE: ParameterTypes.TYPE_MAC_ADDRESS,
  30. Param.IP_SOURCE: ParameterTypes.TYPE_IP_ADDRESS,
  31. Param.MAC_DESTINATION: ParameterTypes.TYPE_MAC_ADDRESS,
  32. Param.IP_DESTINATION: ParameterTypes.TYPE_IP_ADDRESS,
  33. Param.PORT_DESTINATION: ParameterTypes.TYPE_PORT,
  34. Param.TARGET_HOST: ParameterTypes.TYPE_DOMAIN,
  35. #Param.TARGET_URI: ParameterTypes.TYPE_URI,
  36. Param.INJECT_AT_TIMESTAMP: ParameterTypes.TYPE_FLOAT,
  37. Param.INJECT_AFTER_PACKET: ParameterTypes.TYPE_PACKET_POSITION,
  38. Param.PACKETS_PER_SECOND: ParameterTypes.TYPE_FLOAT
  39. }
  40. def init_params(self):
  41. """
  42. Initialize the parameters of this attack using the user supplied command line parameters.
  43. Use the provided statistics to calculate default parameters and to process user
  44. supplied queries.
  45. :param statistics: Reference to a statistics object.
  46. """
  47. # PARAMETERS: initialize with default utilsvalues
  48. # (values are overwritten if user specifies them)
  49. # Attacker configuration
  50. most_used_ip_address = self.statistics.get_most_used_ip_address()
  51. if isinstance(most_used_ip_address, list):
  52. most_used_ip_address = most_used_ip_address[0]
  53. self.add_param_value(Param.IP_SOURCE, most_used_ip_address)
  54. self.add_param_value(Param.MAC_SOURCE, self.statistics.get_mac_address(most_used_ip_address))
  55. # Victim configuration
  56. random_ip_address = self.statistics.get_random_ip_address()
  57. self.add_param_value(Param.IP_DESTINATION, random_ip_address)
  58. destination_mac = self.statistics.get_mac_address(random_ip_address)
  59. if isinstance(destination_mac, list) and len(destination_mac) == 0:
  60. destination_mac = self.generate_random_mac_address()
  61. self.add_param_value(Param.MAC_DESTINATION, destination_mac)
  62. self.add_param_value(Param.PORT_DESTINATION, self.http_port)
  63. # self.add_param_value(Param.TARGET_URI, "/")
  64. self.add_param_value(Param.TARGET_HOST, "www.hackme.com")
  65. # Attack configuration
  66. self.add_param_value(Param.INJECT_AFTER_PACKET, randint(0, self.statistics.get_packet_count()))
  67. self.add_param_value(Param.PACKETS_PER_SECOND,
  68. (self.statistics.get_pps_sent(most_used_ip_address) +
  69. self.statistics.get_pps_received(most_used_ip_address)) / 2)
  70. def generate_attack_pcap(self):
  71. # Timestamp
  72. timestamp_next_pkt = self.get_param_value(Param.INJECT_AT_TIMESTAMP)
  73. pps = self.get_param_value(Param.PACKETS_PER_SECOND)
  74. # Calculate complement packet rates of BG traffic per interval
  75. complement_interval_pps = self.statistics.calculate_complement_packet_rates(pps)
  76. # Initialize parameters
  77. packets = []
  78. mac_source = self.get_param_value(Param.MAC_SOURCE)
  79. ip_source = self.get_param_value(Param.IP_SOURCE)
  80. mac_destination = self.get_param_value(Param.MAC_DESTINATION)
  81. ip_destination = self.get_param_value(Param.IP_DESTINATION)
  82. port_destination = self.get_param_value(Param.PORT_DESTINATION)
  83. target_host = self.get_param_value(Param.TARGET_HOST)
  84. target_uri = "/" # self.get_param_value(Param.TARGET_URI)
  85. # Check ip.src == ip.dst
  86. self.ip_src_dst_equal_check(ip_source, ip_destination)
  87. path_attack_pcap = None
  88. # Set TTL based on TTL distribution of IP address
  89. source_ttl_dist = self.statistics.get_ttl_distribution(ip_source)
  90. if len(source_ttl_dist) > 0:
  91. source_ttl_prob_dict = Lea.fromValFreqsDict(source_ttl_dist)
  92. source_ttl_value = source_ttl_prob_dict.random()
  93. else:
  94. source_ttl_value = self.statistics.process_db_query("most_used(ttlValue)")
  95. destination_ttl_dist = self.statistics.get_ttl_distribution(ip_destination)
  96. if len(destination_ttl_dist) > 0:
  97. destination_ttl_prob_dict = Lea.fromValFreqsDict(destination_ttl_dist)
  98. destination_ttl_value = destination_ttl_prob_dict.random()
  99. else:
  100. destination_ttl_value = self.statistics.process_db_query("most_used(ttlValue)")
  101. # Inject SQLi Attack
  102. # Read SQLi Attack pcap file
  103. orig_ip_dst = None
  104. exploit_raw_packets = RawPcapReader(self.template_attack_pcap_path)
  105. inter_arrival_times, inter_arrival_time_dist = self.get_inter_arrival_time(exploit_raw_packets,True)
  106. timeSteps = Lea.fromValFreqsDict(inter_arrival_time_dist)
  107. exploit_raw_packets = RawPcapReader(self.template_attack_pcap_path)
  108. port_source = randint(self.minDefaultPort,self.maxDefaultPort) # experiments show this range of ports
  109. # Random TCP sequence numbers
  110. global attacker_seq
  111. attacker_seq = randint(1000, 50000)
  112. global victim_seq
  113. victim_seq = randint(1000, 50000)
  114. for pkt_num, pkt in enumerate(exploit_raw_packets):
  115. eth_frame = Ether(pkt[0])
  116. ip_pkt = eth_frame.payload
  117. tcp_pkt = ip_pkt.payload
  118. str_tcp_seg = str(tcp_pkt.payload)
  119. # Clean payloads
  120. eth_frame.payload = b''
  121. ip_pkt.payload = b''
  122. tcp_pkt.payload = b''
  123. if pkt_num == 0:
  124. prev_orig_port_source = tcp_pkt.getfieldval("sport")
  125. orig_ip_dst = ip_pkt.getfieldval("dst") # victim IP
  126. if tcp_pkt.getfieldval("dport") == 80 or tcp_pkt.getfieldval("sport") == 80:
  127. # Attacker --> vicitm
  128. if ip_pkt.getfieldval("dst") == orig_ip_dst: # victim IP
  129. # There are 363 TCP connections with different source ports, for each of them we generate random port
  130. if tcp_pkt.getfieldval("sport") != prev_orig_port_source and tcp_pkt.getfieldval("dport") != 4444:
  131. port_source = randint(self.minDefaultPort, self.maxDefaultPort)
  132. prev_orig_port_source = tcp_pkt.getfieldval("sport")
  133. # New connection, new random TCP sequence numbers
  134. attacker_seq = randint(1000, 50000)
  135. victim_seq = randint(1000, 50000)
  136. # First packet in a connection has ACK = 0
  137. tcp_pkt.setfieldval("ack", 0)
  138. # Ether
  139. eth_frame.setfieldval("src", mac_source)
  140. eth_frame.setfieldval("dst", mac_destination)
  141. # IP
  142. ip_pkt.setfieldval("src", ip_source)
  143. ip_pkt.setfieldval("dst", ip_destination)
  144. ip_pkt.setfieldval("ttl", source_ttl_value)
  145. # TCP
  146. tcp_pkt.setfieldval("sport",port_source)
  147. tcp_pkt.setfieldval("dport", port_destination)
  148. str_tcp_seg = self.modify_http_header(str_tcp_seg, '/ATutor', target_uri, orig_ip_dst, target_host)
  149. # TCP Seq, Ack
  150. if tcp_pkt.getfieldval("ack") != 0:
  151. tcp_pkt.setfieldval("ack", victim_seq)
  152. tcp_pkt.setfieldval("seq", attacker_seq)
  153. if not (tcp_pkt.getfieldval("flags") == 16 and len(str_tcp_seg) == 0): # flags=A:
  154. attacker_seq += max(len(str_tcp_seg), 1)
  155. new_pkt = (eth_frame / ip_pkt/ tcp_pkt / str_tcp_seg)
  156. new_pkt.time = timestamp_next_pkt
  157. pps = max(get_interval_pps(complement_interval_pps, timestamp_next_pkt), 10)
  158. timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + float(timeSteps.random())
  159. # Victim --> attacker
  160. else:
  161. # Ether
  162. eth_frame.setfieldval("src", mac_destination)
  163. eth_frame.setfieldval("dst", mac_source)
  164. # IP
  165. ip_pkt.setfieldval("src", ip_destination)
  166. ip_pkt.setfieldval("dst", ip_source)
  167. ip_pkt.setfieldval("ttl", destination_ttl_value)
  168. # TCP
  169. tcp_pkt.setfieldval("dport", port_source)
  170. tcp_pkt.setfieldval("sport", port_destination)
  171. str_tcp_seg = self.modify_http_header(str_tcp_seg, '/ATutor', target_uri, orig_ip_dst, target_host)
  172. # TCP Seq, ACK
  173. tcp_pkt.setfieldval("ack", attacker_seq)
  174. tcp_pkt.setfieldval("seq", victim_seq)
  175. strLen = len(str_tcp_seg)
  176. if not (tcp_pkt.getfieldval("flags") == 16 and strLen == 0): # flags=A:
  177. victim_seq += max(strLen, 1)
  178. new_pkt = (eth_frame / ip_pkt / tcp_pkt / str_tcp_seg)
  179. timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + float(timeSteps.random())
  180. new_pkt.time = timestamp_next_pkt
  181. # The last connection
  182. else:
  183. # New connection, new random TCP sequence numbers
  184. attacker_seq = randint(1000, 50000)
  185. victim_seq = randint(1000, 50000)
  186. # First packet in a connection has ACK = 0
  187. tcp_pkt.setfieldval("ack", 0)
  188. #port_source = randint(self.minDefaultPort, self.maxDefaultPort)
  189. # Attacker --> vicitm
  190. if ip_pkt.getfieldval("dst") == orig_ip_dst: # victim IP
  191. # Ether
  192. eth_frame.setfieldval("src", mac_source)
  193. eth_frame.setfieldval("dst", mac_destination)
  194. # IP
  195. ip_pkt.setfieldval("src", ip_source)
  196. ip_pkt.setfieldval("dst", ip_destination)
  197. ip_pkt.setfieldval("ttl", source_ttl_value)
  198. # TCP
  199. #tcp_pkt.setfieldval("sport", port_source)
  200. str_tcp_seg = self.modify_http_header(str_tcp_seg, '/ATutor', target_uri, orig_ip_dst, target_host)
  201. # TCP Seq, Ack
  202. if tcp_pkt.getfieldval("ack") != 0:
  203. tcp_pkt.setfieldval("ack", victim_seq)
  204. tcp_pkt.setfieldval("seq", attacker_seq)
  205. if not (tcp_pkt.getfieldval("flags") == 16 and len(str_tcp_seg) == 0): # flags=A:
  206. attacker_seq += max(len(str_tcp_seg), 1)
  207. new_pkt = (eth_frame / ip_pkt / tcp_pkt / str_tcp_seg)
  208. new_pkt.time = timestamp_next_pkt
  209. pps = max(get_interval_pps(complement_interval_pps, timestamp_next_pkt), 10)
  210. timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + float(timeSteps.random())
  211. # Victim --> attacker
  212. else:
  213. # Ether
  214. eth_frame.setfieldval("src", mac_destination)
  215. eth_frame.setfieldval("dst", mac_source)
  216. # IP
  217. ip_pkt.setfieldval("src", ip_destination)
  218. ip_pkt.setfieldval("dst", ip_source)
  219. ip_pkt.setfieldval("ttl", destination_ttl_value)
  220. # TCP
  221. #tcp_pkt.setfieldval("dport", port_source)
  222. str_tcp_seg = self.modify_http_header(str_tcp_seg, '/ATutor', target_uri, orig_ip_dst, target_host)
  223. # TCP Seq, ACK
  224. tcp_pkt.setfieldval("ack", attacker_seq)
  225. tcp_pkt.setfieldval("seq", victim_seq)
  226. strLen = len(str_tcp_seg)
  227. if not (tcp_pkt.getfieldval("flags") == 16 and strLen == 0): # flags=A:
  228. victim_seq += max(strLen, 1)
  229. new_pkt = (eth_frame / ip_pkt / tcp_pkt / str_tcp_seg)
  230. timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps) + float(timeSteps.random())
  231. new_pkt.time = timestamp_next_pkt
  232. packets.append(new_pkt)
  233. # Store timestamp of first packet (for attack label)
  234. self.attack_start_utime = packets[0].time
  235. self.attack_end_utime = packets[-1].time
  236. if len(packets) > 0:
  237. packets = sorted(packets, key=lambda pkt: pkt.time)
  238. path_attack_pcap = self.write_attack_pcap(packets, True, path_attack_pcap)
  239. # return packets sorted by packet time_sec_start
  240. # pkt_num+1: because pkt_num starts at 0
  241. return pkt_num + 1, path_attack_pcap