shSecEnableSecurity) return ''; $shQuery = empty($query) ? (empty($_SERVER['QUERY_STRING']) ? '' : $_SERVER['QUERY_STRING']) : $query; // IP checks $ip = empty($_SERVER['REMOTE_ADDR']) ? '' : $_SERVER['REMOTE_ADDR']; $uAgent = empty($_SERVER['HTTP_USER_AGENT']) ? '' : $_SERVER['HTTP_USER_AGENT']; // ip White/Black listing $shWhiteListedIp = shCheckIPList($ip, $sefConfig->ipWhiteList); if (!$shWhiteListedIp) { if (shCheckIPList($ip, $sefConfig->ipBlackList)) shDoRestrictedAccess('Blacklisted IP'); } // UserAgent White/Black listing $whiteListedUAgent = shCheckUAgentList($uAgent, $sefConfig->uAgentWhiteList); if (!$whiteListedUAgent) { if (shCheckUAgentList($uAgent, $sefConfig->uAgentBlackList)) shDoRestrictedAccess('BlackListed user agent'); } if (!$shWhiteListedIp && !$whiteListedUAgent && $fullCheck) { shDoAntiFloodCheck($ip); } // url content checks $halt = 0; while (true) { // allow for multiple url decode $last = $shQuery; $shQuery = urldecode($shQuery); // do our tests $shQuery = str_replace('&', '&', $shQuery); // bad content in query string $c = shCheckConfigVars($shQuery); if ($c) shDoRestrictedAccess($c . ' in URL'); $c = shCheckBase64($shQuery); if ($c) shDoRestrictedAccess($c . ' in URL'); $c = shCheckScripts($shQuery); if ($c) shDoRestrictedAccess($c . ' in URL'); $c = shCheckStandardVars($_GET); if ($c) shDoRestrictedAccess($c . ' in URL'); $c = shCheckImgTxtCmd($shQuery); // V x if ($c) shDoRestrictedAccess($c . ' in URL'); // Check whether the last decode is equal to the previous one if ($shQuery == $last) { // Break out of the while if the URI is stable. break; } else if (++$halt > 10) { // Runaway check. URI has been seriously compromised. shDoRestrictedAccess('Multiple level of url encode'); } } if (!$fullCheck) return; // don't check POST and/or Honey pot if second check // check POST variables if ($sefConfig->shSecCheckPOSTData) { $c = shCheckStandardVars($_POST); if ($c) shDoRestrictedAccess($c . ' in POST'); foreach ($_POST as $key => $value) { $c = shCheckConfigVars($key . '=' . $value); if ($c) shDoRestrictedAccess($c . ' in POST'); $c = shCheckBase64($key . '=' . $value); if ($c) shDoRestrictedAccess($c . ' in POST'); $c = shCheckScripts($key . '=' . $value); if ($c) shDoRestrictedAccess($c . ' in POST'); $c = shCheckImgTxtCmd($key . '=' . $value); // V x if ($c) shDoRestrictedAccess($c . ' in POST'); } } // do Project Honey Pot check if (!$shWhiteListedIp && $sefConfig->shSecCheckHoneyPot) { shDoHoneyPotCheck($ip); } } function shSendEmailToAdmin($logData) { if (!sh404SEF_SEC_MAIL_ATTACKS_TO_ADMIN) return; $mainframe = JFactory::getApplication(); $subject = str_replace('%sh404SEF_404_SITE_NAME%', $mainframe->getCfg('sitename'), sh404SEF_SEC_EMAIL_TO_ADMIN_SUBJECT); $logText = ''; foreach ($logData as $key => $text) { $logText .= "\n" . $key . "\t\t" . ' :: ' . shSecOutput(JString::trim($text)); } $body = str_replace('%sh404SEF_404_SITE_URL%', Sh404sefFactory::getPageInfo()->getDefaultFrontLiveSite(), sh404SEF_SEC_EMAIL_TO_ADMIN_BODY); $body = str_replace('%sh404SEF_404_ATTACK_DETAILS%', $logText, $body); if (!defined('_ISO')) define('_ISO', 'charset=iso-8859-1'); jimport('joomla.mail.mail'); JMail::sendMail($mainframe->getCfg('mailfrom'), $mainframe->getCfg('fromname'), $mainframe->getCfg('mailfrom'), $subject, $body); } function shLogToSecFile($logData) { $shNum = 12 * (intval(date('Y')) - 2000) + intval(date('m')); // number current month $fileName = 'sh404sef/sec/log_' . date('Y') . '-' . date('m') . '-' . 'sh404SEF_security_log' . '.' . $shNum . '.log.php'; $options = array('text_entry_format' => "{DATE}\t{TIME}\t{CAUSE}\t{C-IP}\t{USER}\t{USER_AGENT}\t{REQUEST_METHOD}\t{REQUEST_URI}\t{COMMENT}", 'text_file' => $fileName); jimport('joomla.error.log'); JLog::addLogger($options, JLog::INFO, array('sh404sef_sec')); $entry = new JLogEntry(''); foreach ($logData as $key => $value) { $entry->$key = $value; } $entry->category = 'sh404sef_sec'; // and add it JLog::add($entry, JLog::INFO, 'sh404sef_sec'); } function shCleanUpSecLogFiles() { // delete security log files older than param $sefConfig = Sh404sefFactory::getConfig(); if (mt_rand(1, SH404SEF_PAGES_TO_CLEAN_LOGS) != 1) return; // probability = 1/SH404SEF_PAGES_TO_CLEAN_LOGS $curMonth = 12 * (intval(date('Y')) - 2000) + intval(date('m')); if ($sefConfig->shSecLogAttacks) { if ($handle = @opendir(JPATH_ROOT . '/logs/sh404sef/sec')) { while (false !== ($file = readdir($handle))) { $matches = array(); if ($file != '.' && $file != '..' && preg_match('/\.[0-9]*\./', $file, $matches)) { $fileNum = JString::trim($matches[0], '.'); if ($curMonth - $fileNum > $sefConfig->monthsToKeepLogs) { @unlink(JPATH_ROOT . '/logs/sh404sef/sec/' . $file); ShlSystem_Log::debug('sh404sef', 'Erasing security log file : ' . $file); } } } closedir($handle); } } } function shDoRestrictedAccess($causeText, $comment = '', $displayEntrance = false) { $sefConfig = Sh404sefFactory::getConfig(); if ($sefConfig->shSecLogAttacks) { // log what's happening $logData = array(); $logData['DATE'] = ShlSystem_Date::getSiteNow('Y-m-d'); $logData['TIME'] = ShlSystem_Date::getSiteNow('H:i:s'); $logData['CAUSE'] = shSecOutput($causeText); $logData['C-IP'] = empty($_SERVER['REMOTE_ADDR']) ? '-' : $_SERVER['REMOTE_ADDR']; if ($_SERVER['REMOTE_ADDR'] != 'localhost' && $_SERVER['REMOTE_ADDR'] != '::1') { $name = getHostByAddr($_SERVER['REMOTE_ADDR']); } else { $name = '-'; } $logData['NAME'] = $name; $logData['USER_AGENT'] = empty($_SERVER['HTTP_USER_AGENT']) ? '-' : $_SERVER['HTTP_USER_AGENT']; $logData['REQUEST_METHOD'] = $_SERVER['REQUEST_METHOD']; $logData['REQUEST_URI'] = $_SERVER['REQUEST_URI']; $logData['COMMENT'] = $comment; shLogToSecFile($logData); } // V x : we can possibly send email to site admin, but not log shSendEmailToAdmin($logData); // actually restrict access if (!headers_sent()) { header('HTTP/1.0 403 FORBIDDEN'); } echo '
shSecSmellyPotText; ?>>>
(' . $causeText . ')'; } JFactory::getApplication()->close(403); } function shCheckConfigVars($query) { if (empty($query)) return ''; if (preg_match('/mosConfig_[a-zA-Z_]{1,21}=/iu', $query)) return 'mosConfig_var'; else return ''; } function shCheckBase64($query) { if (empty($query)) return ''; if (preg_match('/base64_encode.*\(.*\)/iu', $query)) return 'Base 64 encoded data'; else return ''; } function shCheckScripts($query) { if (empty($query)) return ''; if (preg_match('/(\<).*script[^A-Za-z0-9]*(\>)/iu', $query)) return '