Patched Zoom Exploit: Altering Camera Settings via Remote SQL Injection
Old versions of Zoom’s software contained a SQL injection vulnerability that allowed a remote attacker to alter a victim’s settings, including camera privacy options. This issue, which affected the Mac and Linux clients, was quickly patched, and Zoom users are no longer impacted. I found this issue on April 7, I shared it with Zoom the same day, and it was fixed in the April 12 macOS release (4.6.11) and the April 14 Linux release (3.5.385850.0413). Now that this vulnerability has been patched and all users are required to upgrade to Zoom 5.0 or later, I wanted to offer both a technical description of how I found this issue and a look at some of the behind-the-scenes work which has gone into securing Zoom.
Zoom’s explosive rise in popularity presented a unique challenge to third-party security researchers like me. We foresaw that attackers would recognize the large new pool of potential victims and target Zoom from all angles. One particular concern of ours was Zoom’s use of desktop applications, which, unlike the in-browser version, exist outside of a browser’s security sandbox. Although attackers would be looking for exploitable security issues in the desktop clients, we researchers could try to find them first and give Zoom a head start to patch before they are exploited. I opted to investigate the client on Linux, where I was most familiar with testing tools, and start looking for security issues which carry over to more popular platforms.
Immediately, the web browser stands out as an easily reached attack surface of the Zoom desktop application. Visiting a Zoom meeting page in a browser can open the meeting in the application, so there must be some communication between the two. A CSRF-style attack from a malicious webpage might then be able to exploit the client. The Zoom meeting page source reveals that this browser-to-application communication occurs via the “zoommtg://” custom URI scheme. These URIs contain several parameters passed in a Base64-encoded blob, but it is not clear what all the parameters mean or how they might be exploited.
Rather than try to understand every parameter, I might make faster progress by looking for exploitable issues in the Zoom binary itself. This closed-source binary has no debugging symbols, and it would be too time consuming to reverse engineer large parts of the application. However, looking at the strings of the binary rapidly provides useful information. In the Zoom binary, there are several partial SQL queries with format specifiers, which indicates that SQL queries are composed at runtime instead of being properly hardcoded parameterized queries. This suggests potential SQL injection issues, but it is far from conclusive.
To investigate the partial SQL queries, it helps to see which queries are being executed by the application. This can be done by attaching to a running Zoom client with a debugger and setting a breakpoint at the SQL query function. Without debug symbols, however, I have no indication where that function is. Fortunately, one of the strings in the binary reveals that SQLite version 3.27.2 has been compiled into the application. The source code of the SQLite project is public domain, so once I find the location of one SQLite function in the Zoom binary, I can use it to rapidly identify all related functions. This continues until I find the “sqlite3LockAndPrepare” function which, as the name suggests, prepares a SQL statement for execution. I set a debugging breakpoint here and watch as the partial SQL queries are filled.
When I trigger the “zoommtg://” URI in the browser, it hits the breakpoint not once but several times. One of these queries updates a database entry with a long hexadecimal meeting code — the exact same hexadecimal code passed as the “tid” parameter in the URI’s encoded data. This confirms that any website can use CSRF techniques to trigger a database call in Zoom, but to see if this actually leads to SQL injection, I must investigate further.
Although any SQL injection vulnerability would be a problem, I need to know what impact it could have on a victim’s privacy to know how urgent it would be. By changing privacy settings in the application, I can use a SQL explorer to see which entries change in the application’s database. Some of the settings appear particularly sensitive: automatically joining meetings without user approval and joining meetings with webcam and audio enabled. A SQL injection attack could surreptitiously modify these values from their default, and, once Zoom has been closed and reopened, Zoom would automatically share the victim’s camera and audio with any meeting a malicious web page sends it to.
So far, all of this suggests a worrying vulnerability in the Zoom binary, but it is incomplete without an actual exploit. I use a crafted URI to send the application a simple payload with a lone single quote and check the database for results, but the attempted SQL injection fails. In a successful attack, the single quote would be interpreted as part of the SQL command, and all database table entries would be updated to the same value, but they are not. It appears that an input sanitization function replaces every single quote with two single quotes, preventing the attack. Common sanitization bypasses, like including a backslash character, also fail.
While it appears that Zoom is escaping common SQL attacks correctly, perhaps it is susceptible to a more obscure attack. A number of old web-application bugs exploit differences in how sanitization functions and backend systems treat Unicode, and there are several Unicode edge cases which are tricky to handle correctly. Perhaps a similar exploitation technique works here. After several failed attempts, I find the magic sequence which slips past the sanitization filter.
success \xC2' or 1=1;
An interesting property of UTF-8 Unicode strings might explain what is going on here. In ASCII strings, each byte in the string has a value below 0x80 and represents one character. In UTF-8 strings, most byte values represent the same thing as ASCII, but values above 0x80 represent the beginning of multi-byte characters. The sanitization function processes the payload and creates an ASCII string with a pair of single quote characters that does not cause SQL injection. However, before these bytes are passed to the query function, they are interpreted as a UTF-8 string. Byte 0xC2 in the payload shifts from representing an out-of-range ASCII character to representing the beginning of a two-byte UTF-8 character, preventing the next byte from being interpreted as a single quote. The UTF-8 interpretation contains only the remaining single quote, and the SQL injection attack succeeds.
As soon as I had enough to confirm the vulnerability, I began writing a report to submit to Zoom’s security team. Evan Johnson, one of the security researchers who was also testing Zoom, successfully replicated the issue on Mac, confirming that this issue affected a wide user base. We submitted our findings, reproduction steps, and recommendations to Zoom on April 7 via HackerOne, and the issue was triaged as high severity the following day.
Zoom fixed the vulnerability, issued updated versions of the client, and awarded us $2000 for reporting the problem. Since this vulnerability was difficult to exploit, and since Zoom now requires that all users upgrade to version 5.0 or later (which contains the patch), we feel comfortable publishing the details of the vulnerability. The mandatory upgrade closed the window on attackers who might want to exploit this issue, and so there is no risk to users in sharing the details of this exploit.
Since exploding in popularity, Zoom has taken many steps to improve their product’s security. They have patched bugs, added privacy controls, and expanded support for the in-browser client. A bug bounty program is just one possible facet of a strong defense against attackers, but in this case, we reached a good outcome. Overall, I believe this shows that Zoom security has been moving in the right direction and has been in capable hands as it navigates this transition. We caught this issue early, it was quickly fixed, and as a result, users of Zoom are now more secure.