Page 1 of 1

I'm in a desperate situation. My site is hacked!

Posted: Mon Jul 23, 2007 4:06 am
by legend986
I wonder what happened, but my site was hacked once again by someone who calls himself Undead. The moment it loads, it redirects to this site:

Code: Select all

http://nt_undead.ifastnet.com
I've viewed the source files. It keeps inserting a Meta refresh tag in every file that is loading up...

It is inserting this everywhere in my pages... Donno from where it is inserting it...When I goto my FTP account and view the source files, there's nothing there but when loading, its putting this up into every page and then redirecting me:

Code: Select all

<META HTTP-EQUIV="Refresh" CONTENT="1;URL=http://nt_undead.ifastnet.com">

Any advice please?

Posted: Mon Jul 23, 2007 4:08 am
by Jenk
Replace the main index page with a replacement until you have 'fixed' it. A plain, static page with nothing more than "Sorry, back soon" type message.

Inform your host you have been "hacked" and ask them to check the servers processes.

Posted: Mon Jul 23, 2007 4:11 am
by Chris Corbyn
Somebody must have modified your source otherwise that won't work. Eiher that, or they've managed to get your host the virtualhost some arbitrary files using your account name.

Are you sure this isn't a redirect from a .htaccess file?

Shared hosting is a drag... I never had a good experience and repeatedly had files vandalised with racist/religious junk. What web host are you with? I switched to Virtual Linux Hosting a couple of years ago now and won't ever change back to shared hosting.

Posted: Mon Jul 23, 2007 4:21 am
by legend986
Thank you so much... I'm using a host called dx-t.net. I've asked them for help. One of them asked me to change my password and reupload my files but I see that there's nothing wrong in my files at all. The META HTTP-EQUIV is being inserted in every page that I'm loading and yes, I've uploaded a static page that redirects to another "Under Construction..." page and fortunately its working...

Just for information, I'm using Joomla and Invision. Here's my .htaccess:

Code: Select all

##
# @version $Id: htaccess.txt 4756 2006-08-25 16:07:11Z stingrey $
# @package Joomla
# @copyright Copyright (C) 2005 Open Source Matters. All rights reserved.
# @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
# Joomla! is Free Software
##


#####################################################
#  READ THIS COMPLETELY IF YOU CHOOSE TO USE THIS FILE
#
# The line just below this section: 'Options FollowSymLinks' may cause problems
# with some server configurations.  It is required for use of mod_rewrite, but may already
# be set by your server administrator in a way that dissallows changing it in
# your .htaccess file.  If using it causes your server to error out, comment it out (add # to 
# beginning of line), reload your site in your browser and test your sef url's.  If they work,
# it has been set by your server administrator and you do not need it set here. 
#
# Only use one of the two SEF sections that follow.  Lines that can be uncommented
# (and thus used) have only one #.  Lines with two #'s should not be uncommented
# In the section that you don't use, all lines should start with #
#
# For Standard SEF, use the standard SEF section.  You can comment out
# all of the RewriteCond lines and reduce your server's load if you
# don't have directories in your root named 'component' or 'content'
#
# If you are using a 3rd Party SEF or the Core SEF solution
# uncomment all of the lines in the '3rd Party or Core SEF' section
#
#####################################################

#####  SOLVING PROBLEMS WITH COMPONENT URL's that don't work #####
# SPECIAL NOTE FOR SMF USERS WHEN SMF IS INTEGRATED AND BRIDGED
# OR ANY SITUATION WHERE A COMPONENT's URL's AREN't WORKING
#
# In both the 'Standard SEF', and '3rd Party or Core SEF' sections the line:
# RewriteCond %{REQUEST_URI} ^(/component/option,com) [NC,OR] ##optional - see notes##
# May need to be uncommented.  If you are running your Joomla/Mambo from
# a subdirectory the name of the subdirectory will need to be inserted into this
# line.  For example, if your Joomla/Mambo is in a subdirectory called '/test/',
# change this:
# RewriteCond %{REQUEST_URI} ^(/component/option,com) [NC,OR] ##optional - see notes##
# to this:
# RewriteCond %{REQUEST_URI} ^(/test/component/option,com) [NC,OR] ##optional - see notes##
#
#####################################################


##  Can be commented out if causes errors, see notes above.
Options FollowSymLinks

#
#  mod_rewrite in use

RewriteEngine On


#  Uncomment following line if your webserver's URL
#  is not directly related to physical file paths.
#  Update Your Joomla/MamboDirectory (just / for root)

# RewriteBase /


########## Begin - Joomla! core SEF Section
############# Use this section if using ONLY Joomla! core SEF
## ALL (RewriteCond) lines in this section are only required if you actually
## have directories named 'content' or 'component' on your server
## If you do not have directories with these names, comment them out.
#
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#RewriteCond %{REQUEST_URI} ^(/component/option,com) [NC,OR] 		##optional - see notes##
RewriteCond %{REQUEST_URI} (/|\.htm|\.php|\.html|/[^.]*)$  [NC]
RewriteRule ^(content/|component/) index.php
#
########## End - Joomla! core SEF Section



########## Begin - 3rd Party SEF Section
############# Use this section if you are using a 3rd party (Non Joomla! core) SEF extension - e.g. OpenSEF, 404_SEF, 404SEFx, SEF Advance, etc
#
#RewriteCond %{REQUEST_URI} ^(/component/option,com) [NC,OR] 		##optional - see notes##
#RewriteCond %{REQUEST_URI} (/|\.htm|\.php|\.html|/[^.]*)$  [NC]
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule (.*) index.php
#
########## End - 3rd Party SEF Section



########## Begin - Rewrite rules to block out some common exploits
## If you experience problems on your site block out the operations listed below
## This attempts to block the most common type of exploit `attempts` to Joomla! 
#                              
# Block out any script trying to set a mosConfig value through the URL
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR]
# Block out any script trying to base64_encode crap to send via URL
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [OR]
# Block out any script that includes a <script> tag in URL
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
# Block out any script trying to set a PHP GLOBALS variable via URL
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
# Block out any script trying to modify a _REQUEST variable via URL
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
# Send all blocked request to homepage with 403 Forbidden error!
RewriteRule ^(.*)$ index.php [F,L]
# 
########## End - Rewrite rules to block out some common exploits
I don't see anything suspicious unless I really missed out something...

And the main index.php is from the Joomla package itself...

Code: Select all

<?php
/**
* @version $Id: index.php 6022 2006-12-18 22:30:07Z friesengeist $
* @package Joomla
* @copyright Copyright (C) 2005 Open Source Matters. All rights reserved.
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php
* Joomla! is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* See COPYRIGHT.php for copyright notices and details.
*/

// Set flag that this is a parent file
define( '_VALID_MOS', 1 );

// checks for configuration file, if none found loads installation page
if (!file_exists( 'configuration.php' ) || filesize( 'configuration.php' ) < 10) {
	$self = rtrim( dirname( $_SERVER['PHP_SELF'] ), '/\\' ) . '/';
	header("Location: http://" . $_SERVER['HTTP_HOST'] . $self . "installation/index.php" );
	exit();
}

require( 'globals.php' );
require_once( 'configuration.php' );

// SSL check - $http_host returns <live site url>:<port number if it is 443>
$http_host = explode(':', $_SERVER['HTTP_HOST'] );
if( (!empty( $_SERVER['HTTPS'] ) && strtolower( $_SERVER['HTTPS'] ) != 'off' || isset( $http_host[1] ) && $http_host[1] == 443) && substr( $mosConfig_live_site, 0, 8 ) != 'https://' ) {
	$mosConfig_live_site = 'https://'.substr( $mosConfig_live_site, 7 );
}

require_once( 'includes/joomla.php' );

//Installation sub folder check, removed for work with SVN
if (file_exists( 'installation/index.php' ) && $_VERSION->SVN == 0) {
	define( '_INSTALL_CHECK', 1 );
	include ( $mosConfig_absolute_path .'/offline.php');
	exit();
}

// displays offline/maintanance page or bar
if ($mosConfig_offline == 1) {
	require( $mosConfig_absolute_path .'/offline.php' );
}

// load system bot group
$_MAMBOTS->loadBotGroup( 'system' );

// trigger the onStart events
$_MAMBOTS->trigger( 'onStart' );

if (file_exists( $mosConfig_absolute_path .'/components/com_sef/sef.php' )) {
	require_once( $mosConfig_absolute_path .'/components/com_sef/sef.php' );
} else {
	require_once( $mosConfig_absolute_path .'/includes/sef.php' );
}
require_once( $mosConfig_absolute_path .'/includes/frontend.php' );

// retrieve some expected url (or form) arguments
$option = strval( strtolower( mosGetParam( $_REQUEST, 'option' ) ) );
$Itemid = intval( mosGetParam( $_REQUEST, 'Itemid', null ) );

if ($option == '') {
	if ($Itemid) {
		$query = "SELECT id, link"
		. "\n FROM #__menu"
		. "\n WHERE menutype = 'mainmenu'"
		. "\n AND id = " . (int) $Itemid
		. "\n AND published = 1"
		;
		$database->setQuery( $query );
	} else {
		$query = "SELECT id, link"
		. "\n FROM #__menu"
		. "\n WHERE menutype = 'mainmenu'"
		. "\n AND published = 1"
		. "\n ORDER BY parent, ordering"
		;
		$database->setQuery( $query, 0, 1 );
	}
	$menu = new mosMenu( $database );
	if ($database->loadObject( $menu )) {
		$Itemid = $menu->id;
	}
	$link = $menu->link;
	if (($pos = strpos( $link, '?' )) !== false) {
		$link = substr( $link, $pos+1 ). '&Itemid='.$Itemid;
	}
	parse_str( $link, $temp );
	/** this is a patch, need to rework when globals are handled better */
	foreach ($temp as $k=>$v) {
		$GLOBALS[$k] = $v;
		$_REQUEST[$k] = $v;
		if ($k == 'option') {
			$option = $v;
		}
	}
}
if ( !$Itemid ) {
// when no Itemid give a default value
	$Itemid = 99999999;
}

// mainframe is an API workhorse, lots of 'core' interaction routines
$mainframe = new mosMainFrame( $database, $option, '.' );
$mainframe->initSession();

// trigger the onAfterStart events
$_MAMBOTS->trigger( 'onAfterStart' );

// checking if we can find the Itemid thru the content
if ( $option == 'com_content' && $Itemid === 0 ) {
	$id 	= intval( mosGetParam( $_REQUEST, 'id', 0 ) );
	$Itemid = $mainframe->getItemid( $id );
}

/** do we have a valid Itemid yet?? */
if ( $Itemid === 0 ) {
	/** Nope, just use the homepage then. */
	$query = "SELECT id"
	. "\n FROM #__menu"
	. "\n WHERE menutype = 'mainmenu'"
	. "\n AND published = 1"
	. "\n ORDER BY parent, ordering"
	;
	$database->setQuery( $query, 0, 1 );
	$Itemid = $database->loadResult();
}

// patch to lessen the impact on templates
if ($option == 'search') {
	$option = 'com_search';
}

// loads english language file by default
if ($mosConfig_lang=='') {
	$mosConfig_lang = 'english';
}
include_once( $mosConfig_absolute_path .'/language/' . $mosConfig_lang . '.php' );

// frontend login & logout controls
$return 	= strval( mosGetParam( $_REQUEST, 'return', NULL ) );
$message 	= intval( mosGetParam( $_POST, 'message', 0 ) );
if ($option == 'login') {
	$mainframe->login();

	// JS Popup message
	if ( $message ) {
		?>
		<script language="javascript" type="text/javascript">
		<!--//
		alert( "<?php echo addslashes( _LOGIN_SUCCESS ); ?>" );
		//-->
		</script>
		<?php
	}

	if ( $return && !( strpos( $return, 'com_registration' ) || strpos( $return, 'com_login' ) ) ) {
	// checks for the presence of a return url
	// and ensures that this url is not the registration or login pages
		// If a sessioncookie exists, redirect to the given page. Otherwise, take an extra round for a cookiecheck
		if (isset( $_COOKIE[mosMainFrame::sessionCookieName()] )) {
			mosRedirect( $return );
		} else {
			mosRedirect( $mosConfig_live_site .'/index.php?option=cookiecheck&return=' . urlencode( $return ) );
		}
	} else {
		// If a sessioncookie exists, redirect to the start page. Otherwise, take an extra round for a cookiecheck
		if (isset( $_COOKIE[mosMainFrame::sessionCookieName()] )) {
			mosRedirect( $mosConfig_live_site .'/index.php' );
		} else {
			mosRedirect( $mosConfig_live_site .'/index.php?option=cookiecheck&return=' . urlencode( $mosConfig_live_site .'/index.php' ) );
		}
	}

} else if ($option == 'logout') {
	$mainframe->logout();

	// JS Popup message
	if ( $message ) {
		?>
		<script language="javascript" type="text/javascript">
		<!--//
		alert( "<?php echo addslashes( _LOGOUT_SUCCESS ); ?>" );
		//-->
		</script>
		<?php
	}

	if ( $return && !( strpos( $return, 'com_registration' ) || strpos( $return, 'com_login' ) ) ) {
	// checks for the presence of a return url
	// and ensures that this url is not the registration or logout pages
		mosRedirect( $return );
	} else {
		mosRedirect( $mosConfig_live_site.'/index.php' );
	}
} else if ($option == 'cookiecheck') {
	// No cookie was set upon login. If it is set now, redirect to the given page. Otherwise, show error message.
	if (isset( $_COOKIE[mosMainFrame::sessionCookieName()] )) {
		mosRedirect( $return );
	} else {
		mosErrorAlert( _ALERT_ENABLED );
	}
}

/** get the information about the current user from the sessions table */
$my = $mainframe->getUser();

// detect first visit
$mainframe->detect();

// set for overlib check
$mainframe->set( 'loadOverlib', false );

$gid = intval( $my->gid );

// gets template for page
$cur_template = $mainframe->getTemplate();
/** temp fix - this feature is currently disabled */

/** @global A places to store information from processing of the component */
$_MOS_OPTION = array();

// precapture the output of the component
require_once( $mosConfig_absolute_path . '/editor/editor.php' );

ob_start();

if ($path = $mainframe->getPath( 'front' )) {
	$task 	= strval( mosGetParam( $_REQUEST, 'task', '' ) );
	$ret 	= mosMenuCheck( $Itemid, $option, $task, $gid );

	if ($ret) {
		require_once( $path );
	} else {
		mosNotAuth();
	}
} else {
	header( 'HTTP/1.0 404 Not Found' );
	echo _NOT_EXIST;
}

$_MOS_OPTION['buffer'] = ob_get_contents();

ob_end_clean();

initGzip();

header( 'Expires: Mon, 26 Jul 1997 05:00:00 GMT' );
header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
header( 'Cache-Control: post-check=0, pre-check=0', false );
header( 'Pragma: no-cache' );

// display the offline alert if an admin is logged in
if (defined( '_ADMIN_OFFLINE' )) {
	include( $mosConfig_absolute_path .'/offlinebar.php' );
}

// loads template file
if ( !file_exists( $mosConfig_absolute_path .'/templates/'. $cur_template .'/index.php' ) ) {
	echo _TEMPLATE_WARN . $cur_template;
} else {
	require_once( $mosConfig_absolute_path .'/templates/'. $cur_template .'/index.php' );
	echo '<!-- '. time() .' -->';
}

// displays queries performed for page
if ($mosConfig_debug) {
	echo $database->_ticker . ' queries executed';
	echo '<pre>';
 	foreach ($database->_log as $k=>$sql) {
 		echo $k+1 . "\n" . $sql . '<hr />';
	}
	echo '</pre>';
}

doGzip();
?>
I'm clueless as to what to do... :( I know being panic only worsens things but I really don't know what to do at this stage... I've mailed the host but I've not got a reply.. Is there anything that can solve the problem?

Posted: Mon Jul 23, 2007 4:27 am
by legend986
And this is how a page that has been loaded looks like:

Code: Select all

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Hacked By UndeAd http://www.turkeyhack.org</title>
<!-- SOME CONTENT REMOVED TO REDUCE THE SIZE OF THE POST -->
	

//--><!]]>
</script>

<ul><li class='active'><a href="http://www.somewebsite.com/component/option,com_bbpixelfnews/Itemid,26/">Main</a></li>

<li><a href="http://www.somewebsite.com/forum"><META HTTP-EQUIV="Refresh" CONTENT="0;URL=http://nt_undead.ifastnet.com"></a></li>
See the last line? Its inserting such tags everywhere atleast once in all the files that are loading... I don't know where to correct that...

Posted: Mon Jul 23, 2007 4:38 am
by Chris Corbyn
It looks to me as if that content comes from the database. Could your site be susceptible to XSS attacks (injection of HTML into a page)?

Posted: Mon Jul 23, 2007 5:03 am
by legend986
Ok so its a database attack? I've no clue about XSS attacks.. For now, is there something I could in the database? Like searching for a problem or something?

Posted: Mon Jul 23, 2007 5:26 am
by volka
Which versions of Joomla and IP board do you use?
What does

Code: Select all

<?php
echo 'version: ', phpversion(), "<br />\n";
echo 'sapi: ', php_sapi_name(), "<br />\n";
echo 'register_globals: ', ini_get('register_globals') ? 'on':'off';
?>
print when run on your site's webserver?

Posted: Mon Jul 23, 2007 5:26 am
by legend986
Ok.. I've performed a search in the database and you are right! I've found a few entries with that name. Do I delete them?

Posted: Mon Jul 23, 2007 5:30 am
by legend986
volka wrote:Which versions of Joomla and IP board do you use?
What does

Code: Select all

<?php
echo 'version: ', phpversion(), "<br />\n";
echo 'sapi: ', php_sapi_name(), "<br />\n";
echo 'register_globals: ', ini_get('register_globals') ? 'on':'off';
?>
print when run on your site's webserver?
I've asked the IPB people, they say there's nothing wrong with their script and that I'm running the up to date version... I'll show them the problem in action when this is solved... The script displays the following:

Code: Select all

version: 4.4.7
sapi: apache
register_globals: off

Posted: Mon Jul 23, 2007 6:12 am
by legend986
d11wtq wrote:It looks to me as if that content comes from the database. Could your site be susceptible to XSS attacks (injection of HTML into a page)?
:worship: You were right! Something related to that I guess... I've opened up the database and deleted everything that had that hacker's words and now the site is working. Could you please enlighten me as to how this was carried out and how I can prevent it?

Posted: Mon Jul 23, 2007 6:48 am
by superdezign
Filtering EVERYTHING that you allow your users to enter into your webpage. NEVER trust a user.

htmlspecialchars() may be of interest.

Posted: Mon Jul 23, 2007 7:22 am
by phpdevuk
I had similar problems once running an old version of phpBB, they put code into the title of a topic I think it was which rewrote most of the page to display some stuff, quite annoying, good reason to get regular database backups.

Posted: Mon Jul 23, 2007 8:07 am
by legend986
I will definitely follow the advices :) Thank you...