diff --git a/README.md b/README.md index 68a1d65..d31e52f 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,14 @@ -# repl.me +# replme Throwaway devenvs in the web. -## idea +## getting started -Server manages docker containers. Streams io over ws connection between client and pty (bash) wrapper service running on each container. +```bash +git clone git@github.com:enowars/enowars8-service-replme.git +cd enowars8-service-replme/service +docker compose up +``` -Clients can access either shared container through user+pass, or let server spin up personal container identified through hash of username. - -Clients on shared container can interact with each other in "coffeelounge". Simple program to allow some chatting. - -## vulns - -1. Hash function for identification of personal container is weak. Has multiple master images. -2. Shared container has misconfigurations allowing access of files of other users (TBD) -3. Some vuln in coffeelounge (TBD) - -## flags - -Flags are stored in some user's home on the shared and personal containers. Flags are not stored in cleartext, but are printed in stdout by running some brainfuck code. Brainfuck program needs some input to generate the correct output from. Input could be "ENO". - -## stack - -- pty wrapper: xterm.js for prototype; C, libvterm for mvp -- server: go / next.js (TBD) -- client: html/css/js / react.js / next.js (TBD) -- coffeelounge: java +The service is now available via `http://127.0.0.1:6969` from the browser. diff --git a/documentation/documentation.pdf b/documentation/documentation.pdf index fe7ac87..200bcb7 100644 Binary files a/documentation/documentation.pdf and b/documentation/documentation.pdf differ diff --git a/documentation/tex/src/main.tex b/documentation/tex/src/main.tex index 402425b..8cc23dc 100644 --- a/documentation/tex/src/main.tex +++ b/documentation/tex/src/main.tex @@ -359,15 +359,15 @@ \subsection{How it works} \end{center} However, all \robotomonoRegular{/api/devenv/...} endpoints also accept a query parameter \robotomonoRegular{?uuid=} which overloads the \robotomonoRegular{} when specified. -\lstinputlisting[caption=service/backend/server/router.go\ (l.110-148), style=go, label={lst:devenv-uuid-snippet}]{src/devenv-uuid-snippet.go} +\lstinputlisting[caption=service/backend/server/router.go\ (lines\ 110-148), style=go, label={lst:devenv-uuid-snippet}]{src/devenv-uuid-snippet.go} The extracted DEVENV and \robotomonoRegular{uuid} are saved in the current requests context. We can see, that \robotomonoRegular{id} is seemingly sanitized via \robotomonoRegular{util.ExtractUuid}. Instead of using the \robotomonoRegular{devenv} from the context (that definitely belongs to the current user), the eventually executed controller function \robotomonoRegular{GetFileContent} uses the \robotomonoRegular{uuid} to compute the path of the requested file content. -\lstinputlisting[caption=service/backend/controller/devenv.go\ (l.239-262), style=go, label={lst:devenv-file-content-snippet}]{src/devenv-file-content-snippet.go} +\lstinputlisting[caption=service/backend/controller/devenv.go\ (lines\ 239-262), style=go, label={lst:devenv-file-content-snippet}]{src/devenv-file-content-snippet.go} Herein lies the second vulnerability. Due to the \robotomonoRegular{util.ExtractUuid} function (seen in Listing \ref{lst:devenv-uuid-snippet}) which does not sanitize user input correctly, the adversary is able use path traversal to retrieve the contents of files belonging to DEVENVs owned by other users. -\lstinputlisting[caption=service/backend/util/encoding.go\ (l.21-29), style=go, label={lst:extract-uuid-snippet}]{src/extract-uuid-snippet.go} +\lstinputlisting[caption=service/backend/util/encoding.go\ (lines\ 21-29), style=go, label={lst:extract-uuid-snippet}]{src/extract-uuid-snippet.go} In line 6 in Listing \ref{lst:extract-uuid-snippet} the "i" of the left \robotomonoRegular{uuid} variable is not an ASCII "i". Instead it is the "Cyrillic Small Letter Byelorussian-Ukrainian I" (\robotomonoRegular{U+0456}), a unicode look-alike. Therefore, in line 8, the \robotomonoRegular{uuid} defined in line 1 which is just set to the user input is returned -- completely unescaped. @@ -399,7 +399,7 @@ \subsection{How it works} All the ALPINEs share the same DIND network. That means an adversary can send requests to an ALPINEs CHILD-BACKEND from another ALPINE. But, the CHILD-BACKENDs API is secured with an API key, that is randomly generated once for all ALPINEs per service. This API key lies in the environment of the root user of an ALPINE. To register a user on an ALPINE the client sends some username and password key-pair. Without being properly sanitized, the password is forwarded by the MAIN-BACKEND to the target ALPINEs CHILD-BACKEND. The following code is then executed by the CHILD-BACKEND. -\lstinputlisting[caption=service/image/service/user.go\ (l.148-188), style=go]{src/create-user-snippet.go} +\lstinputlisting[caption=service/image/service/user.go\ (lines\ 148-188), style=go]{src/create-user-snippet.go} As we can see it is just a plain \robotomonoRegular{sh} command. Herein lies the third vulnerability. The adversary can execute abitrary \robotomonoRegular{sh} commands with root rights on an ALPINE.