The Device field from the Monitors table was interpolated directly into
shell commands (qx(), backticks, exec()) without sanitization, allowing
authenticated users with monitor-edit permissions to execute arbitrary
commands as www-data via the Device Path field.
Defense in depth:
- Input validation: reject Device values not matching /^\/dev\/[\w\/.\-]+$/
at save time in both web UI and REST API
- Output sanitization: use escapeshellarg() in PHP and quote validated
values in Perl at every shell execution point
Affected locations:
- scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm (control, zmcControl)
- scripts/zmpkg.pl.in (system startup)
- web/includes/Monitor.php (zmcControl)
- web/includes/functions.php (zmcStatus, zmcCheck, validDevicePath)
- web/includes/actions/monitor.php (save action)
- web/api/app/Model/Monitor.php (daemonControl, validation rules)
- web/api/app/Controller/MonitorsController.php (daemonStatus)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>