|
@@ -69,7 +69,7 @@ class JoomlaRegPrivExploit(BaseAttack.BaseAttack):
|
|
|
most_used_ip_address = most_used_ip_address[0]
|
|
|
self.add_param_value(Param.IP_SOURCE, most_used_ip_address)
|
|
|
self.add_param_value(Param.MAC_SOURCE, self.statistics.get_mac_address(most_used_ip_address))
|
|
|
- self.add_param_value(Param.TARGET_URI, "/")
|
|
|
+ self.add_param_value(Param.TARGET_URI, '/')
|
|
|
self.add_param_value(Param.TARGET_HOST, "www.hackme.com")
|
|
|
self.add_param_value(Param.INJECT_AFTER_PACKET, randint(0, self.statistics.get_packet_count()))
|
|
|
self.add_param_value(Param.PACKETS_PER_SECOND,self.maxDefaultPPS)
|
|
@@ -84,6 +84,7 @@ class JoomlaRegPrivExploit(BaseAttack.BaseAttack):
|
|
|
destination_mac = self.generate_random_mac_address()
|
|
|
self.add_param_value(Param.MAC_DESTINATION, destination_mac)
|
|
|
|
|
|
+ @property
|
|
|
def generate_attack_pcap(self):
|
|
|
def update_timestamp(timestamp, pps, maxdelay):
|
|
|
"""
|
|
@@ -123,40 +124,55 @@ class JoomlaRegPrivExploit(BaseAttack.BaseAttack):
|
|
|
target_host = self.get_param_value(Param.TARGET_HOST)
|
|
|
target_uri = self.get_param_value(Param.TARGET_URI)
|
|
|
|
|
|
- # Aidmar - check ip.src == ip.dst
|
|
|
+ # Check ip.src == ip.dst
|
|
|
if ip_source == ip_destination:
|
|
|
print("\nERROR: Invalid IP addresses; source IP is the same as destination IP: " + ip_source + ".")
|
|
|
import sys
|
|
|
sys.exit(0)
|
|
|
|
|
|
path_attack_pcap = None
|
|
|
- replyDelay = self.get_reply_delay(ip_destination)
|
|
|
+ minDelay, maxDelay = self.get_reply_delay(ip_destination)
|
|
|
|
|
|
# Inject Joomla_registration_privesc
|
|
|
# Read joomla_registration_privesc pcap file
|
|
|
orig_ip_dst = None
|
|
|
- exploit_raw_packets = RawPcapReader("joomla_registration_privesc.pcap")
|
|
|
+ exploit_raw_packets = RawPcapReader("resources/joomla_registration_privesc.pcap")
|
|
|
|
|
|
port_source = randint(self.minDefaultPort,self.maxDefaultPort) # experiments show this range of ports
|
|
|
|
|
|
+ # Random TCP sequence numbers
|
|
|
+ global attacker_seq
|
|
|
+ attacker_seq = randint(1000,50000)
|
|
|
+ global victim_seq
|
|
|
+ victim_seq = randint(1000,50000)
|
|
|
+
|
|
|
for pkt_num, pkt in enumerate(exploit_raw_packets):
|
|
|
eth_frame = Ether(pkt[0])
|
|
|
ip_pkt = eth_frame.payload
|
|
|
tcp_pkt = ip_pkt.payload
|
|
|
- str_http_pkt = str(tcp_pkt.payload)
|
|
|
+ str_tcp_seg = str(tcp_pkt.payload)
|
|
|
+
|
|
|
+ # Clean payloads
|
|
|
+ eth_frame.payload = b''
|
|
|
+ ip_pkt.payload = b''
|
|
|
+ tcp_pkt.payload = b''
|
|
|
|
|
|
if pkt_num == 0:
|
|
|
prev_orig_port_source = tcp_pkt.getfieldval("sport")
|
|
|
if tcp_pkt.getfieldval("dport") == self.http_port:
|
|
|
orig_ip_dst = ip_pkt.getfieldval("dst") # victim IP
|
|
|
|
|
|
- # Request
|
|
|
+ # Request: Attacker --> vicitm
|
|
|
if ip_pkt.getfieldval("dst") == orig_ip_dst: # victim IP
|
|
|
-
|
|
|
# There are 7 TCP connections with different source ports, for each of them we generate random port
|
|
|
if tcp_pkt.getfieldval("sport") != prev_orig_port_source:
|
|
|
port_source = randint(self.minDefaultPort, self.maxDefaultPort)
|
|
|
prev_orig_port_source = tcp_pkt.getfieldval("sport")
|
|
|
+ # New connection, new random TCP sequence numbers
|
|
|
+ attacker_seq = randint(1000, 50000)
|
|
|
+ victim_seq = randint(1000, 50000)
|
|
|
+ # First packet in a connection has ACK = 0
|
|
|
+ tcp_pkt.setfieldval("ack", 0)
|
|
|
|
|
|
# Ether
|
|
|
eth_frame.setfieldval("src", mac_source)
|
|
@@ -167,29 +183,33 @@ class JoomlaRegPrivExploit(BaseAttack.BaseAttack):
|
|
|
# TCP
|
|
|
tcp_pkt.setfieldval("sport",port_source)
|
|
|
|
|
|
-
|
|
|
- eth_frame.payload = b''
|
|
|
- ip_pkt.payload = b''
|
|
|
- tcp_pkt.payload = b''
|
|
|
- #temp = "GET / HTTP/1.0\r\n\r\n"
|
|
|
- #temp = "GET / HTTP/1.1\r\nHost: 192.168.189.1\r\nUser-Agent: Mozilla/4.0(compatible;MSIE6.0;WindowsNT5.1)\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n"
|
|
|
-
|
|
|
- if len(str_http_pkt) > 0:
|
|
|
- # convert payload bytes to str => str = "b'..\\r\\n..'"
|
|
|
- str_http_pkt = str_http_pkt[2:-1]
|
|
|
- str_http_pkt = str_http_pkt.replace('/joomla360', target_uri)
|
|
|
- str_http_pkt = str_http_pkt.replace(orig_ip_dst, target_host)
|
|
|
- str_http_pkt = str_http_pkt.replace("\\n", "\n")
|
|
|
- str_http_pkt = str_http_pkt.replace("\\r", "\r")
|
|
|
-
|
|
|
- new_pkt = (eth_frame / ip_pkt/ tcp_pkt / str_http_pkt)
|
|
|
+ if len(str_tcp_seg) > 0:
|
|
|
+ # convert payload bytes to string => str = "b'..\\r\\n..'" additional characters are added in the string,
|
|
|
+ # mainly backslashes to escape single quotes and whitespaces
|
|
|
+ str_tcp_seg = str_tcp_seg[2:-1]
|
|
|
+ str_tcp_seg = str_tcp_seg.replace('/joomla360', target_uri)
|
|
|
+ str_tcp_seg = str_tcp_seg.replace(orig_ip_dst, target_host)
|
|
|
+ str_tcp_seg = str_tcp_seg.replace("\\n", "\n")
|
|
|
+ str_tcp_seg = str_tcp_seg.replace("\\r", "\r")
|
|
|
+ str_tcp_seg = str_tcp_seg.replace("\\t", "\t")
|
|
|
+ str_tcp_seg = str_tcp_seg.replace("\\\'", "\'")
|
|
|
+
|
|
|
+ # TCP Seq, Ack
|
|
|
+ if tcp_pkt.getfieldval("ack") != 0:
|
|
|
+ tcp_pkt.setfieldval("ack", victim_seq)
|
|
|
+ tcp_pkt.setfieldval("seq", attacker_seq)
|
|
|
+ if not(tcp_pkt.getfieldval("flags") == 16 and len(str_tcp_seg) == 0): # flags=A:
|
|
|
+ attacker_seq += max(len(str_tcp_seg),1)
|
|
|
+
|
|
|
+ new_pkt = (eth_frame / ip_pkt/ tcp_pkt / str_tcp_seg)
|
|
|
new_pkt.time = timestamp_next_pkt
|
|
|
|
|
|
maxdelay = randomdelay.random()
|
|
|
pps = self.minDefaultPPS if getIntervalPPS(complement_interval_pps, timestamp_next_pkt) is None else max(
|
|
|
getIntervalPPS(complement_interval_pps, timestamp_next_pkt), self.minDefaultPPS)
|
|
|
timestamp_next_pkt = update_timestamp(timestamp_next_pkt, pps, maxdelay)
|
|
|
- # Reply
|
|
|
+
|
|
|
+ # Reply: Victim --> attacker
|
|
|
else:
|
|
|
# Ether
|
|
|
eth_frame.setfieldval("src", mac_destination)
|
|
@@ -200,20 +220,26 @@ class JoomlaRegPrivExploit(BaseAttack.BaseAttack):
|
|
|
# TCP
|
|
|
tcp_pkt.setfieldval("dport", port_source)
|
|
|
|
|
|
- eth_frame.payload = b''
|
|
|
- ip_pkt.payload = b''
|
|
|
- tcp_pkt.payload = b''
|
|
|
-
|
|
|
- if len(str_http_pkt) > 0:
|
|
|
- # convert payload bytes to str => str = "b'..\\r\\n..'"
|
|
|
- str_http_pkt = str_http_pkt[2:-1]
|
|
|
- str_http_pkt = str_http_pkt.replace('/joomla360', target_uri)
|
|
|
- str_http_pkt = str_http_pkt.replace(orig_ip_dst, target_host)
|
|
|
- str_http_pkt = str_http_pkt.replace("\\n", "\n")
|
|
|
- str_http_pkt = str_http_pkt.replace("\\r", "\r")
|
|
|
-
|
|
|
- new_pkt = (eth_frame / ip_pkt / tcp_pkt / str_http_pkt)
|
|
|
- timestamp_next_pkt = timestamp_next_pkt + uniform(replyDelay, 2 * replyDelay)
|
|
|
+ if len(str_tcp_seg) > 0:
|
|
|
+ # convert payload bytes to string => str = "b'..\\r\\n..'" additional characters are added in the string,
|
|
|
+ # mainly backslashes to escape single quotes and whitespaces
|
|
|
+ str_tcp_seg = str_tcp_seg[2:-1]
|
|
|
+ str_tcp_seg = str_tcp_seg.replace('/joomla360', target_uri)
|
|
|
+ str_tcp_seg = str_tcp_seg.replace(orig_ip_dst, target_host)
|
|
|
+ str_tcp_seg = str_tcp_seg.replace("\\n", "\n")
|
|
|
+ str_tcp_seg = str_tcp_seg.replace("\\r", "\r")
|
|
|
+ str_tcp_seg = str_tcp_seg.replace("\\t", "\t")
|
|
|
+ str_tcp_seg = str_tcp_seg.replace("\\\'", "\'")
|
|
|
+
|
|
|
+ # TCP Seq, ACK
|
|
|
+ tcp_pkt.setfieldval("ack", attacker_seq)
|
|
|
+ tcp_pkt.setfieldval("seq", victim_seq)
|
|
|
+ strLen = len(str_tcp_seg)
|
|
|
+ if not(tcp_pkt.getfieldval("flags") == 16 and strLen == 0): # flags=A:
|
|
|
+ victim_seq += max(strLen, 1)
|
|
|
+
|
|
|
+ new_pkt = (eth_frame / ip_pkt / tcp_pkt / str_tcp_seg)
|
|
|
+ timestamp_next_pkt = timestamp_next_pkt + uniform(minDelay, maxDelay)
|
|
|
new_pkt.time = timestamp_next_pkt
|
|
|
|
|
|
packets.append(new_pkt)
|