mirror of
https://github.com/ZoneMinder/zoneminder.git
synced 2026-10-16 03:32:31 -04:00
Event::Event() wrote the event's Cause and Notes into single-quoted literals of the Events INSERT without escaping them. Both come from outside the daemon: Cause includes the names of the alarmed zones, which any Monitors=Edit user can set, and the external trigger's cause and text, which zmtrigger.pl takes unauthenticated from TCP port 6802. A zone name could close the literal and fill the rest of the row with a subquery, copying any value the ZoneMinder database user can read, such as password hashes, into an event shown in the web UI. An ordinary apostrophe was enough to break it: the INSERT failed, and the constructor retries until it succeeds, so it logged the failure several times a second and the monitor recorded no further events until zmc was restarted. A zone named "Bob's drive" stopped motion recording. Escape both, as updateNotes() already does for the same column. While here, escape the other SQL values built from strings in src/: the Event_Data detections JSON, the DefaultVideo update, both Tags queries, the Servers lookup by ZM_SERVER_NAME and the device, path, protocol, host and port that the zmc monitor-loading queries match on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>