diff --git a/intercepting-communication/module.yml b/intercepting-communication/module.yml index 9f5300b..45a7704 100644 --- a/intercepting-communication/module.yml +++ b/intercepting-communication/module.yml @@ -35,8 +35,8 @@ challenges: name: UDP 2 - id: udp-spoof-host name: UDP Spoofing 1 - visibility: - start: "2029-11-04T13:00:00-07:00" +- id: udp-spoof-host-2 + name: UDP Spoofing 2 - id: level-12 name: ARP - id: level-13 diff --git a/intercepting-communication/udp-spoof-host-2/.init b/intercepting-communication/udp-spoof-host-2/.init new file mode 120000 index 0000000..ea4ba49 --- /dev/null +++ b/intercepting-communication/udp-spoof-host-2/.init @@ -0,0 +1 @@ +../.init \ No newline at end of file diff --git a/intercepting-communication/udp-spoof-host-2/DESCRIPTION.md b/intercepting-communication/udp-spoof-host-2/DESCRIPTION.md new file mode 100644 index 0000000..9dbddd7 --- /dev/null +++ b/intercepting-communication/udp-spoof-host-2/DESCRIPTION.md @@ -0,0 +1,11 @@ +There is a fairly wide gap between the features that TCP provides and UDP's barebones nature. +Sometimes, developers want _some_ of those features, and end up reimplementing just those that they need on top of UDP. +This leads to weird situations, such as the ability to trigger outbound traffic to other servers, with a potential application to Denial of Service [amplification](https://www.cisa.gov/news-events/alerts/2014/01/17/udp-based-amplification-attacks). + +Rather than leaking the flag directly, this challenge allows you to redirect it to another server. +Can you catch it on the other side? + +---- + +**HINT:** +You'll need to either use a UDP server to actually receive the flag (e.g., python or netcat), or just sniff it off the network with Wireshark when it comes to you, even if you don't have a server listening! diff --git a/intercepting-communication/udp-spoof-host-2/run b/intercepting-communication/udp-spoof-host-2/run new file mode 100755 index 0000000..2d24e41 --- /dev/null +++ b/intercepting-communication/udp-spoof-host-2/run @@ -0,0 +1,47 @@ +#!/usr/bin/exec-suid --real -- /usr/bin/python -I + +import psutil +import socket +import time +import os + +from dojjail import Host, Network + +flag = open("/flag").read() +parent_process = psutil.Process(os.getppid()) + +class ServerHost(Host): + def entrypoint(self): + server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + server_socket.bind(("0.0.0.0", 31337)) + while True: + try: + client_message, (client_host, client_port) = server_socket.recvfrom(1024) + if client_message.strip() == b"ACTION?": + server_socket.sendto(b"NONE", (client_host, client_port)) + except ConnectionError: + continue + +class ClientHost(Host): + def entrypoint(self): + client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + client_socket.bind(("0.0.0.0", 31338)) + while True: + try: + client_socket.sendto(b"ACTION?", ("10.0.0.3", 31337)) + message, (peer_host, peer_port) = client_socket.recvfrom(1024) + if peer_port == 31337 and message.startswith(b"FLAG"): + _, flag_host, flag_port = message.strip().split(b":") + client_socket.sendto(flag.encode(), (flag_host, int(flag_port))) + + time.sleep(1) + except (ConnectionError, ValueError): + continue + +user_host = Host("ip-10-0-0-1", privileged_uid=parent_process.uids().effective) +client_host = ClientHost("ip-10-0-0-2") +server_host = ServerHost("ip-10-0-0-3") +network = Network(hosts={user_host: "10.0.0.1", client_host: "10.0.0.2", server_host: "10.0.0.3"}, subnet="10.0.0.0/24") +network.run() + +user_host.interactive(environ=parent_process.environ()) diff --git a/intercepting-communication/udp-spoof-host/DESCRIPTION.md b/intercepting-communication/udp-spoof-host/DESCRIPTION.md index a23198a..e8504f7 100644 --- a/intercepting-communication/udp-spoof-host/DESCRIPTION.md +++ b/intercepting-communication/udp-spoof-host/DESCRIPTION.md @@ -1,9 +1,12 @@ -Though we didn't explore this for TCP, in addition to selecting the destination port, both TCP and UDP can set their _source_ port. -We'll practice that here --- you can set the source port with `s.bind` on the socket, exactly how a server does it to set their listening port. -Read the source code of `/challenge/run` to see what source port you'll need! +There are two dangers to UDP: first, it is often used in places where people are already cutting corners for performence's sake. +Second, it forces the programmer to keep track of sessions explicitly. +This combination can cause security issues. + +In this challenge, one side of the connection can confuse a non-trusted connection for a trusted connection, and print the flag. +Can you trigger this confusion? ---- **NOTE:** -You must set the source port _before_ sending data! -Otherwise, Linux will pick a random source port (the default behavior, when `bind` is not called). +In this level, the flag will just be printed to the console when you trigger the confusion. +We'll work on realistically exfiltrating it later. diff --git a/intercepting-communication/udp-spoof-host/run b/intercepting-communication/udp-spoof-host/run index 575b001..18cebc4 100755 --- a/intercepting-communication/udp-spoof-host/run +++ b/intercepting-communication/udp-spoof-host/run @@ -2,7 +2,6 @@ import psutil import socket -import time import os from dojjail import Host, Network @@ -30,9 +29,8 @@ class ClientHost(Host): try: client_socket.sendto(b"ACTION?", ("10.0.0.3", 31337)) message, (peer_host, peer_port) = client_socket.recvfrom(1024) - if peer_port == 31337 and message.startswith(b"FLAG"): - _, flag_host, flag_port = message.strip().split(b":") - client_socket.sendto(flag.encode(), (flag_host, int(flag_port))) + if peer_port == 31337 and message.strip() == b"FLAG": + print(f"YOUR FLAG: {flag}") time.sleep(1) except ConnectionError: