Last week, I found a content spoofing bug in Medium’s jobs site, which can lead to stroed XSS.

Introduction

I was not looking for bugs there neither a job, I just wanted to see what technologies are being used in Medium, so I visted this link:

https://jobs.medium.com/show.html?jobId=8b2157c9-f755-40f7-b2c7-e81c49a51664

When I saw the file extension I knew they were using static pages with Javascript to show the description, and the apply link.

I like to look into Javascript files to learn new techniques and check the DOM XSS that I can find.

After geting a quick look into the mechinsim of show.html file, and how it brings the job details, I found out the file that responsable for bring the job details, it’s called jobOpening.min.js .

What is the vulnreability down here ?

function(e,t,n){
"use strict";function r(e){return e&&e.__esModule?e:{default:e}}var i=n(120),o=r(i),s=n(131);
(0,o.default)((0,s.urlParam)("jobId"))},130:function(e,t){"use strict";
Object.defineProperty(t,"__esModule",{value:!0});
t.openingUrl=function(e){return"https://api.lever.co/v0/postings/medium/"+e},t.applyUrl=function(e){return"https://api.lever.co/v0/postings/medium/"+e+"?key=hfhW4CLqdCzAsQdyfQL5"}},131:function(e,t){"use strict";
function n(e){var t=new RegExp("[?&]"+e+"=([^&#]*)").exec(window.location.href);return t[1]||0}Object.defineProperty(t,"__esModule",{value:!0}),t.urlParam=n}});

You saw it ? No. It is okay if you did not get it, now I am going to expalin it in steps:

  1. Javascript gets the jobId parameter from URL.
  2. It passes the value of the parameter to a functiuon as e.
  3. The function create a URL to Lever API.
  4. The code writes the JSON response to the page.

What is Lever ?

Lever is an US-based software company headquartered in San Francisco, California that provides an applicant tracking system for hiring. It was founded in 2012 by Sarah Nahm, Nate Smith, and Randal Truong.

Their API has a json endpoint that contains the job details.

The bug

Since the page take the ID of the job from the URL and send it to the API we can change the path of the request.

The ID of real Medium’s job:

vuln

This page send a reqest to Lever:

https://api.lever.co/v0/postings/medium/8b2157c9-f755-40f7-b2c7-e81c49a51664

I google this endpoint, and I got some useful results like this one:

https://api.lever.co/v0/postings/hightechhigh/f427aa0d-8260-48e2-b93b-cad30d049729

The key : I just changed the path of request using double dot(..) and backslash(/) and added the /hightechhigh/f427aa0d-8260-48e2-b93b-cad30d049729.

PoC

Here is the PoC:

https://jobs.medium.com/show.html?jobId=../hightechhigh/f427aa0d-8260-48e2-b93b-cad30d049729 


vuln


Evil hacker scenario

An evil hacker can register an account at Lever. e.g :

https://api.lever.co/v0/postings/hackerorg/XXXXXXXX-XXXXX-XXXX-XXXX-XXXXXXXXXXX

After that he/she creates the following URL:

https://jobs.medium.com/show.html?jobId=../hackerorg/XXXXXXXX-XXXXX-XXXX-XXXX-XXXXXXXXXXX 

The page will look like this:


vuln


It’s even can lead to stored XSS. Let’s use the alert(document.domain)

vuln


This bug is patched now and I will get a new Medium shirt :)

Thanks for reading.