Note that there are some explanatory texts on larger screens.

plurals
  1. POHacker Backdoor script?
    text
    copied!<p>I found this script attached to a modified index page. This looks like some kind of backdoor. and who is this SAPE ?</p> <pre><code>&lt;?php class SAPE_base { var $_version = '1.0.8'; var $_verbose = false; var $_charset = ''; var $_sape_charset = ''; var $_server_list = array('dispenser-01.sape.ru', 'dispenser-02.sape.ru'); var $_cache_lifetime = 3600; var $_cache_reloadtime = 600; var $_error = ''; var $_host = ''; var $_request_uri = ''; var $_multi_site = false; var $_fetch_remote_type = ''; var $_socket_timeout = 6; var $_force_show_code = false; var $_is_our_bot = false; var $_debug = false; var $_ignore_case = false; var $_db_file = ''; var $_use_server_array = false; var $_force_update_db = false; function SAPE_base($options = null) { $host = ''; if (is_array($options)) { if (isset($options['host'])) { $host = $options['host']; } } elseif (strlen($options)) { $host = $options; $options = array(); } else { $options = array(); } if (isset($options['use_server_array']) &amp;&amp; $options['use_server_array'] == true) { $this-&gt;_use_server_array = true; } if (strlen($host)) { $this-&gt;_host = $host; } else { $this-&gt;_host = $_SERVER['HTTP_HOST']; } $this-&gt;_host = preg_replace('/^http:\/\//', '', $this-&gt;_host); $this-&gt;_host = preg_replace('/^www\./', '', $this-&gt;_host); if (isset($options['request_uri']) &amp;&amp; strlen($options['request_uri'])) { $this-&gt;_request_uri = $options['request_uri']; } elseif ($this-&gt;_use_server_array === false) { $this-&gt;_request_uri = getenv('REQUEST_URI'); } if (strlen($this-&gt;_request_uri) == 0) { $this-&gt;_request_uri = $_SERVER['REQUEST_URI']; } if (isset($options['multi_site']) &amp;&amp; $options['multi_site'] == true) { $this-&gt;_multi_site = true; } if (isset($options['debug']) &amp;&amp; $options['debug'] == true) { $this-&gt;_debug = true; } if (isset($_COOKIE['sape_cookie']) &amp;&amp; ($_COOKIE['sape_cookie'] == _SAPE_USER)) { $this-&gt;_is_our_bot = true; if (isset($_COOKIE['sape_debug']) &amp;&amp; ($_COOKIE['sape_debug'] == 1)) { $this-&gt;_debug = true; $this-&gt;_options = $options; $this-&gt;_server_request_uri = $this-&gt;_request_uri = $_SERVER['REQUEST_URI']; $this-&gt;_getenv_request_uri = getenv('REQUEST_URI'); $this-&gt;_SAPE_USER = _SAPE_USER; } if (isset($_COOKIE['sape_updatedb']) &amp;&amp; ($_COOKIE['sape_updatedb'] == 1)) { $this-&gt;_force_update_db = true; } } else { $this-&gt;_is_our_bot = false; } if (isset($options['verbose']) &amp;&amp; $options['verbose'] == true || $this-&gt;_debug) { $this-&gt;_verbose = true; } if (isset($options['charset']) &amp;&amp; strlen($options['charset'])) { $this-&gt;_charset = $options['charset']; } else { $this-&gt;_charset = 'windows-1251'; } if (isset($options['fetch_remote_type']) &amp;&amp; strlen($options['fetch_remote_type'])) { $this-&gt;_fetch_remote_type = $options['fetch_remote_type']; } if (isset($options['socket_timeout']) &amp;&amp; is_numeric($options['socket_timeout']) &amp;&amp; $options['socket_timeout'] &gt; 0) { $this-&gt;_socket_timeout = $options['socket_timeout']; } if (isset($options['force_show_code']) &amp;&amp; $options['force_show_code'] == true) { $this-&gt;_force_show_code = true; } if (!defined('_SAPE_USER')) { return $this-&gt;raise_error('Не задана константа _SAPE_USER'); } if (isset($options['ignore_case']) &amp;&amp; $options['ignore_case'] == true) { $this-&gt;_ignore_case = true; $this-&gt;_request_uri = strtolower($this-&gt;_request_uri); } } function fetch_remote_file($host, $path) { $user_agent = $this-&gt;_user_agent . ' ' . $this-&gt;_version; @ini_set('allow_url_fopen', 1); @ini_set('default_socket_timeout', $this-&gt;_socket_timeout); @ini_set('user_agent', $user_agent); if ( $this-&gt;_fetch_remote_type == 'file_get_contents' || ( $this-&gt;_fetch_remote_type == '' &amp;&amp; function_exists('file_get_contents') &amp;&amp; ini_get('allow_url_fopen') == 1 ) ) { $this-&gt;_fetch_remote_type = 'file_get_contents'; if ($data = @file_get_contents('http://' . $host . $path)) { return $data; } } elseif ( $this-&gt;_fetch_remote_type == 'curl' || ( $this-&gt;_fetch_remote_type == '' &amp;&amp; function_exists('curl_init') ) ) { $this-&gt;_fetch_remote_type = 'curl'; if ($ch = @curl_init()) { @curl_setopt($ch, CURLOPT_URL, 'http://' . $host . $path); @curl_setopt($ch, CURLOPT_HEADER, false); @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); @curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this-&gt;_socket_timeout); @curl_setopt($ch, CURLOPT_USERAGENT, $user_agent); if ($data = @curl_exec($ch)) { return $data; } @curl_close($ch); } } else { $this-&gt;_fetch_remote_type = 'socket'; $buff = ''; $fp = @fsockopen($host, 80, $errno, $errstr, $this-&gt;_socket_timeout); if ($fp) { @fputs($fp, "GET {$path} HTTP/1.0\r\nHost: {$host}\r\n"); @fputs($fp, "User-Agent: {$user_agent}\r\n\r\n"); while (!@feof($fp)) { $buff .= @fgets($fp, 128); } @fclose($fp); $page = explode("\r\n\r\n", $buff); return $page[1]; } } return $this-&gt;raise_error('Не могу подключиться к серверу: ' . $host . $path . ', type: ' . $this-&gt;_fetch_remote_type); } function _read($filename) { $fp = @fopen($filename, 'rb'); @flock($fp, LOCK_SH); if ($fp) { clearstatcache(); $length = @filesize($filename); $mqr = @get_magic_quotes_runtime(); @set_magic_quotes_runtime(0); if ($length) { $data = @fread($fp, $length); } else { $data = ''; } @set_magic_quotes_runtime($mqr); @flock($fp, LOCK_UN); @fclose($fp); return $data; } return $this-&gt;raise_error('Не могу считать данные из файла: ' . $filename); } function _write($filename, $data) { $fp = @fopen($filename, 'ab'); if ($fp) { if (flock($fp, LOCK_EX | LOCK_NB)) { $length = strlen($data); ftruncate($fp, 0); @fwrite($fp, $data, $length); @flock($fp, LOCK_UN); @fclose($fp); if (md5($this-&gt;_read($filename)) != md5($data)) { @unlink($filename); return $this-&gt;raise_error('Нарушена целостность данных при записи в файл: ' . $filename); } } else { return false; } return true; } return $this-&gt;raise_error('Не могу записать данные в файл: ' . $filename); } function raise_error($e) { $this-&gt;_error = '&lt;p style="color: red; font-weight: bold;"&gt;SAPE ERROR: ' . $e . '&lt;/p&gt;'; if ($this-&gt;_verbose == true) { print $this-&gt;_error; } return false; } function load_data() { $this-&gt;_db_file = $this-&gt;_get_db_file(); if (!is_file($this-&gt;_db_file)) { if (@touch($this-&gt;_db_file)) { @chmod($this-&gt;_db_file, 0666); } else { return $this-&gt;raise_error('Нет файла ' . $this-&gt;_db_file . '. Создать не удалось. Выставите права 777 на папку.'); } } if (!is_writable($this-&gt;_db_file)) { return $this-&gt;raise_error('Нет доступа на запись к файлу: ' . $this-&gt;_db_file . '! Выставите права 777 на папку.'); } @clearstatcache(); $data = $this-&gt;_read($this-&gt;_db_file); if ( $this-&gt;_force_update_db || ( !$this-&gt;_is_our_bot &amp;&amp; ( filemtime($this-&gt;_db_file) &lt; (time() - $this-&gt;_cache_lifetime) || filesize($this-&gt;_db_file) == 0 || @unserialize($data) == false ) ) ) { @touch($this-&gt;_db_file, (time() - $this-&gt;_cache_lifetime + $this-&gt;_cache_reloadtime)); $path = $this-&gt;_get_dispenser_path(); if (strlen($this-&gt;_charset)) { $path .= '&amp;charset=' . $this-&gt;_charset; } foreach ($this-&gt;_server_list as $i =&gt; $server) { if ($data = $this-&gt;fetch_remote_file($server, $path)) { if (substr($data, 0, 12) == 'FATAL ERROR:') { $this-&gt;raise_error($data); } else { $hash = @unserialize($data); if ($hash != false) { $hash['__sape_charset__'] = $this-&gt;_charset; $hash['__last_update__'] = time(); $hash['__multi_site__'] = $this-&gt;_multi_site; $hash['__fetch_remote_type__'] = $this-&gt;_fetch_remote_type; $hash['__ignore_case__'] = $this-&gt;_ignore_case; $hash['__php_version__'] = phpversion(); $hash['__server_software__'] = $_SERVER['SERVER_SOFTWARE']; $data_new = @serialize($hash); if ($data_new) { $data = $data_new; } $this-&gt;_write($this-&gt;_db_file, $data); break; } } } } } if (strlen(session_id())) { $session = session_name() . '=' . session_id(); $this-&gt;_request_uri = str_replace(array('?' . $session, '&amp;' . $session), '', $this-&gt;_request_uri); } $this-&gt;set_data(@unserialize($data)); } } class SAPE_client extends SAPE_base { var $_links_delimiter = ''; var $_links = array(); var $_links_page = array(); var $_user_agent = 'SAPE_Client PHP'; function SAPE_client($options = null) { parent::SAPE_base($options); $this-&gt;load_data(); } function return_links($n = null, $offset = 0) { if (is_array($this-&gt;_links_page)) { $total_page_links = count($this-&gt;_links_page); if (!is_numeric($n) || $n &gt; $total_page_links) { $n = $total_page_links; } $links = array(); for ($i = 1; $i &lt;= $n; $i++) { if ($offset &gt; 0 &amp;&amp; $i &lt;= $offset) { array_shift($this-&gt;_links_page); } else { $links[] = array_shift($this-&gt;_links_page); } } $html = join($this-&gt;_links_delimiter, $links); if ( strlen($this-&gt;_charset) &gt; 0 &amp;&amp; strlen($this-&gt;_sape_charset) &gt; 0 &amp;&amp; $this-&gt;_sape_charset != $this-&gt;_charset &amp;&amp; function_exists('iconv') ) { $new_html = @iconv($this-&gt;_sape_charset, $this-&gt;_charset, $html); if ($new_html) { $html = $new_html; } } if ($this-&gt;_is_our_bot) { $html = '&lt;sape_noindex&gt;' . $html . '&lt;/sape_noindex&gt;'; } } else { $html = $this-&gt;_links_page; } if ($this-&gt;_debug) { $html .= print_r($this, true); } return $html; } function _get_db_file() { if ($this-&gt;_multi_site) { return dirname(__FILE__) . '/' . $this-&gt;_host . '.links.db'; } else { return dirname(__FILE__) . '/links.db'; } } function _get_dispenser_path() { return '/code.php?user=' . _SAPE_USER . '&amp;host=' . $this-&gt;_host; } function set_data($data) { if ($this-&gt;_ignore_case) { $this-&gt;_links = array_change_key_case($data); } else { $this-&gt;_links = $data; } if (isset($this-&gt;_links['__sape_delimiter__'])) { $this-&gt;_links_delimiter = $this-&gt;_links['__sape_delimiter__']; } if (isset($this-&gt;_links['__sape_charset__'])) { $this-&gt;_sape_charset = $this-&gt;_links['__sape_charset__']; } else { $this-&gt;_sape_charset = ''; } if (@array_key_exists($this-&gt;_request_uri, $this-&gt;_links) &amp;&amp; is_array($this-&gt;_links[$this-&gt;_request_uri])) { $this-&gt;_links_page = $this-&gt;_links[$this-&gt;_request_uri]; } else { if (isset($this-&gt;_links['__sape_new_url__']) &amp;&amp; strlen($this-&gt;_links['__sape_new_url__'])) { if ($this-&gt;_is_our_bot || $this-&gt;_force_show_code) { $this-&gt;_links_page = $this-&gt;_links['__sape_new_url__']; } } } } } class SAPE_context extends SAPE_base { var $_words = array(); var $_words_page = array(); var $_user_agent = 'SAPE_Context PHP'; var $_filter_tags = array('a', 'textarea', 'select', 'script', 'style', 'label', 'noscript', 'noindex', 'button'); function SAPE_context($options = null) { parent::SAPE_base($options); $this-&gt;load_data(); } function replace_in_text_segment($text) { $debug = ''; if ($this-&gt;_debug) { $debug .= "&lt;!-- argument for replace_in_text_segment: \r\n" . base64_encode($text) . "\r\n --&gt;"; } if (count($this-&gt;_words_page) &gt; 0) { $source_sentence = array(); if ($this-&gt;_debug) { $debug .= '&lt;!-- sentences for replace: '; } foreach ($this-&gt;_words_page as $n =&gt; $sentence) { //Заменяем все сущности на символы $special_chars = array( '&amp;amp;' =&gt; '&amp;', '&amp;quot;' =&gt; '"', '&amp;#039;' =&gt; '\'', '&amp;lt;' =&gt; '&lt;', '&amp;gt;' =&gt; '&gt;' ); $sentence = strip_tags($sentence); foreach ($special_chars as $from =&gt; $to) { str_replace($from, $to, $sentence); } $sentence = htmlspecialchars($sentence); $sentence = preg_quote($sentence, '/'); $replace_array = array(); if (preg_match_all('/(&amp;[#a-zA-Z0-9]{2,6};)/isU', $sentence, $out)) { for ($i = 0; $i &lt; count($out[1]); $i++) { $unspec = $special_chars[$out[1][$i]]; $real = $out[1][$i]; $replace_array[$unspec] = $real; } } foreach ($replace_array as $unspec =&gt; $real) { $sentence = str_replace($real, '((' . $real . ')|(' . $unspec . '))', $sentence); } $source_sentences[$n] = str_replace(' ', '((\s)|(&amp;nbsp;))+', $sentence); if ($this-&gt;_debug) { $debug .= $source_sentences[$n] . "\r\n\r\n"; } } if ($this-&gt;_debug) { $debug .= '--&gt;'; } $first_part = true; if (count($source_sentences) &gt; 0) { $content = ''; $open_tags = array(); $close_tag = ''; $part = strtok(' ' . $text, '&lt;'); while ($part !== false) { if (preg_match('/(?si)^(\/?[a-z0-9]+)/', $part, $matches)) { $tag_name = strtolower($matches[1]); if (substr($tag_name, 0, 1) == '/') { $close_tag = substr($tag_name, 1); if ($this-&gt;_debug) { $debug .= '&lt;!-- close_tag: ' . $close_tag . ' --&gt;'; } } else { $close_tag = ''; if ($this-&gt;_debug) { $debug .= '&lt;!-- open_tag: ' . $tag_name . ' --&gt;'; } } $cnt_tags = count($open_tags); if (($cnt_tags &gt; 0) &amp;&amp; ($open_tags[$cnt_tags - 1] == $close_tag)) { array_pop($open_tags); if ($this-&gt;_debug) { $debug .= '&lt;!-- ' . $tag_name . ' - deleted from open_tags --&gt;'; } if ($cnt_tags - 1 == 0) { if ($this-&gt;_debug) { $debug .= '&lt;!-- start replacement --&gt;'; } } } if (count($open_tags) == 0) { if (!in_array($tag_name, $this-&gt;_filter_tags)) { $split_parts = explode('&gt;', $part, 2); if (count($split_parts) == 2) { foreach ($source_sentences as $n =&gt; $sentence) { if (preg_match('/' . $sentence . '/', $split_parts[1]) == 1) { $split_parts[1] = preg_replace('/' . $sentence . '/', str_replace('$', '\$', $this-&gt;_words_page[$n]), $split_parts[1], 1); if ($this-&gt;_debug) { $debug .= '&lt;!-- ' . $sentence . ' --- ' . $this-&gt;_words_page[$n] . ' replaced --&gt;'; } unset($source_sentences[$n]); unset($this-&gt;_words_page[$n]); } } $part = $split_parts[0] . '&gt;' . $split_parts[1]; unset($split_parts); } } else { $open_tags[] = $tag_name; if ($this-&gt;_debug) { $debug .= '&lt;!-- ' . $tag_name . ' - added to open_tags, stop replacement --&gt;'; } } } } else { foreach ($source_sentences as $n =&gt; $sentence) { if (preg_match('/' . $sentence . '/', $part) == 1) { $part = preg_replace('/' . $sentence . '/', str_replace('$', '\$', $this-&gt;_words_page[$n]), $part, 1); if ($this-&gt;_debug) { $debug .= '&lt;!-- ' . $sentence . ' --- ' . $this-&gt;_words_page[$n] . ' replaced --&gt;'; } unset($source_sentences[$n]); unset($this-&gt;_words_page[$n]); } } } if ($this-&gt;_debug) { $content .= $debug; $debug = ''; } if ($first_part) { $content .= $part; $first_part = false; } else { $content .= $debug . '&lt;' . $part; } unset($part); $part = strtok('&lt;'); } $text = ltrim($content); unset($content); } } else { if ($this-&gt;_debug) { $debug .= '&lt;!-- No word`s for page --&gt;'; } } if ($this-&gt;_debug) { $debug .= '&lt;!-- END: work of replace_in_text_segment() --&gt;'; } if ($this-&gt;_is_our_bot || $this-&gt;_force_show_code || $this-&gt;_debug) { $text = '&lt;sape_index&gt;' . $text . '&lt;/sape_index&gt;'; if (isset($this-&gt;_words['__sape_new_url__']) &amp;&amp; strlen($this-&gt;_words['__sape_new_url__'])) { $text .= $this-&gt;_words['__sape_new_url__']; } } if ($this-&gt;_debug) { if (count($this-&gt;_words_page) &gt; 0) { $text .= '&lt;!-- Not replaced: ' . "\r\n"; foreach ($this-&gt;_words_page as $n =&gt; $value) { $text .= $value . "\r\n\r\n"; } $text .= '--&gt;'; } $text .= $debug; } return $text; } function replace_in_page(&amp;$buffer) { if (count($this-&gt;_words_page) &gt; 0) { $split_content = preg_split('/(?smi)(&lt;\/?sape_index&gt;)/', $buffer, -1); $cnt_parts = count($split_content); if ($cnt_parts &gt; 1) { //Если есть хоть одна пара sape_index, то начинаем работу if ($cnt_parts &gt;= 3) { for ($i = 1; $i &lt; $cnt_parts; $i = $i + 2) { $split_content[$i] = $this-&gt;replace_in_text_segment($split_content[$i]); } } $buffer = implode('', $split_content); if ($this-&gt;_debug) { $buffer .= '&lt;!-- Split by Sape_index cnt_parts=' . $cnt_parts . '--&gt;'; } } else { $split_content = preg_split('/(?smi)(&lt;\/?body[^&gt;]*&gt;)/', $buffer, -1, PREG_SPLIT_DELIM_CAPTURE); if (count($split_content) == 5) { $split_content[0] = $split_content[0] . $split_content[1]; $split_content[1] = $this-&gt;replace_in_text_segment($split_content[2]); $split_content[2] = $split_content[3] . $split_content[4]; unset($split_content[3]); unset($split_content[4]); $buffer = $split_content[0] . $split_content[1] . $split_content[2]; if ($this-&gt;_debug) { $buffer .= '&lt;!-- Split by BODY --&gt;'; } } else { if ($this-&gt;_debug) { $buffer .= '&lt;!-- Can`t split by BODY --&gt;'; } } } } else { if (!$this-&gt;_is_our_bot &amp;&amp; !$this-&gt;_force_show_code &amp;&amp; !$this-&gt;_debug) { $buffer = preg_replace('/(?smi)(&lt;\/?sape_index&gt;)/', '', $buffer); } else { if (isset($this-&gt;_words['__sape_new_url__']) &amp;&amp; strlen($this-&gt;_words['__sape_new_url__'])) { $buffer .= $this-&gt;_words['__sape_new_url__']; } } if ($this-&gt;_debug) { $buffer .= '&lt;!-- No word`s for page --&gt;'; } } return $buffer; } function _get_db_file() { if ($this-&gt;_multi_site) { return dirname(__FILE__) . '/' . $this-&gt;_host . '.words.db'; } else { return dirname(__FILE__) . '/words.db'; } } function _get_dispenser_path() { return '/code_context.php?user=' . _SAPE_USER . '&amp;host=' . $this-&gt;_host; } function set_data($data) { $this-&gt;_words = $data; if (@array_key_exists($this-&gt;_request_uri, $this-&gt;_words) &amp;&amp; is_array($this-&gt;_words[$this-&gt;_request_uri])) { $this-&gt;_words_page = $this-&gt;_words[$this-&gt;_request_uri]; } } } ?&gt; </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload