Content injection via Incidents Timeline description
HackerOne report #1647446 by yvvdwf
on 2022-07-23, assigned to @nmalcolm:
Report | Attachments | How To Reproduce
Report
Content injection via Incidents Timeline description
Gitlab recently relased a feature allowing to add descriptions in the timeline of an incident. Its markdown description is filtered by TimelineEventPipeline
pipeline which includes Filter::ImageLinkFilter
filter. The latter is vulnerable to arbitrary content injection, thus leads to XSS.
This is the venerable code because link_replaces_image
is true in TimelineEventPipeline
.
link.children = if link_replaces_image
img['alt'] || img['data-src'] || img['src']
else
img.clone
end
Consequently, we can inject any HTML content by using alt
attribute whose value is not sanitized. Although the injected HTML content will be sanitized one more times using Dompurify when showing in Web browser, but there are few exceptions:
-
there exists
data-disable-with
attribute that is not sanitized and allows attackers to inject any HTML content, even<iframe>
,<script
tags, etc. Attackers may get full XSS in the Gitlab self-managed instances that are not protected by a restricted CSP as I reported -
when combining with other gadgets, the
class
attribute allows attackers may send arbitrary POST requests on behalf of victims. This leads to the possibility of admin user escalation or account takeover (when the account was created via a third party provider.
The following steps shows a demo of account takeover attack on Gitlab.com. The exploitation should be the same as in 1628009.
Step to reproduce
-
These steps will be done on Gitlab.com. You need to have a victim account to take over. This account is registered on Gitlab.com by logging in via a third provider, such as, a Google, Github, Twitter, Bitbucket, or Saleforce.
-
On an existing project (or create a new project), Goto
Monitor/Incidents
, then click onCreate incident
button to create a new incident. Then fill the form as you want. Then clickCreate issue
to create a new incident. You will be redirected to the result. -
Now click on
Timeline
link, then click onAdd new timeline event
and fill theTimeline text
using the following payload:
<img src=x alt="<a class='js-issuable-todo fixed-top fixed-bottom text-hide cursor-defaul' data-create-path=/-/profile/password?_method=put&user%5Bnew_password%5D=12345678&user%5Bpassword_confirmation%5D=12345678><style> .tab-content>.tab-pane{display: block !important}</style>">
-
Click on
Save
button. -
You may notice that:
-
Now logout Gitlab.com, then login with a third party provider to generate a new account on Gitlab.com
-
(If the attack project is not public, then we need to invite the victim to be a member of the project so that the victim can access to the incident page)
-
As the victim, visit the incident page and click anywhere (the topmost transparent layer)
-
Refresh the page, you should now be logged out from Gitlab.com as your password was changed
-
Here is an example, that is in a private project: https://gitlab.com/yvvdwf/xss/-/issues/incident/11
Impact
HTML injection allows attackers to (1) get full XSS in the Gitlab self-managed instances that are not protected by a restricted CSP, or (2) to send arbitrary POST request on behalf of victims that can lead to permission escalation or even account takeover, etc.
Impact
HTML injection allows attackers to (1) get full XSS in the Gitlab self-managed instances that are not protected by a restricted CSP, or (2) to send arbitrary POST request on behalf of victims that can lead to permission escalation or even account takeover, etc.
Attachments
Warning: Attachments received through HackerOne, please exercise caution!
How To Reproduce
Please add reproducibility information to this section: