-
Notifications
You must be signed in to change notification settings - Fork 10
Sadserver instance on redis instance #459
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: redis-instance
Are you sure you want to change the base?
Changes from all commits
b105feb
24f24e2
b566485
ffd0a9b
18d35b7
5e78342
08bc637
9bdd2f0
e9928f0
e6ecd93
daa11d7
de7da98
e70e2d6
21add01
701840f
8a2ae69
1e455b9
3df110e
33fc404
d719aad
d698441
bde55ee
2025eff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,53 @@ | ||||||
| FROM golang:1.23 AS builder | ||||||
|
|
||||||
| RUN apt-get update && apt-get install -y \ | ||||||
| make git gcc util-linux \ | ||||||
| && rm -rf /var/lib/apt/lists/* | ||||||
|
|
||||||
| WORKDIR /app | ||||||
|
|
||||||
| COPY go.mod go.sum ./ | ||||||
| RUN go mod download | ||||||
|
|
||||||
| COPY . . | ||||||
|
|
||||||
| RUN cp scripts/docker-enter /usr/bin/docker-enter && \ | ||||||
| cp scripts/docker_enter /usr/bin/docker_enter && \ | ||||||
| chmod u+s /usr/bin/docker_enter && \ | ||||||
| gcc -o /usr/bin/importenv scripts/importenv.c | ||||||
|
|
||||||
| RUN make build | ||||||
|
|
||||||
| FROM ubuntu:22.04 | ||||||
|
|
||||||
| RUN apt-get update && apt-get install -y ca-certificates curl gnupg lsb-release \ | ||||||
| && rm -rf /var/lib/apt/lists/* | ||||||
|
|
||||||
| RUN install -m 0755 -d /etc/apt/keyrings && \ | ||||||
| curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \ | ||||||
| chmod a+r /etc/apt/keyrings/docker.gpg && \ | ||||||
| echo \ | ||||||
| "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ | ||||||
| $(. /etc/os-release && echo $VERSION_CODENAME) stable" \ | ||||||
| > /etc/apt/sources.list.d/docker.list && \ | ||||||
| apt-get update && \ | ||||||
| apt-get install -y \ | ||||||
| redis-tools \ | ||||||
| postgresql-client \ | ||||||
| docker-ce-cli \ | ||||||
| docker-compose-plugin \ | ||||||
| docker-buildx-plugin && \ | ||||||
| apt-get clean && rm -rf /var/lib/apt/lists/* | ||||||
|
|
||||||
| COPY --from=builder /go/bin/beast /usr/local/bin/beast | ||||||
|
|
||||||
| COPY --from=builder /usr/bin/docker-enter /usr/local/bin/docker-enter | ||||||
| COPY --from=builder /usr/bin/docker_enter /usr/local/bin/docker_enter | ||||||
| COPY --from=builder /usr/bin/importenv /usr/local/bin/importenv | ||||||
|
|
||||||
| COPY setup.sh /usr/local/bin/setup.sh | ||||||
| RUN chmod +x /usr/local/bin/setup.sh | ||||||
|
|
||||||
| EXPOSE 5005 | ||||||
|
|
||||||
| ENTRYPOINT ["setup.sh"] | ||||||
|
||||||
| ENTRYPOINT ["setup.sh"] | |
| ENTRYPOINT ["/usr/local/bin/setup.sh"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -81,3 +81,66 @@ installenv: | |
| @./scripts/installenv.sh | ||
|
|
||
| .PHONY: build format test check_format tools docs installenv | ||
|
|
||
| # ── Docker Compose Targets ──────────────────────────────────────────────────── | ||
| # Usage: make up NAME=myctf | ||
| # | ||
| # NAME (required, no spaces) — used to create a .<NAME> folder on the host which | ||
| # is mounted as /root/.beast inside the beast container. This keeps each | ||
| # deployment isolated and named. | ||
| # | ||
| # Prerequisites: | ||
| # - config.toml must exist alongside this Makefile. | ||
| # - In config.toml set psql_config.host = "postgres" (the compose service name). | ||
| # | ||
|
Comment on lines
+92
to
+95
|
||
| # Targets: | ||
| # make up NAME=<name> — set up .<name>/, copy config, start services | ||
| # make down NAME=<name> — stop and remove services | ||
| # make logs NAME=<name> — tail beast service logs | ||
|
|
||
| check-name: | ||
| @if [ -z "$(NAME)" ]; then \ | ||
| echo "Error: NAME is required. Usage: make up NAME=myctf"; \ | ||
| exit 1; \ | ||
| fi | ||
| @if echo "$(NAME)" | grep -q "[[:space:]]"; then \ | ||
| echo "Error: NAME must not contain spaces"; \ | ||
| exit 1; \ | ||
| fi | ||
|
|
||
| check-config: | ||
| @if [ ! -f "config.toml" ]; then \ | ||
| echo "Error: config.toml not found in current directory."; \ | ||
| echo "Place your config.toml here (see _examples/example.config.toml)."; \ | ||
| echo "Ensure psql_config.host = \"postgres\" for the compose network."; \ | ||
| exit 1; \ | ||
| fi | ||
|
|
||
| BEAST_DIR = $(HOME)/.$(NAME) | ||
|
|
||
| setup-beast-dir: check-name check-config | ||
| @echo "[*] Setting up $(BEAST_DIR)..." | ||
| @mkdir -p $(BEAST_DIR)/assets/logo | ||
| @mkdir -p $(BEAST_DIR)/assets/mailTemplates | ||
| @mkdir -p $(BEAST_DIR)/remote | ||
| @mkdir -p $(BEAST_DIR)/uploads | ||
| @mkdir -p $(BEAST_DIR)/secrets | ||
| @mkdir -p $(BEAST_DIR)/scripts | ||
| @mkdir -p $(BEAST_DIR)/staging | ||
| @mkdir -p $(BEAST_DIR)/cache | ||
| @mkdir -p $(BEAST_DIR)/logs | ||
| @cp config.toml $(BEAST_DIR)/config.toml | ||
| @echo "[*] $(BEAST_DIR) ready (mounted as /root/.beast in container)" | ||
|
|
||
| up: setup-beast-dir | ||
| @echo "[*] Starting beast services (project: $(NAME))..." | ||
| @BEAST_DIR=$(BEAST_DIR) docker compose --project-name $(NAME) up -d --build | ||
| @echo "[*] Beast API running at http://localhost:5005" | ||
|
|
||
| down: check-name | ||
| @docker compose --project-name $(NAME) down | ||
|
|
||
| logs: check-name | ||
| @docker compose --project-name $(NAME) logs -f beast | ||
|
|
||
| .PHONY: check-name check-config setup-beast-dir up down logs | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,17 @@ | ||
| FROM php:7.4-apache | ||
|
|
||
| # Install MySQL extension | ||
| RUN apt-get update && apt-get install -y --no-install-recommends openssh-server \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| RUN groupadd -g 1337 beast-grp \ | ||
| && useradd -u 1337 -g 1337 -ms /bin/bash beast | ||
|
|
||
| RUN docker-php-ext-install mysqli pdo pdo_mysql | ||
|
|
||
| # Copy challenge files | ||
| COPY challenge/ /var/www/html/ | ||
| COPY check.sh /challenge/check.sh | ||
|
|
||
| # Set permissions | ||
| RUN chown -R www-data:www-data /var/www/html | ||
| RUN chown -R www-data:www-data /var/www/html \ | ||
| && chmod +x /challenge/check.sh | ||
|
|
||
| EXPOSE 80 | ||
| EXPOSE 80 22 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| #!/bin/bash | ||
| # Placeholder for Beast instanced challenges (dynamic flag / checks live here in real challenges). | ||
| exit 0 |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,6 +2,7 @@ package api | |||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||
| "errors" | ||||||||||||||||||||||||||||||||||||||||
| "golang.org/x/crypto/ssh" | ||||||||||||||||||||||||||||||||||||||||
| "log" | ||||||||||||||||||||||||||||||||||||||||
| "net/http" | ||||||||||||||||||||||||||||||||||||||||
| "strings" | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -215,10 +216,10 @@ func register(c *gin.Context) { | |||||||||||||||||||||||||||||||||||||||
| email = strings.TrimSpace(strings.ToLower(email)) | ||||||||||||||||||||||||||||||||||||||||
| sshKey = strings.TrimSpace(sshKey) | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| if username == "" || password == "" || email == "" { | ||||||||||||||||||||||||||||||||||||||||
| if username == "" || password == "" || email == "" || sshKey == "" { | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| c.JSON(http.StatusBadRequest, HTTPPlainResp{ | ||||||||||||||||||||||||||||||||||||||||
| Message: "Username, password and email can not be empty", | ||||||||||||||||||||||||||||||||||||||||
| Message: "Username, password, email, and sshKey can not be empty", | ||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -230,6 +231,15 @@ func register(c *gin.Context) { | |||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| key, _, _, _, err := ssh.ParseAuthorizedKey([]byte(sshKey)) | ||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||
| c.JSON(http.StatusBadRequest, HTTPErrorResp{ | ||||||||||||||||||||||||||||||||||||||||
| Error: "SSH Key is not valid", | ||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| sshKey = string(ssh.MarshalAuthorizedKey(key)) | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+234
to
+242
|
||||||||||||||||||||||||||||||||||||||||
| key, _, _, _, err := ssh.ParseAuthorizedKey([]byte(sshKey)) | |
| if err != nil { | |
| c.JSON(http.StatusBadRequest, HTTPErrorResp{ | |
| Error: "SSH Key is not valid", | |
| }) | |
| } | |
| sshKey = string(ssh.MarshalAuthorizedKey(key)) | |
| if sshKey != "" { | |
| key, _, _, _, err := ssh.ParseAuthorizedKey([]byte(sshKey)) | |
| if err != nil { | |
| c.JSON(http.StatusBadRequest, HTTPErrorResp{ | |
| Error: "SSH Key is not valid", | |
| }) | |
| return | |
| } | |
| sshKey = string(ssh.MarshalAuthorizedKey(key)) | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The image sets the setuid bit on
/usr/bin/docker_enter. If this binary is ever executable by a non-root user inside the container, it becomes a straightforward privilege-escalation path. If setuid is not strictly required, drop it; otherwise document why it’s needed and consider restricting permissions/ownership to reduce the attack surface.