diff --git a/browser_devtools/Dockerfile b/browser_devtools/Dockerfile new file mode 100644 index 0000000..2cb8647 --- /dev/null +++ b/browser_devtools/Dockerfile @@ -0,0 +1,12 @@ +FROM node:lts-alpine + +WORKDIR /usr/app + +COPY websockets.js ./ + +RUN npm init -y +RUN npm install ws + +EXPOSE 8080 + +CMD ["node", "websockets.js"] \ No newline at end of file diff --git a/browser_devtools/apps.py b/browser_devtools/apps.py index 8681842..85173a6 100644 --- a/browser_devtools/apps.py +++ b/browser_devtools/apps.py @@ -5,4 +5,6 @@ class BrowserDevtoolsConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" name = "browser_devtools" has_tasks = True + use_docker = True + container_protocol = "ws" display_name = "Browser Devtools" diff --git a/browser_devtools/static/browser_devtools/courier_intercept.js b/browser_devtools/static/browser_devtools/courier_intercept.js new file mode 100644 index 0000000..51d7e77 --- /dev/null +++ b/browser_devtools/static/browser_devtools/courier_intercept.js @@ -0,0 +1,3 @@ +const wsUri = `ws://${window.location.host}/envs/browser_devtools/`; +console.log(wsUri); +const websocket = new WebSocket(wsUri); \ No newline at end of file diff --git a/browser_devtools/templates/browser_devtools/courier_intercept.html b/browser_devtools/templates/browser_devtools/courier_intercept.html new file mode 100644 index 0000000..ffd0104 --- /dev/null +++ b/browser_devtools/templates/browser_devtools/courier_intercept.html @@ -0,0 +1,14 @@ +{% extends "ctef_web/task.html" %} + +{% block head %} +{% load static %} + +{% endblock %} + +{% block task %} + +{% load task %} + +
Test!
+ +{% endblock %} \ No newline at end of file diff --git a/browser_devtools/views.py b/browser_devtools/views.py index 15dae20..1fd0b7d 100644 --- a/browser_devtools/views.py +++ b/browser_devtools/views.py @@ -7,3 +7,7 @@ @define_task(name="Watch your head!", clues="clues/watch_your_head.md") def watch_your_head(request: HttpRequest, context): return render(request, "browser_devtools/watch_your_head.html", context) + +@define_task(name="Courier intercept") +def courier_intercept(request: HttpRequest, context): + return render(request, "browser_devtools/courier_intercept.html", context) \ No newline at end of file diff --git a/browser_devtools/websockets.js b/browser_devtools/websockets.js new file mode 100644 index 0000000..ce8f91a --- /dev/null +++ b/browser_devtools/websockets.js @@ -0,0 +1,13 @@ +import { WebSocketServer } from 'ws'; + +const wss = new WebSocketServer({ port: 8080 }); + +wss.on('connection', function connection(ws) { + ws.on('error', console.error); + + ws.on('message', function message(data) { + console.log('received: %s', data); + }); + + ws.send('something'); +}); \ No newline at end of file diff --git a/ctef/asgi.py b/ctef/asgi.py index 4a2a060..aeaf4b2 100644 --- a/ctef/asgi.py +++ b/ctef/asgi.py @@ -19,12 +19,19 @@ asgi_application = get_asgi_application() from ctef_core.routing import websocket_urlpatterns +from . import urls +# Add the websocket url patterns from the containers +websocket_urlpatterns = websocket_urlpatterns + urls.wspatterns +print(websocket_urlpatterns) + +# TODO: Adapt this to forward websocket connections to container proxy as well +# https://channels.readthedocs.io/en/latest/topics/routing.html# application = ProtocolTypeRouter( { "http": asgi_application, "websocket": AllowedHostsOriginValidator( AuthMiddlewareStack(URLRouter(websocket_urlpatterns)) - ) + ), } ) diff --git a/ctef/urls.py b/ctef/urls.py index 1ae912a..a06a108 100644 --- a/ctef/urls.py +++ b/ctef/urls.py @@ -29,6 +29,8 @@ path("admin/", admin.site.urls), ] +wspatterns = [] + # Import and register all task views in installed CTF modules. from ctef_core.common import fetch_ctf_modules from ctef_web.views import config_hints_view @@ -49,7 +51,17 @@ container = client.containers.get(container_name) IPAddress = container.attrs["NetworkSettings"]["IPAddress"] - urlpatterns.append( + try: + if ctf_module.container_protocol == "ws": + pattern_collection = wspatterns + else: + pattern_collection = urlpatterns + except: + pattern_collection = urlpatterns + + # TODO: Maybe just writing a Proxy consumer would be the easiest. + # Or maybe extend ProxyView? + pattern_collection.append( re_path( f"envs/{module_name}/(?P