{"id":2053,"date":"2026-09-22T11:09:16","date_gmt":"2026-09-22T15:09:16","guid":{"rendered":"https:\/\/www.peteonsoftware.com\/?p=2053"},"modified":"2026-09-22T11:13:00","modified_gmt":"2026-09-22T15:13:00","slug":"hack-the-box-walkthrough-flag-command","status":"publish","type":"post","link":"https:\/\/www.peteonsoftware.com\/index.php\/2026\/09\/22\/hack-the-box-walkthrough-flag-command\/","title":{"rendered":"Hack the Box Walkthrough: Flag Command"},"content":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/peteonsoftware.com\/images\/2026\/flagcommand_headerimage.jpg\" alt=\"AI-generated header image for this post of a green flag flying with terminal commands on it.\" title=\"AI-generated header image for this post of a green flag flying with terminal commands on it.\" style=\"float:left;margin:.5rem;\">Today, we&#8217;re going to tackle a Hack the Box Challenge on the offensive side called <a href=\"https:\/\/app.hackthebox.com\/challenges\/Flag%2520Command?tab=play_challenge\">Flag Command<\/a>.  The scenario that we&#8217;re given is <\/p>\n<pre>Embark on the \"Dimensional Escape Quest\" where you wake up in a mysterious forest maze that's not quite of this world. Navigate singing squirrels, mischievous nymphs, and grumpy wizards in a whimsical labyrinth that may lead to otherworldly surprises. Will you conquer the enchanted maze or find yourself lost in a different dimension of magical challenges? The journey unfolds in this mystical escape!<\/pre>\n<p>If you click to start the challenge, you&#8217;ll be given an IP:Port to connect to.  In my case, it is 154.57.164.75:32410, yours will almost certainly be different.  Going to that page, I see this:<br \/>\n<img decoding=\"async\" src=\"https:\/\/peteonsoftware.com\/images\/2026\/flagcommand_initialscreen.jpg\" alt=\"Our initial game screen\" title=\"Our initial game screen\"><\/p>\n<p>I follow along and type start and it gives me options like this:<\/p>\n<pre>\r\n>> start\r\nYOU WAKE UP IN A FOREST.\r\n\r\nYou have 4 options!\r\nHEAD NORTH\r\nHEAD SOUTH\r\nHEAD EAST\r\nHEAD WEST\r\n<\/pre>\n<p>I tried to play along still, but even when I typed an available option, it is apparently case sensitive.  So they are doing some sort of input validation.  Given that this is a text engagement, I was wondering if we&#8217;d get some command injection or something.  The first step to that would be to get past the validation.<\/p>\n<pre>\r\n>> head north\r\nYou do realise its not a park where you can just play around and move around pick from options how are hard it is for you????\r\n\r\n>> HEAD NORTH\r\nVenturing forth with the grace of a three-legged cat, you head North. Turns out, your sense of direction is as bad as your cooking - somehow, it actually works out this time. You stumble into a clearing, finding a small, cozy-looking tavern with \"The Sloshed Squirrel\" swinging on the signpost. Congratulations, you've avoided immediate death by boredom and possibly by beasties. For now...\r\n<\/pre>\n<p>I checked and it does send the commands to the server.  My next command was sent to http:\/\/154.57.164.75:32410\/api\/monitor as this request and then response<\/p>\n<pre>\r\n\/\/ Request\r\n{command: \"TURN BACK\"}\r\n\r\n\/\/ Response\r\n{ \"message\": \"You decide to turn back, but you realize you've lost your way. Night falls, and the forest becomes a dark, eerie place. You hear mysterious sounds closing in. Game over!\" }\r\n<\/pre>\n<p>I tried a few simple commands and couldn&#8217;t get anything going<\/p>\n<pre>\r\n>> id\r\n'id' command not found. For a list of commands, type 'help'\r\n\r\n>> help\r\nstart Start the game\r\nclear Clear the game screen\r\naudio Toggle audio on\/off\r\nrestart Restart the game\r\ninfo Show info about the game\r\n\r\n>> info\r\nYou abruptly find yourself lucid in the middle of a bizarre, alien forest.\r\nHow the hell did you end up here?\r\nEerie, indistinguishable sounds ripple through the gnarled trees, setting the hairs on your neck on edge.\r\nGlancing around, you spot a gangly, grinning figure lurking in the shadows, muttering 'Xclow3n' like some sort of deranged mantra, clearly waiting for you to pass out or something. Creepy much?\r\nHeads up! This forest isn't your grandmother's backyard.\r\nIt's packed with enough freaks and frights to make a horror movie blush. Time to find your way out.\r\nThe stakes? Oh, nothing big. Just your friends, plunged into an abyss of darkness and despair.\r\nPunch in 'start' to kick things off in this twisted adventure!\r\n\r\n>> start\r\nYOU WAKE UP IN A FOREST.\r\n\r\nYou have 4 options!\r\nHEAD NORTH\r\nHEAD SOUTH\r\nHEAD EAST\r\nHEAD WEST\r\n\r\n>> id\r\nYou do realise its not a park where you can just play around and move around pick from options how are hard it is for you????\r\n\r\n>> ;id\r\nYou do realise its not a park where you can just play around and move around pick from options how are hard it is for you????\r\n\r\n>> id; #\r\nYou do realise its not a park where you can just play around and move around pick from options how are hard it is for you????\r\n<\/pre>\n<p>Okay, let&#8217;s take a look at the source code of the web app.  I went into Developer Tools -> Sources and saw that there are 3 main javascript files at work here.<\/p>\n<pre>\r\n &lt;script src=\"\/static\/terminal\/js\/commands.js\" type=\"module\"&gt;&lt;\/script&gt;\r\n &lt;script src=\"\/static\/terminal\/js\/main.js\" type=\"module\"&gt;&lt;\/script&gt;\r\n &lt;script src=\"\/static\/terminal\/js\/game.js\" type=\"module\"&gt;&lt;\/script&gt;\r\n<\/pre>\n<p>Commands.js seems interesting.  What&#8217;s in there?<\/p>\n<pre>\r\nexport const START = 'YOU WAKE UP IN A FOREST.';\r\n\r\nexport const INITIAL_OPTIONS = [\r\n    '&lt;span class=\"command\"&gt;You have 4 options!&lt;\/span&gt;',\r\n    'HEAD NORTH',\r\n    'HEAD SOUTH',\r\n    'HEAD EAST',\r\n    'HEAD WEST'\r\n];\r\n\r\nexport const GAME_LOST =  'You &lt;span class=\"command error\"&gt;died&lt;\/span&gt; and couldn\\'t escape the forest. Press &lt;span class=\"command error\"&gt;restart&lt;\/span&gt; to try again.';\r\n\r\nexport const GAME_WON = 'You &lt;span class=\"command success\"&gt;escaped&lt;\/span&gt; the forest and &lt;span class=\"command success\"&gt;won&lt;\/span&gt; the game! Congratulations! Press &lt;span class=\"command success\"&gt;restart&lt;\/span&gt; to play again.';\r\n\r\nexport const INFO = [\r\n    \"You abruptly find yourself lucid in the middle of a bizarre, alien forest.\",\r\n    \"How the hell did you end up here?\",\r\n    \"Eerie, indistinguishable sounds ripple through the gnarled trees, setting the hairs on your neck on edge.\",\r\n    \"Glancing around, you spot a gangly, grinning figure lurking in the shadows, muttering 'Xclow3n' like some sort of deranged mantra, clearly waiting for you to pass out or something. Creepy much?\",\r\n    \"Heads up! This forest isn't your grandmother's backyard.\",\r\n    \"It's packed with enough freaks and frights to make a horror movie blush. Time to find your way out.\",\r\n    \"The stakes? Oh, nothing big. Just your friends, plunged into an abyss of darkness and despair.\",\r\n    \"Punch in 'start' to kick things off in this twisted adventure!\"\r\n];\r\n\r\nexport const CONTROLS = [\r\n    \"Use the &lt;span class='command'&gt;arrow&lt;\/span&gt; keys to traverse commands in the command history.\",\r\n    \"Use the &lt;span class='command'&gt;enter&lt;\/span&gt; key to submit a command.\",\r\n];\r\n\r\nexport const HELP = [\r\n    '&lt;span class=\"command help\"&gt;start&lt;\/span&gt; Start the game',\r\n    '&lt;span class=\"command help\"&gt;clear&lt;\/span&gt; Clear the game screen',\r\n    '&lt;span class=\"command help\"&gt;audio&lt;\/span&gt; Toggle audio on\/off',\r\n    '&lt;span class=\"command help\"&gt;restart&lt;\/span&gt; Restart the game',\r\n    '&lt;span class=\"command help\"&gt;info&lt;\/span&gt; Show info about the game',\r\n];\r\n<\/pre>\n<p>Okay, nothing exciting in there.  The game.js is extremely boring and nothing is in there.  That leaves us with main.js.  There is a lot in main.js, but here is a relevant part where it checks the command and sends it to the API and also where it gets your options.<\/p>\n<pre>\r\n\/\/ HTTP REQUESTS\r\n\/\/ ---------------------------------------\r\nasync function CheckMessage() {\r\n    fetchingResponse = true;\r\n    currentCommand = commandHistory[commandHistory.length - 1];\r\n\r\n    if (availableOptions[currentStep].includes(currentCommand) || availableOptions['secret'].includes(currentCommand)) {\r\n        await fetch('\/api\/monitor', {\r\n            method: 'POST',\r\n            headers: {\r\n                'Content-Type': 'application\/json'\r\n            },\r\n            body: JSON.stringify({ 'command': currentCommand })\r\n        })\r\n            .then((res) =&gt; res.json())\r\n            .then(async (data) =&gt; {\r\n                console.log(data)\r\n                await displayLineInTerminal({ text: data.message });\r\n\r\n                if(data.message.includes('Game over')) {\r\n                    playerLost();\r\n                    fetchingResponse = false;\r\n                    return;\r\n                }\r\n\r\n                if(data.message.includes('HTB{')) {\r\n                    playerWon();\r\n                    fetchingResponse = false;\r\n\r\n                    return;\r\n                }\r\n\r\n                if (currentCommand == 'HEAD NORTH') {\r\n                    currentStep = '2';\r\n                }\r\n                else if (currentCommand == 'FOLLOW A MYSTERIOUS PATH') {\r\n                    currentStep = '3'\r\n                }\r\n                else if (currentCommand == 'SET UP CAMP') {\r\n                    currentStep = '4'\r\n                }\r\n\r\n                let lineBreak = document.createElement(\"br\");\r\n\r\n\r\n                beforeDiv.parentNode.insertBefore(lineBreak, beforeDiv);\r\n                displayLineInTerminal({ text: '&lt;span class=\"command\"&gt;You have 4 options!&lt;\/span&gt;' })\r\n                displayLinesInTerminal({ lines: availableOptions[currentStep] })\r\n                fetchingResponse = false;\r\n            });\r\n\r\n\r\n    }\r\n    else {\r\n        displayLineInTerminal({ text: \"You do realise its not a park where you can just play around and move around pick from options how are hard it is for you????\" });\r\n        fetchingResponse = false;\r\n    }\r\n}\r\n\r\n\/\/ LATER IN THE FILE\r\nconst fetchOptions = () =&gt; {\r\n    fetch('\/api\/options')\r\n        .then((data) =&gt; data.json())\r\n        .then((res) =&gt; {\r\n            availableOptions = res.allPossibleCommands;\r\n\r\n        })\r\n        .catch(() =&gt; {\r\n            availableOptions = undefined;\r\n        })\r\n}\r\n<\/pre>\n<p>That \/api\/monitor gets POSTed to.  Attempting a GET returns a MethodNotAllowed error.  We will have to keep an eye on how it is interacted with.  Let&#8217;s call the other API that we found: \/api\/options.  That gives us this:<\/p>\n<pre>\r\n{\r\n  \"allPossibleCommands\": {\r\n    \"1\": [\r\n      \"HEAD NORTH\",\r\n      \"HEAD WEST\",\r\n      \"HEAD EAST\",\r\n      \"HEAD SOUTH\"\r\n    ],\r\n    \"2\": [\r\n      \"GO DEEPER INTO THE FOREST\",\r\n      \"FOLLOW A MYSTERIOUS PATH\",\r\n      \"CLIMB A TREE\",\r\n      \"TURN BACK\"\r\n    ],\r\n    \"3\": [\r\n      \"EXPLORE A CAVE\",\r\n      \"CROSS A RICKETY BRIDGE\",\r\n      \"FOLLOW A GLOWING BUTTERFLY\",\r\n      \"SET UP CAMP\"\r\n    ],\r\n    \"4\": [\r\n      \"ENTER A MAGICAL PORTAL\",\r\n      \"SWIM ACROSS A MYSTERIOUS LAKE\",\r\n      \"FOLLOW A SINGING SQUIRREL\",\r\n      \"BUILD A RAFT AND SAIL DOWNSTREAM\"\r\n    ],\r\n    \"secret\": [\r\n      \"Blip-blop, in a pickle with a hiccup! Shmiggity-shmack\"\r\n    ]\r\n  }\r\n}\r\n<\/pre>\n<p>Okay, what is the &#8220;secret&#8221; one?  Can I use that?  It turns out that I can&#8217;t use it at the beginning of the game.  I still have to enter &#8220;start&#8221;.  However, once the game is in play (which makes sense given all the other commands in this list are &#8220;in game&#8221; commands), I can use that secret to win the game.<\/p>\n<pre>\r\n>> Blip-blop, in a pickle with a hiccup! Shmiggity-shmack\r\n'blip-blop, in a pickle with a hiccup! shmiggity-shmack' command not found. For a list of commands, type 'help'\r\n\r\n>> start\r\nYOU WAKE UP IN A FOREST.\r\n\r\nYou have 4 options!\r\nHEAD NORTH\r\nHEAD SOUTH\r\nHEAD EAST\r\nHEAD WEST\r\n\r\n>> Blip-blop, in a pickle with a hiccup! Shmiggity-shmack\r\nHTB{D3v3l0p3r_t00l5_4r3_b35t__t0015_wh4t_d0_y0u_Th1nk??}\r\n\r\nYou escaped the forest and won the game! Congratulations! Press restart to play again.\r\n<\/pre>\n<p>That&#8217;s it.  Not &#8220;nothing&#8221;, but definitely &#8220;Very Easy&#8221; by Hack the Box standards, as advertised.  Any questions, let me know!<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/peteonsoftware.com\/images\/2026\/flagcommand_solved.jpg\" alt=\"Flag Command Solved\" title=\"Flag Command Solved\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today, we&#8217;re going to tackle a Hack the Box Challenge on the offensive side called Flag Command. The scenario that we&#8217;re given is Embark on the &#8220;Dimensional Escape Quest&#8221; where you wake up in a &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[153],"tags":[141,142],"class_list":["post-2053","post","type-post","status-publish","format-standard","hentry","category-capture-the-flag","tag-information-security","tag-infosec"],"_links":{"self":[{"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/posts\/2053","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/comments?post=2053"}],"version-history":[{"count":0,"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/posts\/2053\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/media?parent=2053"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/categories?post=2053"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/tags?post=2053"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}