From 9d7378a5628020993c32f80e62fb02ae076f24c7 Mon Sep 17 00:00:00 2001 From: Mathy Vanhoef Date: Thu, 30 Jul 2020 17:54:04 +0400 Subject: [PATCH] fragattacks: experimental udp injection --- research/fragattack.py | 3 +++ research/fraginternals.py | 19 ++++++++++++++----- research/tests_common.py | 8 ++++++-- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/research/fragattack.py b/research/fragattack.py index 9be62f52c..e22ec2dec 100755 --- a/research/fragattack.py +++ b/research/fragattack.py @@ -152,6 +152,7 @@ def args2ptype(args): if args.dhcp: return REQ_DHCP if args.icmp: return REQ_ICMP if args.ipv6: return REQ_ICMPv6_RA + if args.udp: return REQ_UDP return None @@ -187,6 +188,8 @@ if __name__ == "__main__": parser.add_argument('--dhcp', default=False, action='store_true', help="Override default request with DHCP discover.") parser.add_argument('--icmp', default=False, action='store_true', help="Override default request with ICMP ping request.") parser.add_argument('--ipv6', default=False, action='store_true', help="Override default request with ICMPv6 router advertisement.") + # TODO: Test the --udp option more + parser.add_argument('--udp', type=int, default=None, help="Override default request with UDP packet to the given port.") parser.add_argument('--no-dhcp', default=False, action='store_true', help="Do not reply to DHCP requests as an AP.") parser.add_argument('--icmp-size', type=int, default=None, help="Second to wait after AfterAuth before triggering Connected event") parser.add_argument('--padding', type=int, default=None, help="Add padding data to ARP/DHCP/ICMP requests.") diff --git a/research/fraginternals.py b/research/fraginternals.py index 16886311c..f49715aa7 100644 --- a/research/fraginternals.py +++ b/research/fraginternals.py @@ -89,9 +89,9 @@ def freebsd_encap_eapolmsdu(p, src, dst, payload): # ----------------------------------- Vulnerability Tests ----------------------------------- -REQ_ARP, REQ_ICMP, REQ_ICMPv6_RA, REQ_DHCP = range(4) +REQ_ARP, REQ_ICMP, REQ_ICMPv6_RA, REQ_DHCP, REQ_UDP = range(5) -def generate_request(sta, ptype, prior=2, icmp_size=None, padding=None, to_self=False): +def generate_request(sta, ptype, prior=2, icmp_size=None, padding=None, to_self=False, dport=None): header = sta.get_header(prior=prior) # Test handle the client handles Ethernet frames with the same src and dst MAC address @@ -141,6 +141,15 @@ def generate_request(sta, ptype, prior=2, icmp_size=None, padding=None, to_self= # We assume DHCP discover is sent towards the AP. header.addr3 = "ff:ff:ff:ff:ff:ff" + elif ptype == REQ_UDP: + port = random.randint(2000, 2**16) + + # We cannot chekc UDP automatically + check = None + + request = LLC()/SNAP()/IP(src=sta.ip, dst=sta.peerip) + request = request/UDP(sport=port, dport=dport)/Raw(b"AAAA") + if padding != None and padding >= 1: request = raw(request) + b"\x00" + b"A" * (padding - 1) @@ -397,7 +406,7 @@ class Station(): if self.tk: p = self.encrypt(p) self.daemon.inject_mon(p) - log(STATUS, "[Injected] " + repr(p)) + log(STATUS, "[Injected packet] " + repr(p)) def set_header(self, p, prior=None): """Set addresses to send frame to the peer or the 3rd party station.""" @@ -566,11 +575,11 @@ class Station(): frame = act.frame self.daemon.inject_mon(frame) - log(STATUS, "[Injected fragment] " + repr(frame)) + log(STATUS, "[Injected] " + repr(frame)) if self.options.inject_mf_workaround and frame.FCfield & 0x4 != 0: self.daemon.inject_mon(Dot11(addr1="ff:ff:ff:ff:ff:ff")) - log(DEBUG, "[Injected packet] Prevented bug after fragment injection") + log(DEBUG, "[Injected] Prevent bug after fragment injection") # Stop processing actions if requested diff --git a/research/tests_common.py b/research/tests_common.py index 3f54d4904..dcdb5b933 100644 --- a/research/tests_common.py +++ b/research/tests_common.py @@ -19,6 +19,7 @@ class PingTest(Test): self.padding = None if opt == None else opt.padding self.to_self = False if opt == None else opt.to_self self.bad_mic = False if opt == None else opt.bad_mic + self.dport = None if opt == None else opt.udp self.parse_meta_actions() @@ -37,8 +38,11 @@ class PingTest(Test): def prepare(self, station): log(STATUS, "Generating ping test", color="green") + # TODO: We can only automatically check result if the last action happens while being connected...???? + # Generate the header and payload - header, request, self.check_fn = generate_request(station, self.ptype, icmp_size=self.icmp_size, padding=self.padding, to_self=self.to_self) + header, request, self.check_fn = generate_request(station, self.ptype, icmp_size=self.icmp_size, \ + padding=self.padding, to_self=self.to_self, dport=self.dport) if self.as_msdu == 1: # Set the A-MSDU frame type flag in the QoS header @@ -212,7 +216,7 @@ class EapolAmsduTest(Test): log(STATUS, "Generating ping test", color="green") # Generate the single frame - header, request, check_fn = generate_request(station, self.ptype) + header, request, check_fn = generate_request(station, self.ptype, dport=self.dport) # Set the A-MSDU frame type flag in the QoS header header.Reserved = 1