A tale of HTML Injection to Account takedown at Exercism.org
Table of Contents
#
About Exercism
Exercism is an online platform that helps people upskill their programming skills through practice and mentoring. They are an open-source organization with over 200 GitHub repositories, thousands of contributors, and a friendly, inclusive community.
I came to know about the platform in 2018 when my mentor - Vipin Pavithran asked me to improve my coding skills by practicing on Exercism.
Exercism is an amazing platform to learn to code. It has got an amazing set of challenges and a huge variety of learning tracks.
Enough of the back story, now let’s get to the fun part.
#
Background
I received an newsletter from exercism.io. It’s been around 3-4 years since I used the platform. I decided to have a look at their latest version. The platform has undergone drastic changes since then. I noticed that many features were new. I decided to test one of those features.
Exercism provided a feature to post comments to public solution submissions.
For example:
As you might have already noticed, the comment box supports Markdown.
The markdown input was converted to HTML and saved. The converted HTML code was used for rendering. As expected, only certain tags were allowed. Tags like script
, link
and meta
tags were not allowed. It was also noted that attributes that could trigger JavaScript execution such as onload
, onerror
were stripped off.
However, it was possible to insert div
tags and also add data
attributes to it. Thus, we have partial HTML Injection.
At this point, I felt stuck. However, I decided to take a look into the HTML source code. The platform was running React.js in the frontend.
#
Escalating to XSS
##
Weaponizing React.js
Upon looking at the client-side code, it was noted that, React.js creates React Components using a div
tag and data attributes - data-react-id
, data-react-data
and data-react-hydrate
.
data-react-id
attribute contained the React Component name.data-react-data
attribute stored values that would be used for initialization of the React Component.
For example,
With this, I was able to insert any React.js Component as a comment.
However, to increase the impact of the bug, a JavaScript execution will have to be shown. For doing this, a component that supports insertion of anchor tags to HTML was identified from Exercism Website GitHub Repository.
A React Component that displayed CLI token was used. The component displayed a link - “where do I use this?”. The href attribute of the link was controllable via info
key in the data-react-data
parameter.
We edit the info parameter in data-react-data
attribute of the component to javascript:alert(1)
, and create a comment using it.
|
|
Thus, when a user clicks on the - “where do I use this?” link, the alert
function gets executed.
Now, we have a reflected XSS. However, the cookies were HttpOnly, and could not be accessed with JavaScript.
#
Account Takedown
Since we have the ability to execute arbitary JavaScript code, we can make requests to any endpoint such as reset_account
or delete_account
.
|
|
#
Closing Words
A detailed report of the vulnerability was sent to the maintainers as soon as the vulnerability was found. The team responded and and a quick fix was made, however Exercism does not offer bug bounties.
Had a log of fun finding and escalating this bug.
Thanks for reading! Stay tuned!