CVE-2020-15092: Stored XSS in TimelineJS3 (CVSS Score: 7.2)
This blog post describes a vulnerability I discovered in the TimelineJS3 library in February 2020. This vulnerability has a CVSS v3.1 Base Score of 7.2 (CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H), and is also disclosed on GitHub and the Knight Lab website.
The vulnerability was patched in version 3.7.0, and all prior version are vulnerable.
About TimelineJS3
TimelineJS3 (GitHub) is a JavaScript library used to generate a HTML timeline, showing different types of media and information in a nicely rendered, interactive format.
Data is typically provided by a Google Sheets backend, which easily enables many contributors to add data to a timeline. A common use case (and how I discovered the existence of this library) was contributing to a spreadsheet as a part of a class assignment, which is definitely a little more interesting than writing my 10,000th Canvas post.
TimelineJS3 also can import data from JSON, which was also vulnerable due to using the same rendering code, but I didn’t explore this data entry format.
The Vulnerability
When rendering data from the backend data store, some of the fields are parsed as HTML and directly written to the DOM. There is some filtering/validation done to the data (i.e. <script>
tags are removed) but these can be easily bypassed by using HTML events to trigger JavaScript execution on allowed elements. Therefore, if I were to add my favorite cat picture to the timeline with an <img>
tag and a malicious onload
attribute, I can achieve JavaScript execution in the browser of anyone who views the timeline.
Payload:
<img src="https://cdn.pixabay.com/photo/2014/11/30/14/11/kitty-551554__340.jpg" onload="alert('xss');">
Due to how TimelineJS adds timeline components to the DOM, this specific XSS payload is triggered at page load. The below GIF shows the alert window on page load.
A malicious actor could also include a button or another interactive element to trigger execution on user interaction.
Payload:
Hello! Click the button for more info
<br><br>
<button onclick="alert('xss');">Click Me</button>
There are many fields vulnerable to this type of arbitrary JS execution:
- Display Date (column I in the Google Sheet)
- Headline (column J)
- Text (column K)
If a Media element has been specified (Column L), these fields are vulnerable as well (without a Media element they won’t be included):
- Media Credit (column M)
- Media Caption (column N)
Impact
The above examples are just a few different ways an attacker could exploit this vulnerability. With this level of primitive, an attacker could steal cookies to impersonate another user (or any other type of data), execute arbitrary JavaScript in the victim’s browser, and more. However, this vulnerability is relatively difficult to exploit, due to being required to modify the Google Sheet or JSON file the timeline is being rendered from.
Here are a couple of the more likely exploitation scenarios:
- An instructor creates a Google Sheet for students to add timeline entries to. Then, a malicious student is given access to the Google Sheet (by design) can add a malicious entry to the timeline.
- A user creates a spreadsheet but enables anyone to write to it. Then, a malicious actor can identify a webpage using TimelineJS3 and a globally writable spreadsheet, and add a malicious entry to the timeline.
- This is possible because the URL for the spreadsheet is able to be derived from the
<iframe>
tag used to load TimelineJS3. Thesource
attribute is a spreadsheet ID, and the format of a Google Sheets URL ishttps://docs.google.com/spreadsheets/d/{id}/edit
.
- This is possible because the URL for the spreadsheet is able to be derived from the
Due to the decreased likelihood of exploitation, the disclosure on GitHub has a Moderate severity, even though the CVSS score puts this vulnerability at a High rating.
Remediation
Most users of TimelineJS3 use the latest
version from Knight Lab’s CDN and will automatically use the new version. Other users should consult the TimelineJS3 documentation and the GitHub security advisory to make sure they get to a safe version (3.7.0+)
Users are also encouraged to ensure they have proper access controls configured for their timeline data sources, and limit the number of parties that can write to them.
Timeline
- 2020/02/09: Reached out to a Knight Lab employee who maintains the project on GitHub
- 2020/02/18: Reached out again to the same individual
- 2020/02/18: Got a response
- 2020/02/18: Shared vulnerability details with Knight Lab
- 2020/02/21 - 2020/06/23: Many back and forth emails about the vulnerability and remediation
- 2020/06/23 - 2020/07/07: Discussion for patch timeline/notification
- 2020/07/01: CVE issued by GitHub (CVE-2020-15092)
- 2020/07/09: Publicly disclosed