Persistent XSS in milestones data-milestone-id attribute when payload is using HTML-entities
The milestone_select.js
located in app/assets/javascripts/milestone_select.js
suffers from a stored XSS issue in the renderRow
-function. The issue is that the data-milestone-id
-attribute is containing the name of the milestone, but is not sanitized properly:
The issue is currently on line #98 (closed): https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/javascripts/milestone_select.js#L98
renderRow: milestone => `
<li data-milestone-id="${milestone.name}">
<a href='#' class='dropdown-menu-milestone-link'>
${_.escape(milestone.title)}
</a>
</li>
`,
As you see, the title is escaped but the name is not, but they are the same really:
Now, this is not possible to do with normal angle-brackets, however, due to the passing of data, using HTML-entities for the payload will trigger this issue when creating a Milestone with the following name:
'"><img src=x onerror=alert(document.domain)>
This seems to be some form of issue with it server side, as the milestones.json
actually contains escaped real angle-bracket characters:
"name":"'\"\u003e\u003cimg src=x onerror=alert(document.domain)\u003e"
PoC
- Create a new milestone at:
/project-name/milestones
- Name the milestone:
'"><img src=x onerror=alert(document.domain)> ``` ![Screen_Shot_2018-01-08_at_20.38.36](/uploads/02c2e340e48d5a954b6966cce471d8e7/Screen_Shot_2018-01-08_at_20.38.36.png)
- Save, now go to
/project-name/issues
, pressNew issue
- Click on the Milestone-selector: the javascript will trigger:
This happens on every place where the milestone-selector exists, it's all over the app.
Impact
The stored XSS is triggering for anyone, also triggering on gitlab.com
, and it can trigger on public repos. You could easily build a PoC that would modify the email address of the current user stealing their CSRF-token as soon as the script triggers.