Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 20 additions & 14 deletions user-container/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ RUN rm -f /etc/dpkg/dpkg.cfg.d/excludes && \
grep \
man-db \
manpages \
openssh-server \
xxd \
sudo \
&& if [ "$(dpkg-divert --truename /usr/bin/man)" = "/usr/bin/man.REAL" ]; then rm -f /usr/bin/man && dpkg-divert --quiet --remove --rename /usr/bin/man; fi \
Expand All @@ -32,11 +31,6 @@ ENV LESSCHARSET=utf-8
# Create ieee user
RUN useradd -m -s /bin/bash ieee

RUN mkdir -p /etc/ssh/sshd_config.d /run/sshd && \
rm -f /etc/ssh/ssh_host_* && \
printf 'PermitRootLogin no\nAllowUsers ieee\nPasswordAuthentication yes\nKbdInteractiveAuthentication no\nChallengeResponseAuthentication no\nUseDNS no\nX11Forwarding no\nAllowAgentForwarding no\nAllowTcpForwarding no\nGatewayPorts no\nPermitTunnel no\nDisableForwarding yes\n' > /etc/ssh/sshd_config.d/workshop.conf && \
chmod 600 /etc/ssh/sshd_config.d/workshop.conf

# Sudo: ieee can ONLY run the verifier helpers and fixed challenge emitters as root
RUN echo "ieee ALL=(root) NOPASSWD: /opt/verifier.sh, /opt/cmdlog.sh, /opt/pipes-step1.sh, /opt/pipes-noisy.sh" > /etc/sudoers.d/ieee && \
chmod 440 /etc/sudoers.d/ieee
Expand Down Expand Up @@ -71,15 +65,27 @@ RUN printf '#!/bin/bash\nset -e\nname=$(basename "$0")\ncase "$name" in\n ver
# Run setup to create all challenge files and directories
RUN /opt/setup.sh

# Add transparent command logging to .bashrc (logged via sudo to root-only file)
RUN echo '' >> /home/ieee/.bashrc && \
echo 'export LANG=C.UTF-8' >> /home/ieee/.bashrc && \
echo 'export LESSCHARSET=utf-8' >> /home/ieee/.bashrc && \
echo '_log_cmd() { local c=$(history 1 | sed "s/^[[:space:]]*[0-9]*[[:space:]]*//"); [ -n "$c" ] && cmdlog "$c"; }' >> /home/ieee/.bashrc && \
echo 'PROMPT_COMMAND="_log_cmd;${PROMPT_COMMAND}"' >> /home/ieee/.bashrc && \
chown ieee:ieee /home/ieee/.bashrc
# Keep a clean baseline for challenge 7.3 resets.
RUN cp /home/ieee/.bashrc /opt/.bashrc.baseline && chmod 644 /opt/.bashrc.baseline

# Add transparent command logging outside the student's ~/.bashrc so challenge 7.3
# cannot break later verifier checks by accident.
RUN printf '%s\n' \
'export LANG=C.UTF-8' \
'export LESSCHARSET=utf-8' \
'_workshop_log_cmd() {' \
' local c' \
' c=$(history 1 | sed "s/^[[:space:]]*[0-9]*[[:space:]]*//")' \
' [ -n "$c" ] && cmdlog "$c"' \
'}' \
'case ";${PROMPT_COMMAND:-};" in' \
' *";_workshop_log_cmd;"*) ;;' \
' "") PROMPT_COMMAND="_workshop_log_cmd" ;;' \
' *) PROMPT_COMMAND="_workshop_log_cmd;${PROMPT_COMMAND}" ;;' \
'esac' \
> /etc/profile.d/workshop-shell.sh && \
chmod 644 /etc/profile.d/workshop-shell.sh

Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Command logging is now installed in /etc/profile.d/workshop-shell.sh, which only runs for login shells. If a student opens a subshell with bash (non-login interactive), their commands won't be logged, and logged_since-based verifier checks can fail unexpectedly. Consider also installing the PROMPT_COMMAND hook into /etc/bash.bashrc (or another file sourced by all interactive bash shells), or ensure login shells source it for non-login shells as well.

Suggested change
# Ensure command logging is also enabled in non-login interactive bash shells
RUN printf '%s\n' \
'if [ -f /etc/profile.d/workshop-shell.sh ]; then' \
' . /etc/profile.d/workshop-shell.sh' \
'fi' \
>> /etc/bash.bashrc

Copilot uses AI. Check for mistakes.
# Entrypoint runs as root (starts services, then drops to ieee)
WORKDIR /home/ieee
EXPOSE 22
ENTRYPOINT ["/opt/entrypoint.sh"]
44 changes: 20 additions & 24 deletions user-container/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/bash
set -euo pipefail
# entrypoint.sh — Runs as root: starts services, then drops to ieee shell

AUDIT_DIR="/home/ieee/challenges/perms/audit"
Expand All @@ -14,7 +15,6 @@ HIDDEN_FLAG_FILE="/opt/.hidden_flag"
HIDDEN_PORT_FILE="/opt/.hidden_port"
WEB_SERVICE_CONFIG="/opt/.web_service"
HIDDEN_SERVICE_CONFIG="/opt/.hidden_service"
SSH_SECRET_ENV_CONFIG="/etc/ssh/sshd_config.d/workshop-secret.conf"

generate_token() {
printf '%s%s\n' "$1" "$(head -c 6 /dev/urandom | xxd -p)"
Expand All @@ -25,7 +25,10 @@ generate_hidden_port() {
}

write_secure_token() {
generate_token "$1" | tee "$2"
local token

token=$(generate_token "$1")
printf '%s\n' "$token" > "$2"
chmod 600 "$2"
}

Expand Down Expand Up @@ -76,20 +79,17 @@ write_service_config() {
chmod 600 "$1"
}

write_secret_env_config() {
local secret

secret=$(cat "$SECRET_FLAG_FILE")
mkdir -p /etc/ssh/sshd_config.d
printf 'SetEnv SECRET_FLAG=%s\n' "$secret" > "$SSH_SECRET_ENV_CONFIG"
chmod 600 "$SSH_SECRET_ENV_CONFIG"
}

configure_ssh_access() {
: "${IEEE_PASSWORD:=ieee}"
echo "ieee:${IEEE_PASSWORD}" | chpasswd
mkdir -p /run/sshd /etc/ssh/sshd_config.d
ssh-keygen -A >/dev/null 2>&1
start_flag_service() {
local config_file="$1"
local pid

python3 /opt/flag-server.py "$config_file" &
pid=$!
sleep 0.2
if ! kill -0 "$pid" 2>/dev/null; then
echo "Failed to start flag service for $config_file" >&2
exit 1
fi
}

start_network_services() {
Expand All @@ -100,8 +100,8 @@ start_network_services() {
write_service_config "$WEB_SERVICE_CONFIG" 8080 "$WEB_FLAG_FILE"
write_service_config "$HIDDEN_SERVICE_CONFIG" "$hidden_port" "$HIDDEN_FLAG_FILE"

python3 /opt/flag-server.py "$WEB_SERVICE_CONFIG" &
python3 /opt/flag-server.py "$HIDDEN_SERVICE_CONFIG" &
start_flag_service "$WEB_SERVICE_CONFIG"
start_flag_service "$HIDDEN_SERVICE_CONFIG"
}

# ============================================================
Expand Down Expand Up @@ -201,9 +201,6 @@ if [ ! -f "$HIDDEN_FLAG_FILE" ] || [ ! -f "$HIDDEN_PORT_FILE" ]; then
fi

write_getflag_script
rm -f /etc/profile.d/workshop-secret.sh
write_secret_env_config
configure_ssh_access

SPY_NAME=$(cat "$SPY_NAME_FILE")
SECRET_FLAG=$(cat "$SECRET_FLAG_FILE")
Expand Down Expand Up @@ -246,18 +243,17 @@ touch /opt/.progress /opt/.reset_markers
chmod 600 /opt/.progress /opt/.reset_markers

# ============================================================
# SSH server + optional local shell
# Runtime mode
# ============================================================

if [ -t 0 ] && [ -t 1 ]; then
/usr/local/bin/welcome
/usr/sbin/sshd -D -e &
export SECRET_FLAG
export HOME="$HOME_DIR"
export USER="ieee"
export LOGNAME="ieee"
export SHELL="/bin/bash"
exec runuser --preserve-environment -u ieee -- bash -l
else
exec /usr/sbin/sshd -D -e
exec tail -f /dev/null
fi
Loading
Loading