mirror of
https://github.com/ZoneMinder/zoneminder.git
synced 2026-11-07 21:23:02 -05:00
ZM_Object's constructor takes either an id (which it loads from the database) or an array, which it trusts as the record's own fields. Several request-fed call sites passed the raw request value straight to new ZM\Event(), so a request that sends an array instead of a scalar -- eid[Id]=...&eid[MonitorId]=... -- had its fields adopted as the event row. The request then chose the MonitorId that canView() checks and the StorageId/Scheme/Id that Path() is built from. Impact: view_video.php turned this into an arbitrary file read (forge a viewable MonitorId, point Path() at any directory, append file=); ajax/events.php let a forged row pass the per-event permission check so archive/delete acted on a row the user could not see, and delete ran unlink on the forged Path(). validInt()/validCardinal() already return '' for a non-scalar, so route the request value through them first; an array becomes '' and ZM\Event loads the real row (or none). Fixed at the two affected sinks and centrally in getAffectedIds(), which several action handlers use to build the id list. Addresses GHSA-6h8f-gx4m-qqw4. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>