IncludeModuleLangFile(__FILE__);
class CSecurityRedirect
{
public static function BeforeLocalRedirect(&$url, $skip_security_check)
{
// ToDo: refactoring candidate
//This define will be used on buffer end handler
if(!defined("BX_SECURITY_LOCAL_REDIRECT"))
define("BX_SECURITY_LOCAL_REDIRECT", true);
$kernelSession = \Bitrix\Main\Application::getInstance()->getKernelSession();
if ($kernelSession->isStarted() && $kernelSession->has("LOCAL_REDIRECTS"))
{
if($kernelSession["LOCAL_REDIRECTS"]["C"] == 0 && $kernelSession["LOCAL_REDIRECTS"]["R"] == '')
$kernelSession["LOCAL_REDIRECTS"]["R"] = ($_SERVER["HTTP_REFERER"] ?? '');
$kernelSession["LOCAL_REDIRECTS"]["C"]++;
}
else
{
$kernelSession["LOCAL_REDIRECTS"] = array("C" => 1, "R" => ($_SERVER["HTTP_REFERER"] ?? ''));
}
if($skip_security_check)
return;
/** global CMain $APPLICATION */
global $APPLICATION;
$good = true;
$url = str_replace("\xe2\x80\xae", "", $url);
$url_l = str_replace(array("\r", "\n"), "", $url);
//In case of absolute url will check if server to be redirected is our
$bSkipCheck = false;
if(preg_match('~^(?:http|https)://(.*?)(\\\\|/|\?|#|$|%252f|%2f)~iD', $url_l, $arMatch))
{
if(defined("BX24_HOST_NAME"))
{
$arSite = array(
"SERVER_NAME" => BX24_HOST_NAME,
"DOMAINS" => ""
);
}
elseif(defined("SITE_ID"))
{
$rsSite = CSite::GetByID(SITE_ID);
$arSite = $rsSite->Fetch();
}
else
{
$arSite = false;
}
if(!$bSkipCheck && $arSite && $arSite["SERVER_NAME"])
{
$bSkipCheck = $arMatch[1] === $arSite["SERVER_NAME"];
}
if(!$bSkipCheck && $arSite && $arSite["DOMAINS"])
{
$arDomains = explode("\n", str_replace("\r", "\n", $arSite["DOMAINS"]));
foreach($arDomains as $domain)
{
$domain = trim($domain, " \t\n\r");
if($domain <> '')
{
if($domain === mb_substr($arMatch[1], -mb_strlen($domain)))
{
$bSkipCheck = true;
break;
}
}
}
}
if(!$bSkipCheck)
{
$host = COption::GetOptionString("main", "server_name", "");
$bSkipCheck = $host && $arMatch[1] === $host;
}
if (strpos(strtolower($arMatch[2]), '%2f') === 0)
{
$good = false;
$bSkipCheck = false;
}
}
if(!$bSkipCheck && preg_match("/^(http|https|ftp):\\/\\//i", $url_l))
{
if($kernelSession["LOCAL_REDIRECTS"]["C"] > 1)
$REFERER_TO_CHECK = $kernelSession["LOCAL_REDIRECTS"]["R"];
else
$REFERER_TO_CHECK = ($_SERVER["HTTP_REFERER"] ?? '');
if($good && COption::GetOptionString("security", "redirect_referer_check") == "Y")
{
$good &= $REFERER_TO_CHECK <> '';
}
if($good && $REFERER_TO_CHECK <> '' && COption::GetOptionString("security", "redirect_referer_site_check") == "Y")
{
$valid_site = ($APPLICATION->IsHTTPS()? "https://": "http://").$_SERVER['HTTP_HOST']."/";
$good &= mb_strpos($REFERER_TO_CHECK, $valid_site) === 0;
}
if($good && COption::GetOptionString("security", "redirect_href_sign") == "Y")
{
$sid = static::GetSeed();
$good &= static::Sign($sid, $url) === $_GET["af"];
}
if(!$good)
{
global $APPLICATION;
if(COption::GetOptionString("security", "redirect_log") == "Y")
CSecurityEvent::getInstance()->doLog(
"SECURITY",
"SECURITY_REDIRECT",
$APPLICATION->GetCurPage(),
$url
);
if(COption::GetOptionString("security", "redirect_action") == "show_message_and_stay")
{
$mess = COption::GetOptionString("security", "redirect_message_warning_".LANGUAGE_ID);
if($mess == '')
$mess = COption::GetOptionString("security", "redirect_message_warning");
$charset = COption::GetOptionString("security", "redirect_message_charset");
if($mess == '')
{
$mess = CSecurityRedirect::GetDefaultMessage();
$charset = LANG_CHARSET;
}
$html_mess = str_replace("+", "+", htmlspecialcharsbx($mess));
//Convert to site encoding
if (!defined("BX_UTF") && defined("LANG_CHARSET"))
{
$url_c = \Bitrix\Main\Text\Encoding::convertEncoding($url, "UTF-8", LANG_CHARSET);
}
else
{
$url_c = $url;
}
if (preg_match('~^(http|https)(://)(.*?)(?:\\\\|/|\?|#|$)~iD', $url_c, $arMatch))
{
$converter = CBXPunycode::GetConverter();
$url_e = $arMatch[1].$arMatch[2].$converter->Encode($arMatch[3]).mb_substr($url_c, mb_strlen($arMatch[1].$arMatch[2].$arMatch[3]));
}
else
{
$url_e = $url;
}
$url = htmlspecialcharsbx($url);
$html_url = ''.htmlspecialcharsEx($url_c).'';
$html_mess = str_replace("#URL#", $html_url, $html_mess);
CHTTP::SetStatus("404 Not Found");
header('X-Frame-Options: DENY');
header('X-Robots-Tag: noindex, nofollow');
?>
|
|
|
|
|
Warning: Undefined variable $html_mess in D:\ktt\ttepla.com\public_html\bitrix\modules\security\classes\general\redirect.php on line 192
|
|
|
|
|
|
die();
}
else
{
$url = COption::GetOptionString("security", "redirect_url");
}
}
}
}
public static function GetDefaultMessage($language_id = false)
{
if($language_id===false)
{
return GetMessage("SEC_REDIRECT_DEFAULT_MESSAGE");
}
else
{
$mess = IncludeModuleLangFile(__FILE__, $language_id, true);
if($mess["SEC_REDIRECT_DEFAULT_MESSAGE"] <> '')
{
return $mess["SEC_REDIRECT_DEFAULT_MESSAGE"];
}
else
{
return GetMessage("SEC_REDIRECT_DEFAULT_MESSAGE");
}
}
}
public static function EndBufferContent(&$content)
{
//There was no looped local redirects
//so it's only true referer
if(!defined("BX_SECURITY_LOCAL_REDIRECT"))
\Bitrix\Main\Application::getInstance()->getKernelSession()["LOCAL_REDIRECTS"] = array("C" => 0, "R" => ($_SERVER["HTTP_REFERER"] ?? ''));
if(COption::GetOptionString("security", "redirect_href_sign") == "Y")
$content = preg_replace_callback("#(/]*?href\\s*=\\s*)(['\"])(.+?)(\\2)#i", array("self", "ReplaceHREF"), $content);
}
protected static function ReplaceHREF($matches)
{
static $arUrls = false;
static $sid = false;
static $strDomains = false;
if(!$arUrls)
{
$arUrls = self::GetUrls();
$sid = static::GetSeed();
$arDomains = self::GetDomains();
foreach($arDomains as $i => $domain)
$arDomains[$i] = preg_quote($domain, "/");
$strDomains = "/.*(".implode("|", $arDomains).")$/";
}
foreach($arUrls as $arUrl)
{
if(preg_match("/^(http(?:s){0,1}\\:\\/\\/(?:[a-zA-Z0-9\\.-])+){0,1}".preg_quote($arUrl["URL"], "/")."?.*?".preg_quote($arUrl["PARAMETER_NAME"], "/")."=(http|https|ftp)(:|%3A|%3A)(\\/\\/|%2F%2F|%2F%2F)([^&]+)/im", $matches[3], $match))
{
if($match[1] == '' || preg_match($strDomains, $match[1]))
{
$goto = $match[2].$match[3].$match[4].$match[5];
$goto = str_replace(
array("%", "%3A", "%2F"),
array("%", ":", "/"),
$goto);
return $matches[1].$matches[2].$matches[3]."&af=".static::Sign($sid, urldecode($goto)).$matches[4];
}
}
}
return $matches[0];
}
public static function GetUrls()
{
/**
* global CDatabase $DB
* global CCacheManager $CACHE_MANAGER
*/
global $DB, $CACHE_MANAGER;
if(CACHED_b_sec_redirect_url !== false)
{
$cache_id = "b_sec_redirect_url";
if($CACHE_MANAGER->Read(CACHED_b_sec_filter_mask, $cache_id, "b_sec_redirect_url"))
{
$arUrls = $CACHE_MANAGER->Get($cache_id);
}
else
{
$arUrls = array();
$rs = $DB->Query("SELECT URL, PARAMETER_NAME, IS_SYSTEM from b_sec_redirect_url ORDER BY IS_SYSTEM DESC, SORT ASC");
while($ar = $rs->Fetch())
$arUrls[] = $ar;
$CACHE_MANAGER->Set($cache_id, $arUrls);
}
}
else
{
$arUrls = array();
$rs = $DB->Query("SELECT URL, PARAMETER_NAME, IS_SYSTEM from b_sec_redirect_url ORDER BY IS_SYSTEM DESC, SORT ASC");
while($ar = $rs->Fetch())
$arUrls[] = $ar;
}
return $arUrls;
}
public static function GetDomains()
{
/**
* global CDatabase $DB
* global CCacheManager $CACHE_MANAGER
*/
global $DB, $CACHE_MANAGER;
if(CACHED_b_lang_domain !== false)
{
if($CACHE_MANAGER->Read(CACHED_b_lang_domain, "b_sec_domains", "b_lang_domain"))
{
$arDomains = $CACHE_MANAGER->Get("b_sec_domains");
}
else
{
$arDomains = array();
$rs = $DB->Query("SELECT DOMAIN from b_lang_domain");
while($ar = $rs->Fetch())
$arDomains[] = $ar["DOMAIN"];
$CACHE_MANAGER->Set("b_sec_domains", $arDomains);
}
}
else
{
$arDomains = array();
$rs = $DB->Query("SELECT DOMAIN from b_lang_domain");
while($ar = $rs->Fetch())
$arDomains[] = $ar["DOMAIN"];
}
return $arDomains;
}
public static function ReSeed()
{
COption::SetOptionString("security", "redirect_sid", Bitrix\Main\Security\Random::getString(32));
}
public static function GetSeed()
{
$seed = COption::GetOptionString("security", "redirect_sid");
if (!$seed)
{
static::ReSeed();
$seed = COption::GetOptionString("security", "redirect_sid");
}
return $seed;
}
public static function Sign($seed, $data)
{
$seed .= $_SERVER["REMOTE_ADDR"];
return md5($seed.md5($seed.":".$data));
}
public static function IsActive()
{
$bActive = false;
foreach(GetModuleEvents("main", "OnBeforeLocalRedirect", true) as $event)
{
if(
$event["TO_MODULE_ID"] == "security"
&& $event["TO_CLASS"] == "CSecurityRedirect"
)
{
$bActive = true;
break;
}
}
return $bActive;
}
public static function SetActive($bActive = false)
{
if($bActive)
{
if(!CSecurityRedirect::IsActive())
{
static::ReSeed();
RegisterModuleDependences("main", "OnBeforeLocalRedirect", "security", "CSecurityRedirect", "BeforeLocalRedirect", "1");
RegisterModuleDependences("main", "OnEndBufferContent", "security", "CSecurityRedirect", "EndBufferContent", "1");
}
}
else
{
if(CSecurityRedirect::IsActive())
{
UnRegisterModuleDependences("main", "OnBeforeLocalRedirect", "security", "CSecurityRedirect", "BeforeLocalRedirect");
UnRegisterModuleDependences("main", "OnEndBufferContent", "security", "CSecurityRedirect", "EndBufferContent");
}
}
}
public static function Update($arUrls)
{
/**
* global CDatabase $DB
* global CCacheManager $CACHE_MANAGER
*/
global $DB, $CACHE_MANAGER;
if(is_array($arUrls))
{
$res = $DB->Query("DELETE FROM b_sec_redirect_url WHERE IS_SYSTEM <> 'Y'", false, "File: ".__FILE__."
Line: ".__LINE__);
if($res)
{
$added = array();
$i = 10;
foreach($arUrls as $arUrl)
{
$url = trim($arUrl["URL"]);
$param = trim($arUrl["PARAMETER_NAME"]);
$key = $url.":".$param;
if(mb_strlen($url) && mb_strlen($param) && !array_key_exists($key, $added))
{
$arUrl = array(
"ID" => 1,
"IS_SYSTEM" => "N",
"SORT" => $i,
"URL" => $url,
"PARAMETER_NAME" => $param,
);
$DB->Add("b_sec_redirect_url", $arUrl);
$i += 10;
$added[$key] = true;
}
}
if(CACHED_b_sec_redirect_url !== false)
$CACHE_MANAGER->CleanDir("b_sec_redirect_url");
}
}
return true;
}
public static function GetList()
{
/** global CDatabase $DB */
global $DB;
$res = $DB->Query("SELECT URL, PARAMETER_NAME, IS_SYSTEM from b_sec_redirect_url ORDER BY IS_SYSTEM DESC, SORT ASC");
return $res;
}
}
?>