From 37673ff81be671a28ef21b876ff6332f4e2c37f2 Mon Sep 17 00:00:00 2001 From: Connor Nelson Date: Wed, 18 Oct 2023 15:42:02 -0700 Subject: [PATCH] Change services from unix to tcp --- .../20_start_code_server.sh | 8 ++--- .../38_start_windows_gui.sh | 22 +++---------- challenge/docker-entrypoint.d/39_start_gui.sh | 33 +++++++------------ challenge/docker-entrypoint.sh | 4 +-- docker-compose.yml | 6 ++++ dojo_plugin/api/v1/docker.py | 12 ++----- dojo_plugin/pages/desktop.py | 6 ++-- dojo_plugin/pages/workspace.py | 2 +- dojo_plugin/utils/__init__.py | 13 ++++++-- script/container-setup.sh | 3 +- 10 files changed, 46 insertions(+), 63 deletions(-) diff --git a/challenge/docker-entrypoint.d/20_start_code_server.sh b/challenge/docker-entrypoint.d/20_start_code_server.sh index ea84d7dda..e6ee0607d 100755 --- a/challenge/docker-entrypoint.d/20_start_code_server.sh +++ b/challenge/docker-entrypoint.d/20_start_code_server.sh @@ -1,17 +1,17 @@ #!/bin/sh -mkdir /tmp/code-server +mkdir -p /tmp/.dojo/code-server start-stop-daemon --start \ - --pidfile /tmp/code-server/code-server.pid \ + --pidfile /tmp/.dojo/code-server/code-server.pid \ --make-pidfile \ --background \ --no-close \ --startas /usr/bin/code-server \ -- \ --auth=none \ - --socket=/home/hacker/.local/share/code-server/workspace.socket \ + --bind-addr=dojo-user:6080 \ --extensions-dir=/opt/code-server/extensions \ --disable-telemetry \ >/tmp/code-server/code-server.log \ + >>/tmp/.dojo/code-server/code-server.log \ 2>&1 diff --git a/challenge/docker-entrypoint.d/38_start_windows_gui.sh b/challenge/docker-entrypoint.d/38_start_windows_gui.sh index e253cede0..d7e5a9478 100755 --- a/challenge/docker-entrypoint.d/38_start_windows_gui.sh +++ b/challenge/docker-entrypoint.d/38_start_windows_gui.sh @@ -2,32 +2,18 @@ if ! find /challenge -name '*.exe' -exec false {} + then - mkdir -p /tmp/vnc /home/hacker/.vnc + mkdir -p /tmp/.dojo/vnc /home/hacker/.vnc start-stop-daemon --start \ - --pidfile /tmp/vnc/websockify-windows.pid \ + --pidfile /tmp/.dojo/vnc/websockify-windows.pid \ --make-pidfile \ --background \ --no-close \ --startas /usr/bin/websockify \ -- \ --web /usr/share/novnc/ \ - 24153 \ + dojo-user:6082 \ localhost:5912 \ >/tmp/vnc/websockify-windows.log \ - 2>&1 - - rm -f /home/hacker/.vnc/novnc-windows.socket - start-stop-daemon --start \ - --pidfile /tmp/vnc/socat-windows.pid \ - --make-pidfile \ - --background \ - --no-close \ - --startas /usr/bin/socat \ - -- \ - UNIX-LISTEN:/home/hacker/.vnc/novnc-windows.socket,fork \ - TCP-CONNECT:localhost:24153 \ - >/tmp/vnc/socat-windows.log \ + >>/tmp/.dojo/vnc/websockify-windows.log \ 2>&1 fi diff --git a/challenge/docker-entrypoint.d/39_start_gui.sh b/challenge/docker-entrypoint.d/39_start_gui.sh index 6746bea35..45d3a4fcb 100755 --- a/challenge/docker-entrypoint.d/39_start_gui.sh +++ b/challenge/docker-entrypoint.d/39_start_gui.sh @@ -1,11 +1,13 @@ #!/bin/sh -mkdir -p /tmp/vnc /home/hacker/.vnc +mkdir -p /tmp/.dojo/vnc /home/hacker/.vnc + echo "$(head -c32 /dev/urandom | md5sum | head -c8)" > /home/hacker/.vnc/pass-interact echo "$(head -c32 /dev/urandom | md5sum | head -c8)" > /home/hacker/.vnc/pass-view cat /home/hacker/.vnc/pass-interact /home/hacker/.vnc/pass-view | tigervncpasswd -f > /home/hacker/.vnc/vncpass + start-stop-daemon --start \ - --pidfile /tmp/vnc/vncserver.pid \ + --pidfile /tmp/.dojo/vnc/vncserver.pid \ --make-pidfile \ --background \ --no-close \ @@ -13,40 +15,27 @@ start-stop-daemon --start \ -- \ :42 \ -localhost=0 \ - -rfbunixpath /tmp/vnc/vnc_socket \ + -rfbunixpath /tmp/.dojo/vnc/vnc_socket \ -rfbauth /home/hacker/.vnc/vncpass \ -nolisten tcp \ -geometry 1024x768 \ -depth 24 \ >/tmp/vnc/vncserver.log \ + >>/tmp/.dojo/vnc/vncserver.log \ 2>&1 + start-stop-daemon --start \ - --pidfile /tmp/vnc/websockify.pid \ + --pidfile /tmp/.dojo/vnc/websockify.pid \ --make-pidfile \ --background \ --no-close \ --startas /usr/bin/websockify \ -- \ --web /usr/share/novnc/ \ - 24152 \ - --unix-target=/tmp/vnc/vnc_socket \ - >/tmp/vnc/websockify.log \ - 2>&1 - -rm -f /home/hacker/.vnc/novnc.socket -start-stop-daemon --start \ - --pidfile /tmp/vnc/socat.pid \ - --make-pidfile \ - --background \ - --no-close \ - --startas /usr/bin/socat \ - -- \ - UNIX-LISTEN:/home/hacker/.vnc/novnc.socket,fork \ - TCP-CONNECT:localhost:24152 \ + dojo-user:6081 \ + --unix-target=/tmp/.dojo/vnc/vnc_socket \ >/tmp/vnc/socat.log \ + >>/tmp/.dojo/vnc/websockify.log \ 2>&1 seq 1 50 | while read cnt; do sleep 0.1; [ -e /tmp/.X11-unix/X42 ] && break; done diff --git a/challenge/docker-entrypoint.sh b/challenge/docker-entrypoint.sh index a888b7b08..a6b921c0f 100755 --- a/challenge/docker-entrypoint.sh +++ b/challenge/docker-entrypoint.sh @@ -1,7 +1,7 @@ #!/bin/sh -e -exec >/tmp/.startup_log 2>&1 -chmod 600 /tmp/.startup_log +mkdir -p /tmp/.dojo +exec >/tmp/.dojo/entrypoint.log 2>&1 for SCRIPT in /opt/pwn.college/docker-entrypoint.d/* do diff --git a/docker-compose.yml b/docker-compose.yml index bf3c7562a..5f9cdd2c6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -127,6 +127,12 @@ services: - ./nginx-proxy/etc/passwd:/etc/passwd:ro - ./data/homes:/var/homes:shared - /var/run/docker.sock:/tmp/${DOCKER_PSLR}/docker.sock:ro + networks: + default: + user_network: + aliases: + - nginx + ipv4_address: 10.0.0.3 nginx-certs: container_name: nginx_certs diff --git a/dojo_plugin/api/v1/docker.py b/dojo_plugin/api/v1/docker.py index 694eb3014..7fc21d50e 100644 --- a/dojo_plugin/api/v1/docker.py +++ b/dojo_plugin/api/v1/docker.py @@ -12,7 +12,7 @@ from ...config import HOST_DATA_PATH, INTERNET_FOR_ALL, WINDOWS_VM_ENABLED from ...models import Dojos, DojoModules, DojoChallenges -from ...utils import serialize_user_flag, simple_tar, random_home_path, SECCOMP, USER_FIREWALL_ALLOWED, module_challenges_visible +from ...utils import serialize_user_flag, simple_tar, random_home_path, SECCOMP, USER_FIREWALL_ALLOWED, module_challenges_visible, user_ipv4 from ...utils.dojo import dojo_accessible, get_current_dojo_challenge @@ -117,6 +117,7 @@ def start_container(user, dojo_challenge, practice): f"vm_{hostname}": "127.0.0.1", "challenge.localhost": "127.0.0.1", "hacker.localhost": "127.0.0.1", + "dojo-user": user_ipv4(user), **USER_FIREWALL_ALLOWED, }, init=True, @@ -130,15 +131,6 @@ def start_container(user, dojo_challenge, practice): auto_remove=True, ) - def user_ipv4(user): - # Subnet: 10.0.0.0/8 - # Reserved: 10.0.0.0/24, 10.255.255.0/24 - # Gateway: 10.0.0.1 - # User IPs: 10.0.1.0 - 10.255.254.255 - user_ip = (10 << 24) + (1 << 8) + user.id - assert user_ip < (10 << 24) + (255 << 16) + (255 << 8) - return f"{user_ip >> 24 & 0xff}.{user_ip >> 16 & 0xff}.{user_ip >> 8 & 0xff}.{user_ip & 0xff}" - user_network = docker_client.networks.get("user_network") user_network.connect(container, ipv4_address=user_ipv4(user), aliases=[f"user_{user.id}"]) diff --git a/dojo_plugin/pages/desktop.py b/dojo_plugin/pages/desktop.py index 3dc3ca227..4769a7cd8 100644 --- a/dojo_plugin/pages/desktop.py +++ b/dojo_plugin/pages/desktop.py @@ -74,21 +74,21 @@ def forward_desktop_res(route, socket_path, user_id, path=""): if not can_connect_to(user): abort(403) - return redirect_user_socket(user, socket_path, f"/{path}") + return redirect_user_socket(user, socket_path, path) @desktop.route("/desktop//") @desktop.route("/desktop//") @authed_only def forward_desktop(user_id, path=""): - return forward_desktop_res("desktop", ".vnc/novnc.socket", user_id, path) + return forward_desktop_res("desktop", 6081, user_id, path) @desktop.route("/desktop-win//") @desktop.route("/desktop-win//") @authed_only def forward_desktop_win(user_id, path=""): - return forward_desktop_res("desktop-win", ".vnc/novnc-windows.socket", user_id, path) + return forward_desktop_res("desktop-win", 6082, user_id, path) @desktop.route("/admin/desktops", methods=["GET"]) @admins_only diff --git a/dojo_plugin/pages/workspace.py b/dojo_plugin/pages/workspace.py index 435f4f047..c89368a2c 100644 --- a/dojo_plugin/pages/workspace.py +++ b/dojo_plugin/pages/workspace.py @@ -27,7 +27,7 @@ def forward_workspace(path=""): prefix = "/workspace/" assert request.full_path.startswith(prefix) path = request.full_path[len(prefix):] - return redirect_user_socket(get_current_user(), ".local/share/code-server/workspace.socket", f"/{path}") + return redirect_user_socket(get_current_user(), 6080, path) def redirect_workspace_referers(): diff --git a/dojo_plugin/utils/__init__.py b/dojo_plugin/utils/__init__.py index 0c4cf1f7a..a4bdfbe91 100644 --- a/dojo_plugin/utils/__init__.py +++ b/dojo_plugin/utils/__init__.py @@ -140,6 +140,15 @@ def serialize_user_flag(account_id, challenge_id, *, secret=None): user_flag = serializer.dumps(data)[::-1] return user_flag +def user_ipv4(user): + # Subnet: 10.0.0.0/8 + # Reserved: 10.0.0.0/24, 10.255.255.0/24 + # Gateway: 10.0.0.1 + # User IPs: 10.0.1.0 - 10.255.254.255 + user_ip = (10 << 24) + (1 << 8) + user.id + assert user_ip < (10 << 24) + (255 << 16) + (255 << 8) + return f"{user_ip >> 24 & 0xff}.{user_ip >> 16 & 0xff}.{user_ip >> 8 & 0xff}.{user_ip & 0xff}" + def redirect_internal(redirect_uri, auth=None): response = Response() if auth: @@ -150,9 +159,9 @@ def redirect_internal(redirect_uri, auth=None): response.headers["redirect_uri"] = redirect_uri return response -def redirect_user_socket(user, socket_path, url_path): +def redirect_user_socket(user, port, url_path): assert user is not None - return redirect_internal(f"http://unix:/var/homes/nosuid/{random_home_path(user)}/{socket_path}:{url_path}") + return redirect_internal(f"http://user_{user.id}:{port}/{url_path}") def render_markdown(s): raw_html = build_markdown(s or "") diff --git a/script/container-setup.sh b/script/container-setup.sh index ca702bccb..846915711 100755 --- a/script/container-setup.sh +++ b/script/container-setup.sh @@ -79,4 +79,5 @@ iptables -I DOCKER-USER -i user_network -j DROP for host in $(cat $DOJO_DIR/user_firewall.allowed); do iptables -I DOCKER-USER -i user_network -d $(host $host | awk '{print $NF; exit}') -j ACCEPT done - +iptables -I DOCKER-USER -i user_network -s 10.0.0.0/24 -m conntrack --ctstate NEW -j ACCEPT +iptables -I DOCKER-USER -i user_network -d 10.0.0.0/8 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT