5465 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / lab.sh SH
#!/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