Varonis Labs discovers SQLi and access flaws in Zendesk
Varonis helped solve an SQLi vulnerability, and an access control flaw in Zendesk Explore that would have allowed a threat actor to leak data from Zendesk customer accounts with Explore enabled. Zendesk quickly resolved the issue, and there is no longer this flaw in Explore. As a result, no action is needed from current customers.
There is no evidence any Zendesk Explore customer accounts were exploited, and Zendesk started working on a fix the same day it was reported. The company fixed multiple bugs in less than one workweek.
Before it was patched, the flaw would have allowed threat actors to access conversations, email addresses, tickets, comments, and other information from Zendesk accounts with Explore enabled.
An attacker would first register for the ticketing service of its victim's Zendesk account as a new external user to exploit the vulnerability. Registration is enabled by default because many Zendesk customers rely on end-users submitting support tickets directly via the web. Zendesk Explore is not enabled by default but is heavily advertised as a requirement for the analytic insights page.
Zendesk uses multiple GraphQL APIs in its products, especially in the administration console. Because GraphQL is a relatively new API format, Varonis started its research there. It found one particularly interesting object type in Zendesk Explore named QueryTemplate.
The querySchema field stood out because it contains a Base64-encoded XML document named Query inside of a JSON object, and many of the attributes in the XML were Base64-encoded JSON objects themselves. Translation? That's a Base64-encoded JSON object, inside a Base64-encoded XML document, inside a JSON object.
Multiple nested encodings always catch Varonis’ attention because a large number of wrappers around data usually means many different services are used to process this data. More code usually means more potential locations for vulnerabilities.
For this reason, Varonis dug deeper into Zendesk Explore using the admin user of its lab account in Zendesk.
When visualizing a report in Zendesk Explore, Varonis found an API called execute-query. This API method accepts a JSON object with the Query XML and multiple other XML parameters, some of which are encoded in Base64.
One of the fields passed to the API is extra_param3_value, which includes a plain-text XML document, DesignSchema, not encoded in Base64. This document defines the relationship between an AWS RDS (managed relational database) and the aforementioned Query XML document.
All the name attributes in this XML document, which define the tables and columns to be queried, were vulnerable to a SQL injection attack. The challenge for Varonis was exploiting the SQLi vulnerability to exfiltrate data.
The XML parsing engine on the back end was willing to accept single-quoted attributes instead of the default double-quoted attributes, allowing Varonis to escape the double-quotes in the table name.
Now Varonis needed a way to write strings in the query without using single or double quotes.
Fortunately, PostgreSQL, the database used by Zendesk Explore, provides a convenient method for representing strings: dollar-quoted string constants. The character "$$" can be used to define a string instead of the standard single quote character in an SQL statement.
Using this string representation method, Varonis could extract the list of tables from Zendesk's RDS instance and continue to exfiltrate all the information stored in the database. It included email addresses of users, leads, deals from the CRM, live agent conversations, tickets, help centre articles, and more.
SQL injections are always interesting but being able to exfiltrate data as an admin could be more exciting. So, as Varonis was looking for a broader impact, it decided to study how this execute-query API worked.
The execute-query API method accepts a JSON payload containing a “content” object with “query,” “cubeModels,” and “datasources” properties.
“query" contains a Query XML document with the columns, rows, slicers, measures, and explosions of the query, as well as the visualization configuration in JSON format. The document also contains a reference to the "cubeModels" property. "cubeModels" includes an XML document named "OLAPSchema" that defines the tables that can be queried in the selected data source.
The execute-query API did not perform several logical checks on requests.
The integrity of documents was not checked, allowing Varonis’ team to modify them in ways that exposed the system's inner workings.
“query,” “datasources,” and “cubeModels” IDs were not evaluated to see if they belonged to the current user.
Finally, and most critically, the API endpoint did not verify that the caller had permission to access the database and execute queries. As a result, a newly created end-user could invoke this API, change the query, and steal data from any table in the target Zendesk account's RDS; no SQLi is required.