Skip to content

Latest commit

 

History

History
67 lines (44 loc) · 1.92 KB

File metadata and controls

67 lines (44 loc) · 1.92 KB

Nebula level09

https://exploit-exercises.com/nebula/level09/

Goal

Call getflag from the level09 account.

Situation

There’s a C setuid wrapper for some vulnerable PHP code…

PHP Code

flag09.php

<?php

function spam($email)
{
  $email = preg_replace("/\./", " dot ", $email);
  $email = preg_replace("/@/", " AT ", $email);
  
  return $email;
}

function markup($filename, $use_me)
{
  $contents = file_get_contents($filename);

  $contents = preg_replace("/(\[email (.*)\])/e", "spam(\"\\2\")", $contents);
  $contents = preg_replace("/\[/", "<", $contents);
  $contents = preg_replace("/\]/", ">", $contents);

  return $contents;
}

$output = markup($argv[1], $argv[2]);

print $output;

?>

Exploit

From Wikipedia:

Looking up the preg_replace function shows us that it is meant to replace the portion of the string matched by the regex in the first input with the second input. It also allows backreferences, so things matched inside () in the regex can be essentially passed to the second string as \\n or $n, where \\n will contain the string matched by the n-th parenthesis. So what this does is matches [email blahblahblah] and passes the blahblahblah to the spam function. (Note: the \e at the end of the preg_replace string tells PHP to evaluate the result of the second string, so rather than this becoming "spam(blahblahblah)", it would evaluate spam of blahblahblah.

That /e flag will evaluate anything inside the second string. This means that if we can put in code to call getflag in there, PHP will evaluate it and call getflag. So we need to put something like system(getflag) in there. To do this, we can just have the text in our email block look like [email {${system(getflag)}}] (Note: got the wacky PHP syntax from other solutions). When we try that, we get:

PHP Notice:  Undefined variable: You have successfully executed getflag on a target account

We did it!