RITSEC 2023 - Web / Echoes

Posted by : at

Category : ritsec-ctf-2023

The Challenge

You are led to a website called the “RITSEC Echo Simulator”, where it encourages you to test out some words in an input box. There’s a single button to test the word.


I first entered some gibberish just to see how the application behaved, and a new page loaded with the following:

You entered: asdf

This word echoes (echoes) (echoes)...see?

Because it’s showing the data, this led me to think it’s either an XSS or command injection. There were no obvious signs that a bot or someone else is monitoring the site, so I leaned into command injection.


echo is a command commonly used in linux. For example: echo something will print something as the ouput. You can use subshells (as is common in a lot of command injection vectors) to echo the result of another command. As an example, you could run: echo "My Username is $(whoami)":

echo "My Username is $(whoami)"


I tried adding just id or whoami to see if it was a direct injection, but that didn’t work out. It was just displaying the text. I moved on to using a subshell, as shown above with the username example. Let’s try $(id) as an input:

This word does not echo

hmmmmmmm, ok. There may be some filtering, or I’m not understanding exactly how this is called. This is a different response though, so it’s progress nonetheless!

Echo Subshell

I mean, the name of the challenge is “Echoes”, so let’s try to do the full echo command: echo $(id):

remote code execution displaying the user id of the process

Boom! We got a remote code execution. Now we just need to find that pesky flag. Doing a directory listing, we leak the flag location (flag.txt) by entering echo $(ls -la).

What was in the PHP Code?

Fortunately, we can read out arbitrary files using our RCE, and doing the ls -la, we can see there’s check.php in the current directory. Let’s take a look at that and figure out why our exploit worked this way. …but wait, echo $(cat check.php) says that this word doesn’t echo. Is there something in place to prevent this? This is where I stopped looking because I had the flag. Future Leo, however, went back and checked the source code because I was missing something here. Let’s take a look at the relevant code:

    <p class="php">This word
        if (strlen($_POST["word"]) % 2 == 0) {
          echo nl2br("echoes (echoes) (echoes)...see?\r\n");
	  $cmd = "echo ".$_POST["word"];
	  $outout = array();
          exec($cmd, $outout);
          echo $_POST["word"];
	  echo "<br />";
	  echo $_POST["word"]; 
	  echo "<br />";
          foreach($outout as $line) {
	    echo $line;
	    echo "<br />";
        else echo "does not echo... weird";

So uhhhhh, it was an even/odd number of character thing? This is WAY more simple than I had initially thought, and I over-complicated things a good bit. My above assumptions only worked due to sheer dumb luck regarding the number of characters when running my attempted exploits.


I liked this challenge because of the “easy” remote code execution, however, I was really surprised to see how simple the logic actually was. I was assuming there was some filtering in place to prevent code exfiltration or something similar, but that wasn’t the case! This really brings to light the benefit of having source code available for gray-box testing. If this were for a pen-test, I would have written up steps to reproduce that were both inaccurate and overly complicated.

About Leo Reading
Leo Reading

Leo is a recovering developer with an interest in cyber security - opinions may be misinformed.

About Leo

Leo is a recovering developer with an interest in cyber security - opinions may be misinformed.

Useful Links