{"id":"GHSA-hfxh-rjv7-2369","aliases":[],"status":"published","title":"Uptime Kuma Authenticated remote code execution via TailscalePing","description":"### Summary\n\nThe `runTailscalePing` method of the `TailscalePing` class injects the `hostname` parameter inside a shell command, leading to a command injection and the possibility to run arbitrary commands on the server.\n\n### Details\n\nWhen adding a new monitor on Uptime Kuma, we can select the \"Tailscale Ping\" type. Then we can add a hostname and insert a command injection payload into it. The front-end application requires that the field follow a specific pattern, this validation only happens on the front-end and can be removed by removing the attribute `pattern` on the `input` element.\n\nhttps://github.com/louislam/uptime-kuma/blob/dc4242019331e65a79ac16deef97510144e01b12/server/monitor-types/tailscale-ping.js#L40-L46\n\nWe can finally add the new monitor and observe that our command is being executed.\n\n**NOTE:** When using Uptime Kuma inside a container, the \"TailScale Ping\" type is not visible. We can fake this information by intercepting WebSocket messages and set the `isContainer` option to `false`.\n\n### PoC\n\n* Authenticate.\n* Create a new monitor.\n* Select the TailScale Ping type (if not visible, see the note in the details section).\n* Insert the command injection payload inside the `hostname` field. (for example `$(id \u003e\u00262)`)\n* Remove the `pattern` requirement on the field.\n* Save and start the monitor.\n\n### Impact\n\nAn authenticated user can execute arbitrary command on the server running Uptime Kuma.\n\n### Remediation\n\nThere are other command execution in the codebase, they use a method `spawn` from the `child_process` module which does not interpret the command as a shell command, the same thing should be done here.\n\n**NOTE:** The Tailscale CLI seems to support the `--` sequence. It should be used between the `ping` subcommand and the `hostname` argument to avoid argument injection.","facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"published":"2023-11-27T17:25:11Z","modified":"2023-11-27T17:25:12Z","fixes":[{"ecosystem":"npm","package":"uptime-kuma","fixed_in":["1.23.7"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"uptime-kuma","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.23.0"},{"last_affected":"1.23.6"},{"fixed":"1.23.7"}]}]},{"source":"osv","ecosystem":"npm","package":"uptime-kuma","ranges":[{"type":"SEMVER","events":[{"introduced":"1.23.0"},{"fixed":"1.23.7"}]}]}],"references":[{"url":"https://github.com/louislam/uptime-kuma/security/advisories/GHSA-hfxh-rjv7-2369","tags":["web"]},{"url":"https://github.com/advisories/GHSA-hfxh-rjv7-2369"},{"url":"https://github.com/louislam/uptime-kuma","tags":["package"]}],"sources":{"ghsa":[{"id":"GHSA-hfxh-rjv7-2369","title":"Uptime Kuma Authenticated remote code execution via TailscalePing","description":"### Summary\n\nThe `runTailscalePing` method of the `TailscalePing` class injects the `hostname` parameter inside a shell command, leading to a command injection and the possibility to run arbitrary commands on the server.\n\n### Details\n\nWhen adding a new monitor on Uptime Kuma, we can select the \"Tailscale Ping\" type. Then we can add a hostname and insert a command injection payload into it. The front-end application requires that the field follow a specific pattern, this validation only happens on the front-end and can be removed by removing the attribute `pattern` on the `input` element.\n\nhttps://github.com/louislam/uptime-kuma/blob/dc4242019331e65a79ac16deef97510144e01b12/server/monitor-types/tailscale-ping.js#L40-L46\n\nWe can finally add the new monitor and observe that our command is being executed.\n\n**NOTE:** When using Uptime Kuma inside a container, the \"TailScale Ping\" type is not visible. We can fake this information by intercepting WebSocket messages and set the `isContainer` option to `false`.\n\n### PoC\n\n* Authenticate.\n* Create a new monitor.\n* Select the TailScale Ping type (if not visible, see the note in the details section).\n* Insert the command injection payload inside the `hostname` field. (for example `$(id \u003e\u00262)`)\n* Remove the `pattern` requirement on the field.\n* Save and start the monitor.\n\n### Impact\n\nAn authenticated user can execute arbitrary command on the server running Uptime Kuma.\n\n### Remediation\n\nThere are other command execution in the codebase, they use a method `spawn` from the `child_process` module which does not interpret the command as a shell command, the same thing should be done here.\n\n**NOTE:** The Tailscale CLI seems to support the `--` sequence. It should be used between the `ping` subcommand and the `hostname` argument to avoid argument injection.","status":"published","published":"2023-11-27T17:25:11Z","modified":"2023-11-27T17:25:12Z","updated_at":"2026-11-02T14:37:22.840002Z"}],"osv":[{"id":"GHSA-hfxh-rjv7-2369","title":"Uptime Kuma Authenticated remote code execution via TailscalePing","description":"### Summary\n\nThe `runTailscalePing` method of the `TailscalePing` class injects the `hostname` parameter inside a shell command, leading to a command injection and the possibility to run arbitrary commands on the server.\n\n### Details\n\nWhen adding a new monitor on Uptime Kuma, we can select the \"Tailscale Ping\" type. Then we can add a hostname and insert a command injection payload into it. The front-end application requires that the field follow a specific pattern, this validation only happens on the front-end and can be removed by removing the attribute `pattern` on the `input` element.\n\nhttps://github.com/louislam/uptime-kuma/blob/dc4242019331e65a79ac16deef97510144e01b12/server/monitor-types/tailscale-ping.js#L40-L46\n\nWe can finally add the new monitor and observe that our command is being executed.\n\n**NOTE:** When using Uptime Kuma inside a container, the \"TailScale Ping\" type is not visible. We can fake this information by intercepting WebSocket messages and set the `isContainer` option to `false`.\n\n### PoC\n\n* Authenticate.\n* Create a new monitor.\n* Select the TailScale Ping type (if not visible, see the note in the details section).\n* Insert the command injection payload inside the `hostname` field. (for example `$(id \u003e\u00262)`)\n* Remove the `pattern` requirement on the field.\n* Save and start the monitor.\n\n### Impact\n\nAn authenticated user can execute arbitrary command on the server running Uptime Kuma.\n\n### Remediation\n\nThere are other command execution in the codebase, they use a method `spawn` from the `child_process` module which does not interpret the command as a shell command, the same thing should be done here.\n\n**NOTE:** The Tailscale CLI seems to support the `--` sequence. It should be used between the `ping` subcommand and the `hostname` argument to avoid argument injection.","status":"published","published":"2023-11-27T17:25:11Z","modified":"2023-11-27T17:25:11Z","updated_at":"2026-11-02T15:46:48.920784Z"}]}}
