> For the complete documentation index, see [llms.txt](https://skymas.gitbook.io/ctf/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://skymas.gitbook.io/ctf/buckeyectf-2021/canary.md).

# Canary

```python
import { Client, Intents } from 'discord.js'
import axios from 'axios'
import { wrapper } from 'axios-cookiejar-support'
import { Cookie, CookieJar, MemoryCookieStore } from 'tough-cookie'

const APP_HOSTNAME = process.env.APP_HOSTNAME || 'localhost'
const ADMIN_SECRET = process.env.ADMIN_SECRET || 'superSecretCookie'
const DISCORD_TOKEN = process.env.ADMIN_DISCORD_TOKEN!

const client = new Client({
  intents: [Intents.FLAGS.DIRECT_MESSAGES],
  partials: ['CHANNEL']
})

client.on('ready', () => {
  console.log(`Logged in as ${client.user!.tag}!`)
  client.user!.setPresence({
    activities: [{ name: 'DM me' }]
  })
})

client.on('messageCreate', async (message) => {
  if (message.author.bot) return

  if (
    !(
      message.content.startsWith('http://') ||
      message.content.startsWith('https://')
    )
  ) {
    message.channel.send("I'm just a bot. Maybe send me a URL and I'll open it")
    return
  }

  try {
    if (
      message.content.startsWith(`http://${APP_HOSTNAME}`) ||
      message.content.startsWith(`https://${APP_HOSTNAME}`)
    ) {
      message.channel.send("I see you're trying to steal my cookie :rage:")
      return
    }

    message.channel.sendTyping()

    const jar = new CookieJar(
      new MemoryCookieStore(),
      { allowSpecialUseDomain: true }
    )
    const cookie = new Cookie({
      key: 'auth',
      value: ADMIN_SECRET,
      domain: APP_HOSTNAME
    })

    jar.setCookieSync(cookie, `https://${APP_HOSTNAME}`)

    const client = wrapper(axios.create({ jar }))
    const response = await client.get(message.content, { maxRedirects: 0 })

    await message.channel.send(
      `I fetched your URL and got a ${response.status} status code`
    )
  } catch (e) {
    message.channel.send(`:x: \`${e}\``)
  }
})

client.login(DISCORD_TOKEN)
```

We need to bypass the URL filter:

```python
  try {
    if (
      message.content.startsWith(`http://${APP_HOSTNAME}`) ||
      message.content.startsWith(`https://${APP_HOSTNAME}`)
    ) {
      message.channel.send("I see you're trying to steal my cookie :rage:")
      return
    }
```

To get the admin cookie:

```python
   jar.setCookieSync(cookie, `https://${APP_HOSTNAME}`)

    const client = wrapper(axios.create({ jar }))
    const response = await client.get(message.content, { maxRedirects: 0 })

    await message.channel.send(
      `I fetched your URL and got a ${response.status} status code`
    )
  } catch (e) {
    message.channel.send(`:x: \`${e}\``)
```

And Enter to the /flag and take the flag.

```python
server.get(
  '/flag',
  async (request, reply) => {
    if (request.headers.cookie !== undefined) {
      const cookies = parseCookies(request.headers.cookie)
      if (cookies.auth === ADMIN_SECRET) {
        await reply.send(FLAG)
        return
      }
    }
```

![](/files/SSgL3qyj3dxSnqNIhKDC)

Create a Canary with Canary Bot.

![](/files/ohw9sQygwtmr4T9E8omq)

We can add user@ before the URL to simulate user:password to the request and bypass the filter.

![](/files/p4iqXNcb022TqVnlQg31)

We didn´t receive any warnings, so we can verifiy if the auth cookie was sent.

![](/files/vaOO3PiYBekotDGQVu8d)

![](/files/7yIvGy6If94NwTfz3r11)

> auth:d5692713322d63c8627ce39151943b82

After create the cookie, we can access to /flag!

![](/files/HQbivHsjIyAacVcsDdsS)

![](/files/TPP0hvSso1p12Biuv3pb)

{% hint style="success" %}
buckeye{d0ma1n\_m4tch1ng\_1s\_c4s5\_1ns3nsit1v3}
{% endhint %}
