Results 1 to 6 of 6

Thread: Help with hacked website

  1. #1
    User
    Join Date
    06-19-09.
    Posts
    106

    Default Help with hacked website

    Hello, I've got a Tl installation which was hacked a little while ago, with the result of visitors being re-directed to a Russian website. The hosting company closed the vulnerability and I've cleaned up the .htaccess and the cron.php files.

    I thought that was the end of it. But I've just realised that certain URLs which don't belong to the public website still get redirected to the Russian URL (although this has a 'Server not found' error).

    e.g.
    fightforsight.org.uk/system
    fightforsight.org.uk/tl_files
    fightforsight.org.uk/plugins
    -- it seems to be pretty much any folder

    I don't know what causes the re-direct. I've tried looking through a few files but cannot see anything. Any ideas?

    I've downloaded all files and run an Avast virus check, but that came back clean.

    Many thanks.

  2. #2
    User
    Join Date
    06-19-09.
    Location
    Elbl?g, Poland
    Posts
    152

    Default Re: Help with hacked website

    Check the index.php file in your installation folder. Look at the very bottom of the file, maybe there are some additional lines of code. I had similar situation two years ago.
    Marcin

    http://www.contao.pl - Polish Support Site
    http://forum.contao.pl - Polish Contao community forum


    -----------------------
    Need custom template? Feel free to contact me by e-mail marcin@contao.pl

  3. #3
    User
    Join Date
    06-19-09.
    Posts
    106

    Default Re: Help with hacked website

    Thank you for the feedback. I've had a look and think the index.php file looks fine:

    Code:
    <?php
    
    /**
     * TYPOlight Open Source CMS
     * Copyright (C) 2005-2010 Leo Feyer
     *
     * This program is free software: you can redistribute it and/or
     * modify it under the terms of the GNU Lesser General Public
     * License as published by the Free Software Foundation, either
     * version 3 of the License, or (at your option) any later version.
     * 
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
     * Lesser General Public License for more details.
     * 
     * You should have received a copy of the GNU Lesser General Public
     * License along with this program. If not, please visit the Free
     * Software Foundation website at <http://www.gnu.org/licenses/>.
     *
     * PHP version 5
     * @copyright  Leo Feyer 2005-2010
     * @author     Leo Feyer <http://www.typolight.org>
     * @package    Frontend
     * @license    LGPL
     * @filesource
     */
    
    
    /**
     * Initialize the system
     */
    define('TL_MODE', 'FE');
    require('system/initialize.php');
    
    
    /**
     * Class Index
     *
     * Main front end controller.
     * @copyright  Leo Feyer 2005-2010
     * @author     Leo Feyer <http://www.typolight.org>
     * @package    Controller
     */
    class Index extends Frontend
    {
    
    	/**
    	 * Initialize the object
    	 */
    	public function __construct()
    	{
    		// Try to read from cache
    		$this->outputFromCache();
    
    		// Load user object before calling the parent constructor
    		$this->import('FrontendUser', 'User');
    		parent::__construct();
    
    		// Check whether a user is logged in
    		define('BE_USER_LOGGED_IN', $this->getLoginStatus('BE_USER_AUTH'));
    		define('FE_USER_LOGGED_IN', $this->getLoginStatus('FE_USER_AUTH'));
    
    		// HOOK: trigger recall extension
    		if (!FE_USER_LOGGED_IN && $this->Input->cookie('tl_recall_fe') && in_array('recall', $this->Config->getActiveModules()))
    		{
    			Recall::frontend($this);
    		}
    	}
    
    
    	/**
    	 * Run the controller
    	 */
    	public function run()
    	{
    		global $objPage;
    
    		// Get page ID
    		$pageId = $this->getPageIdFromUrl();
    
    		// Load a website root page object if there is no page ID
    		if (is_null($pageId))
    		{
    			$objHandler = new $GLOBALS['TL_PTY']['root']();
    			$pageId = $objHandler->generate($this->getRootIdFromUrl(), true);
    		}
    
    		$time = time();
    
    		// Get the current page object
    		$objPage = $this->Database->prepare("SELECT * FROM tl_page WHERE (id=? OR alias=?)" . (!BE_USER_LOGGED_IN ? " AND (start='' OR start<?) AND (stop='' OR stop>?) AND published=1" : ""))
    								  ->execute((is_numeric($pageId) ? $pageId : 0), $pageId, $time, $time);
    
    		// Check the URL of each page if there are multiple results
    		if ($objPage->numRows > 1)
    		{
    			$objNewPage = null;
    			$strHost = $this->Environment->host;
    
    			while ($objPage->next())
    			{
    				$objCurrentPage = $this->getPageDetails($objPage->id);
    
    				// Look for a root page whose domain name matches the host name
    				if ($objCurrentPage->domain == $strHost || $objCurrentPage->domain == 'www.' . $strHost)
    				{
    					$objNewPage = $objCurrentPage;
    					break;
    				}
    
    				// Fall back to a root page without domain name
    				if ($objCurrentPage->domain == '')
    				{
    					$objNewPage = $objCurrentPage;
    				}
    			}
    
    			// Matching root page found
    			if (is_object($objNewPage))
    			{
    				$objPage = $objNewPage;
    			}
    		}
    
    		// Load an error 404 page object if the result is empty or still ambiguous
    		if ($objPage->numRows != 1)
    		{
    			$this->User->authenticate();
    			$objHandler = new $GLOBALS['TL_PTY']['error_404']();
    			$objHandler->generate($pageId);
    		}
    
    		// Load a website root page object if the page is a website root page
    		if ($objPage->type == 'root')
    		{
    			$objHandler = new $GLOBALS['TL_PTY']['root']();
    			$objHandler->generate($objPage->id);
    		}
    
    		// Inherit settings from parent pages if it has not been done yet
    		if (!is_bool($objPage->protected))
    		{
    			$objPage = $this->getPageDetails($objPage->id);
    
    			// Check whether there are domain name restrictions
    			if (strlen($objPage->domain))
    			{
    				$strDomain = preg_replace('/^www\./i', '', $objPage->domain);
    
    				// Load an error 404 page object
    				if ($strDomain != $this->Environment->host)
    				{
    					$objHandler = new $GLOBALS['TL_PTY']['error_404']();
    					$objHandler->generate($objPage->id, $strDomain, $this->Environment->host);
    				}
    			}
    		}
    
    		// Authenticate the current user
    		if (!$this->User->authenticate() && $objPage->protected && !BE_USER_LOGGED_IN)
    		{
    			$objHandler = new $GLOBALS['TL_PTY']['error_403']();
    			$objHandler->generate($pageId);
    		}
    
    		// Check user groups if the page is protected
    		if ($objPage->protected && !BE_USER_LOGGED_IN && (!is_array($objPage->groups) || count($objPage->groups) < 1 || count(array_intersect($objPage->groups, $this->User->groups)) < 1))
    		{
    			$this->log('Page "' . $pageId . '" can only be accessed by groups "' . implode(', ', (array) $objPage->groups) . '" (current user groups: ' . implode(', ', $this->User->groups) . ')', 'Index run()', TL_ERROR);
    
    			$objHandler = new $GLOBALS['TL_PTY']['error_403']();
    			$objHandler->generate($pageId);
    		}
    
    		// Load the page object depending on its type
    		$objHandler = new $GLOBALS['TL_PTY'][$objPage->type]();
    
    		switch ($objPage->type)
    		{
    			case 'root':
    			case 'error_403':
    			case 'error_404':
    				$objHandler->generate($pageId);
    				break;
    
    			default:
    				$objHandler->generate($objPage);
    				break;
    		}
    	}
    
    
    	/**
    	 * Load the page from the cache table
    	 */
    	protected function outputFromCache()
    	{
    		// Build page if a user is logged in or there is POST data
    		if ($_SESSION['TL_USER_LOGGED_IN'] || !empty($_POST))
    		{
    			return;
    		}
    
    		$this->import('Environment');
    		$strCacheKey = $this->Environment->base . preg_replace('@^index.php/?@i', '', $this->Environment->request);
    
    		// Do not cache empty requests
    		if (!$strCacheKey)
    		{
    			return;
    		}
    
    		$strCacheFile = TL_ROOT . '/system/tmp/' . md5($strCacheKey);
    
    		// Return if the file does not exist
    		if (!file_exists($strCacheFile))
    		{
    			return;
    		}
    
    		$expire = null;
    		$content = null;
    
    		// Include file
    		ob_start();
    		require_once($strCacheFile);
    
    		// File has expired
    		if ($expire < time())
    		{
    			ob_end_clean();
    			return;
    		}
    
    		// Read buffer
    		$strBuffer = ob_get_contents();
    		ob_end_clean();
    
    		/**
    		 * Copyright notice
    		 * 
    		 * ACCORDING TO THE LESSER GENERAL PUBLIC LICENSE (LGPL),YOU ARE NOT
    		 * PERMITTED TO RUN TYPOlight WITHOUT THIS COPYRIGHT NOTICE. CHANGING,
    		 * REMOVING OR OBSTRUCTING IT IS PROHIBITED BY LAW!
    		 */
    		$strBuffer = preg_replace
    		(
    			'/(<head[^>]*>)/',
    			"<!--\n\n"
    			. "\tThis website is powered by TYPOlight Open Source CMS :: Licensed under GNU/LGPL\n"
    			. "\tCopyright ©2005-" . date('Y') . " by Leo Feyer :: Extensions are copyright of their respective owners\n"
    			. "\tVisit the project website at http://www.typolight.org for more information\n\n"
    			. "//-->\n$1",
    			$strBuffer, 1
    		);
    
    		// Session required to determine the referer
    		$this->import('Session');
    		$session = $this->Session->getData();
    
    		// Set new referer
    		if (!isset($_GET['pdf']) && !isset($_GET['file']) && !isset($_GET['id']) && $session['referer']['current'] != $this->Environment->requestUri)
    		{
    			$session['referer']['last'] = $session['referer']['current'];
    			$session['referer']['current'] = $this->Environment->requestUri;
    		}
    
    		// Store session data
    		$this->Session->setData($session);
    
    		// Content type
    		if (!$content)
    		{
    			$content = 'text/html';
    		}
    
    		header('Content-Type: ' . $content . '; charset=' . $GLOBALS['TL_CONFIG']['characterSet']);
    
    		// Send cache headers
    		if (!is_null($expire) && ($GLOBALS['TL_CONFIG']['cacheMode'] == 'both' || $GLOBALS['TL_CONFIG']['cacheMode'] == 'browser'))
    		{
    			header('Cache-Control: public, max-age=' . ($expire - time()));
    			header('Expires: ' . gmdate('D, d M Y H:i:s', $expire) . ' GMT');
    			header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
    			header('Pragma: public');
    		}
    		else
    		{
    			header('Cache-Control: no-cache');
    			header('Cache-Control: pre-check=0, post-check=0', false);
    			header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
    			header('Expires: Wed, 28 Jan 1976 11:52:00 GMT');
    			header('Pragma: no-cache');
    		}
    
    		// Replace insert tags
    		$strBuffer = $this->replaceInsertTags($strBuffer);
    		$strBuffer = str_replace(array('[{]', '[}]'), array('{{', '}}'), $strBuffer);
    
    		echo $strBuffer;
    		exit;
    	}
    }
    
    
    /**
     * Instantiate controller
     */
    $objIndex = new Index();
    $objIndex->run();
    
    ?>

    Also, this is the .htaccess file:
    Code:
    RewriteEngine On
    RewriteBase /
    RewriteCond %{REQUEST_URI} ^[^/]*/?(plugins|system|tl_files|typolight|img|uploads)/(.*)
    RewriteRule ^(.*)$ $1 [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule .*$ index.php [L]
    
    rewritecond %{http_host} ^fightforsight.org.uk [nc]
    rewriterule ^(.*)$ http://www.fightforsight.org.uk/$1 [r=301,nc] 
    
    DirectoryIndex index.html index.php

    Would anyone have another idea what it might be/where to look?

    By the way, only existing folders re-direct. If I put something random after the domain, e.g. www.domain.com/alksjdlkasjdlkajd it correctly goes to the 404 error page.

  4. #4
    Experienced user
    Join Date
    06-20-09.
    Posts
    1,311

    Default Re: Help with hacked website

    As a thought - if you run the contao-check system check tool for your installation, it should tell you which files are modified (corrupt).

  5. #5
    User
    Join Date
    01-20-11.
    Location
    Germany
    Posts
    77

    Default Re: Help with hacked website

    Hello,

    I guess the best idea is:
    1. Change all passwords immediately before the next step.
    2. Do a backup of all files and the database
    3. Check the files in tl_files and templates for the links to the Russian web page
    4. Especially check the database tl_user and tl_member tables for logins created by the hacker.
    5. Delete all files from the web space
    6. Install a new setup of Contao and all extensions used and connect to the existing (and checked!) version of the database
    7. Import files from tl_files and templates

    This will give you a new and clean installation of Contao, it's extensions and it's files/database.

    Jan
    Free support only here in the forum.
    Please report bugs for my extensions using http://www.contao-forge.org. Thanks!
    Requests for Contao support and development please send mail to jan@theofel.de

  6. #6
    Locker
    Gast

    Default Re: Help with hacked website

    Quote Originally Posted by ramjet
    As a thought - if you run the contao-check system check tool for your installation, it should tell you which files are modified (corrupt).
    When my site got hacked, I tried this, but there was so much corrupted files, that I just decided to delete it all and start from scratch. It was a pain, but I wanted to make sure I got rid of all of the modified files.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •