Так проблема в том, что сайт не торгует их техникой. Информация о том, что они ремонтируют технику этого бренда. Тут уже и до маразама недалеко, запретят без разрешения упоминать бренд, будем говорить "я купил себе посудомойку БИИИП.". Так что ли?
Пришло аналогичное письмо с жалобой на страницу про "ремонт стиральных машин Bosch", где есть их логотип и список моделей стиральных машин. То есть, сайт ничего не продает, больше как информационный. Что в таком случае сделать?
Файл /data/Scanner.php из которого потом создается serval-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.php, размещаемый на наблюдаемых ресурсах - это непосредственный скрипт сканирования файловой структуры.
<? {[copyright]} ini_set('display_errors', 'Off'); ini_set('track_errors', 1); ini_set('memory_limit','100M'); error_reporting(0); set_time_limit(300); register_shutdown_function('serval_shutdown_func'); /* Класс сканера */ Class Scanner{ var $log = array( 'scan'=>array(), /* Массив папок, которых просканировали */ 'dir'=>array(), /* Массив папок, которые в очереди */ 'file'=>array() /* Массив информации о файлах (Имя, Размер, Хеш, Вложенность, Папка) */ ); var $ext = false; /* Массив расширений файлов для сканирования */ var $exc = false; /* Массив папок, которые нужно исключить */ var $excf = false; /* Массив файлов, которые нужно исключить */ var $rootDir = ''; /* Root папка */ var $dirId = 1; /* Счетчик */ var $version = 1.6; /* Версия сканера */ var $maxDir = 100; /* Максимальное кол-во папок за раз по умолчанию */ var $isTest = false; function run($param = array()){ if(!is_array($param) || empty($param['path'])){ return array("status"=>'error','version'=>$this->version,'msg'=>"Ошибка передачи данных"); } $param['path'] = $this->fixPath(($param['path'] === '.' ? $_SERVER['DOCUMENT_ROOT'] : $param['path'])); /* Максимальное кол-во папок */ if($param['dirMax']>0){ $this->maxDir = $param['dirMax']; } /* Если это тест */ if($param['is_test']=="yes"){ $this->isTest = true; } if(is_dir($param['path'])){ if(is_array($param['ext']) && count($param['ext'])>0){ foreach($param['ext'] as $v){ $v = trim($v); if(!empty($v)){ $this->ext[] = $v; } } } $this->ext = (is_array($param['ext']) && count($param['ext'])>0) ? $param['ext'] : false; if(is_array($param['exc']) && count($param['exc'])>0){ foreach($param['exc'] as $v){ $v = trim($v); if(!empty($v)){ $dir = $param['path'].'/'.$v.'/'; $this->exc[] = $this->fixPath($dir,false); } } } $this->excf = (is_array($param['excf']) && count($param['excf'])>0) ? $param['excf'] : false; if(is_array($param['excf']) && count($param['excf'])>0){ foreach($param['excf'] as $v){ $v = trim($v); if(!empty($v)){ $this->excf[] = $this->fixPath($param['path'].'/'.$v,false); } } } $this->rootDir = $param['path']; /* Если передали папки, которые нужно просканировать (шаги) */ if(is_array($param['listDir']) && count($param['listDir'])>0){ foreach($param['listDir'] as $val){ if(!empty($val)){ $this->dirId++; $this->log['dir'][$this->dirId] = $val; $this->find($val['path'],$this->dirId,($val['level']+1)); } } }else{ $this->find($param['path'],$this->dirId); } return array("status"=>'ok','dirMax'=>$this->maxDir,'version'=>$this->version,'log'=>$this->log); }else{ return array("status"=>'error','version'=>$this->version,'msg'=>"Ошибка! root папка не доступна!"); } } /* Метод сканирует папку */ function find($path,$dirId,$i=0){ if(count($this->log['scan'])>=$this->maxDir) return false; /* Максимум, который можно просканировать */ if($i>100) return false; /* Если большая вложенность */ $path = $this->fixPath($path.'/'); $fixPath = $this->fixPath($path.'/',false); /* Читаем папку */ $list = glob($path."{.*,*}",GLOB_BRACE); if(isset($this->log['dir'][$dirId])){ $this->log['scan'][$dirId] = $this->log['dir'][$dirId]; } unset($this->log['dir'][$dirId]); if(count($list)>0){ foreach($list as $val){ $pathInfo = pathinfo($val); if($pathInfo['basename'] === '.' || $pathInfo['basename'] === '..' || is_link($val)) continue; if($this->exc && in_array($val.'/',$this->exc) ) continue; if(is_dir($val)){ $PathName = $this->fixPath($pathInfo['dirname'].'/'.$pathInfo['basename'].'/',false); if(empty($PathName)) continue; if($this->skip($this->fixPath($pathInfo['dirname'].'/'.$pathInfo['basename'].'/'),$this->exc)) continue; $this->dirId++; $this->log['dir'][$this->dirId] = array('path'=>$PathName,'level'=>$i); if(!$this->isTest){ $this->find($val,$this->dirId,($i+1)); } } if(is_file($val)){ if(!$this->ext || in_array(".".$pathInfo['extension'],$this->ext)){ if($this->skip($val,$this->excf)) continue; $this->log['file'][] = array( 'dirId'=>$dirId, 'level'=>$i, 'name'=>$pathInfo['basename'], 'size'=>filesize($val), 'hash'=>$this->hashFile($val), ); } } unset($pathInfo); } } unset($list); } /* FIX пути папки */ function fixPath($val,$root = true){ $val = $this->rootDir.'/'.str_replace($this->rootDir,"/",$val); if(!$root){ /* Удаляем рутовую директорию */ $val = '/'.str_replace($this->rootDir,"/",$val); } return preg_replace('~[\/]+~u','/',$val); } /* Метод получает хеш сумму файла */ function hashFile($file){ $hash = false; if (function_exists('hash_file')) { $hash = @hash_file('md5', $file); } elseif(function_exists('md5_file')) { $hash = @md5_file($file); } else { if($c = file_get_contents($file)){ $hash = md5($c); unset($c); } } return $hash ? $hash : -1; } /* Метод обработки исключений */ function skip($str_in,$exc){ if(is_array($exc) && count($exc)>0){ foreach($exc as $str){ $str = preg_quote("[{$str}]","#"); $str = str_replace("\*","(.*)",$str); if(preg_match("#^({$str})#","[".$str_in."]",$matches)){ return true; } } } return false; } } /* Класс кодирования */ Class BritCrypt{ var $key = null; var $encodingIn = 'UTF-8'; var $encodingOut = 'CP866'; var $stb = 63; var $type = 'default'; /* Кодирование */ function encrypt($string=''){ if(empty($this->key)) return false; if($this->type=="lite"){ return $this->crypt_lite($string); }else{ $keyw = $this->calculateKeyw($string); $Len = mb_strlen($string, $this->encodingIn); $result = ''; for ($i = 0; $i < $Len; $i++) { $char = mb_substr($string, $i, 1, $this->encodingIn); $ord = ord(iconv($this->encodingIn, $this->encodingOut, $char)); $char = chr(($ord - $this->stb) ^ $keyw[$i]); $result.= iconv($this->encodingOut, $this->encodingIn, $char); } unset($string); return $result; } } function calculateKeyw($pass){ $keyw = array(); $lenPass = mb_strlen($pass, $this->encodingIn); $lenKey = mb_strlen($this->key, $this->encodingIn); for ($i = 1; $i <= $lenPass; $i++) { if ($lenKey < $lenPass) { $j = $i % $lenKey; if ($j === 0) { $j = $lenKey; } } else { $j = $i; } $keyw[] = ord(mb_substr($this->key, $j - 1, 1, $this->encodingIn)); } return $keyw; } /* Декодирование */ function decrypt($string=''){ if(empty($this->key)) return false; if($this->type=="lite"){ return $this->crypt_lite($string); }else{ $keyw = $this->calculateKeyw($string); $Len = mb_strlen($string, $this->encodingIn); $result = ''; for ($i = 0; $i < $Len; $i++) { $char = mb_substr($string, $i, 1, $this->encodingIn); $ord = ord(iconv($this->encodingIn, $this->encodingOut, $char)); $ord = $ord ^ $keyw[$i]; $result .=iconv($this->encodingOut, $this->encodingIn, chr($ord + $this->stb)); } unset($string); return $result; } } /* Легкое кодирование */ function crypt_lite($string){ if(empty($this->key)) return false; for($i=0;$i<mb_strlen($string,'utf-8');){ for($j=0;$j<mb_strlen($this->key,'utf-8');$j++, $i++){ $outText .= $string{$i} ^ $this->key{$j}; } } unset($string); return $outText; } } $_POST['_scan_isOk'] = false; if(isset($_POST['run']) && $_POST['run']=="DoCheckThis"){ $sCode = "{[sCODE]}"; $_crypt = new BritCrypt; $_crypt->key = $sCode; $_crypt->type = $_POST['crypt_type']; $data = unserialize($_crypt->decrypt(base64_decode($_POST['data']))); unset($_POST['data']); $scan = new Scanner(); $result = $scan->run($data); unset($data); echo $_crypt->encrypt(base64_encode(serialize($result))); $_POST['_scan_isOk'] = true; } /* Для отлова ошибок */ function serval_shutdown_func(){ if(!$_POST['_scan_isOk']){ $error = error_get_last(); $sCode = "{[sCODE]}"; $_crypt = new BritCrypt($sCode); $_crypt->type = $_POST['crypt_type']; $result = array('status'=>'error','msg'=>"Error: ".$error['message']); echo $_crypt->encrypt(serialize($result)); die(); } } ?>
Здесь нет никакого вебшелла, так что паника по поводу "ааа поставил хреновину, а на сайте появились ссылки" исключена.
P.S. Нашли маленький баг - был удален отладочный ключ на диагностику ошибок сервера. Выложили новый релиз 2.0.3.
В нем должна быть инструкция по установке? По-моему, все и так ясно. В следующий релиз добавим.
Аккаунтом я назвал дисковое пространство, в котором размещаются файлы системы. Он должен, по дефолту, корневым по http. А как это будет устроенно у вас - не имеет значение.
Если перепишите правила в .htaccess - конечно подойдет. Вся адресация там относительно корня идет.
Нет, мы 100% не хотим никому ничего рассылать, а SeVlad меня практически убедил, что смысла в регистрациях нет, так что, через неделю, быстрее всего, скачать можно "без регистраций и смс" =)
А по поводу опасений в вебшелле, единственный - скрипт-сканер, который кладется на наблюдаемые сайты. Сейчас наш программист его подробно откомментрует и я выложу для успокоения. Может приз объявить за поиск шелла в SerVal? :)
Вот, все понял без лишних вопросов :) Если есть хорошее решение, почему бы им не поделиться, а узнаваемость никому не помешает 🍻---------- Добавлено 01.06.2016 в 17:57 ----------
Лучше бы разрешили подправить топик, исправлю мягкий знак и добавлю ссылку на группу в ФБ.
Почему? Я еще раз сказал, чтобы не на унылую цифру смотреть, а на реальных пользователей. Не денег же просим, не ключ от квартиры... 😡
Кто не хочет отставлять свой мыл - есть специальные сервисы, никто не запрещает. Мало того, я дал ссылку на скачивание без регистрации http://www.serval.site/download/5f752bbf6bf99aece869a7b238587726/. Безопасность скриптов может каждый изучить по открытому исходному коду (их чуть больше 40). А если не можете, то, при всем к вам уважении, не надо ля-ля, подозревать, про звоночки какие-то писать. Мы же в техническом разделе, а не на форуме домохозяек, сами же написали!
Я полностью ответил на вопрос?
Не хотите - не скачивайте, не пользуйтесь, только флейм разводить не надо.
Так какие вопросы интересуют? Почему мы просим регистрацию? Я ответил, потому что мы так хотим, как минимум, первое время. Какие еще вопросы?
Внизу на сайте http://www.serval.site/ написано:
.
Скажите, будет ли студия, работающая с 1999 года, портить репутацию рассылкой вебшеллов и пр.? Мы делимся своим внутренним продуктом, который написали и использовали около 3-х лет только для себя, а потом обернули в новый дизайн и выложили в паблик.
Тем, что приведенный вами скрипт надо вещать на крон на каждый хостинг и контролировать его наличие.
У нас тоже так было в самом начале. Теперь это система, в которую сеошник, заходит с утра под чашечку кофе и смотрит все свои проекты сразу. Можно сказать, это как агрегатор таких скриптов в едином интерфейсе. К тому же, ничего не сохраняется на наблюдаемом сайте, никакой даты.