Cross-site scripting via hardcoded front-end watched expression.
Medium
Q
Quantopian
Submitted None
Actions:
Reported by
irisrumtub
Vulnerability Details
Technical details and impact analysis
Hello, favorite security team. This is so far most interesting XSS i've found on your website. And also this is 10th bug i report you, so im gonna celebrate.
**Summary:** Via hardcoded front-end code in algo debugger one is able to execute XSS on algorithm collaborator. One is able to use python to change the output of that hardcoded expression, which is unsanitized HTML, where cross-site scripting fires. Additionally, one can store the malicious code in algorithm and share it, so XSS will fire on anyone who will clone and run the algorithm.
**Description:**
This is an interesting one. First, i noticed that when one validates the code **with debugger**, a certain web socket request is sent
```json
{"e":"set_watch","p":["get_datetime().strftime(\"%Y-%m-%d %H:%M:%S\")#__QUANTOPIAN__"]}
```
By lurking deeper, I've determined that this request sets watched expression, the one that is in charge of current date and time in the debugger:
{F569596}
To check the assumption that this place might contain unsanitized html, i've intercepted incoming web socket response with the result of aforementioned expression (datetime) and added an XSS payload to it, and it worked.
The fact that it is set as a user-defined watched expression got me thinking. We can remove it manually, and calendar will disappear. And we can set it again, and it will reappear, which was interesting. I've tried several different expressions with #__QUANTOPIAN at the end, but nothing appeared where calendar is supposed to be. I wrote to JD on Quantopian's slack, who was kind enough to tell me:
>exact string (including ```get_datetime()```, not just the trailing ```__QUANTOPIAN__``` part) is used as a command from our frontend javascript code to request the current algorithm execution time between each other command that the user sends. However, that exact string is stored as a constant in our frontend code, so only the response that matches that exact value will be shown in the date area.
...what basically means that any output that is generated by this exact expression goes directly into unsanitized HTML.
So we force this expression to output what we want by adding this class :)
----------------
```python
class get_datetime():
def __init__(self):
self.img = '<img src=x'+' one'+'rror=alert(1)>'
def strftime(self, x=None):
return self.img
```
--------------
And next time debugger is launched, expression ```get_datetime().strftime("%Y-%m-%d %H:%M:%S")#__QUANTOPIAN__``` outputs ```<img src=x onerror=alert(1)>```, executing javascript.
I'd like to additionally say that there are two vectors of the attack.
* attack on the collaborator. This is as sneaky, as #615672, because it requires no interaction with the victim. We can either wait for him to be away from keyboard and re-validate our algorithm code with malicious class. Or we can start the backtest even without the code visible, and just intercept outgoing POST request, and since it sends the whole code, we can add our malicious class there. It will not appear visible at any point, but xss will fire.
* attack on anyone who will clone malicious algorithm and run it in his own ide with debugger. First we can obfuscate the code (especially if algo is large, this becomes easier), and share it.
## Steps To Reproduce:
(Add details for how we can reproduce the issue)
1. add xss class to algo code
2. set breakpoint in code so debugger will open, start
3. execute it on collaborator, or obfuscate class and share it.
## Supporting Material/References:
{F569615}
## Test account information
[email protected]
[email protected]
## Impact
Execute our own javascript with all the consequences, steal algorithms (because xss happens on quantopian.com).
Report Details
Additional information and metadata
State
Closed
Substate
Resolved
Bounty
$1225.00
Submitted
Weakness
Cross-site Scripting (XSS) - Generic