HEX
Server: Apache/2.4.54 (Debian)
System: Linux f988254d8f22 6.8.0-87-generic #88~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Oct 14 14:03:14 UTC 2 x86_64
User: (1000)
PHP: 7.4.33
Disabled: NONE
Upload Files
File: /var/www/html/wp-content/plugins/kboard/helper/Security.helper.php
<?php
if(!defined('ABSPATH')) exit;
/**
 * KBoard 워드프레스 게시판 보안 함수
 * @link www.cosmosfarm.com
 * @copyright Copyright 2021 Cosmosfarm. All rights reserved.
 * @license http://www.gnu.org/licenses/gpl.html
 */

// 시스템 설정을 가져온다.
$kboard_xssfilter_active = get_option('kboard_xssfilter')?false:true;
if($kboard_xssfilter_active){
	// HTML Purifier 클래스를 불러온다.
	if(!class_exists('HTMLPurifier')){
		include_once KBOARD_DIR_PATH.'/htmlpurifier/HTMLPurifier.standalone.php';
	}
	// HTML Purifier 캐시 저장을 위한 디렉토리 생성
	wp_mkdir_p(WP_CONTENT_DIR.'/uploads/kboard_htmlpurifier');
}

/**
 * Cross-site scripting (XSS) 공격을 방어하기 위해서 위험한 문자열을 제거한다.
 * @param string $data
 */
function kboard_xssfilter($data){
	global $kboard_xssfilter_active;
	if(is_array($data)) return array_map('kboard_xssfilter', $data);
	if($kboard_xssfilter_active){
		if(!isset($GLOBALS['KBOARD']) || !isset($GLOBALS['KBOARD']['HTMLPurifier']) || !$GLOBALS['KBOARD']['HTMLPurifier'] || !isset($GLOBALS['KBOARD']['HTMLPurifier_Config']) || !$GLOBALS['KBOARD']['HTMLPurifier_Config']){
			$HTMLPurifier_Config = HTMLPurifier_Config::createDefault();
			$HTMLPurifier_Config->set('URI.AllowedSchemes', array('http'=>true,'https'=>true,'mailto'=>true,'tel'=>true,'data'=>true));
			$HTMLPurifier_Config->set('URI.SafeIframeRegexp', '(.*)');
			$HTMLPurifier_Config->set('HTML.SafeIframe', true);
			$HTMLPurifier_Config->set('HTML.SafeObject', true);
			$HTMLPurifier_Config->set('HTML.SafeEmbed', true);
			$HTMLPurifier_Config->set('HTML.TidyLevel', 'light');
			$HTMLPurifier_Config->set('HTML.FlashAllowFullScreen', true);
			$HTMLPurifier_Config->set('HTML.AllowedElements','img,div,a,strong,font,span,em,del,ins,br,p,u,i,b,sup,sub,small,table,thead,tbody,tfoot,tr,td,th,caption,pre,code,ul,ol,li,big,code,blockquote,center,hr,h1,h2,h3,h4,h5,h6,iframe,dl,dt,dd');
			$HTMLPurifier_Config->set('HTML.AllowedAttributes', 'a.rel,a.href,a.target,img.src,iframe.src,iframe.frameborder,*.id,*.alt,*.style,*.class,*.title,*.width,*.height,*.border,*.colspan,*.rowspan');
			$HTMLPurifier_Config->set('HTML.TargetNoreferrer', false);
			$HTMLPurifier_Config->set('Attr.AllowedFrameTargets', array('_blank'));
			$HTMLPurifier_Config->set('Attr.EnableID', true);
			$HTMLPurifier_Config->set('Attr.AllowedRel', 'nofollow,noopener,noreferrer');
			$HTMLPurifier_Config->set('Output.FlashCompat', true);
			$HTMLPurifier_Config->set('Core.RemoveInvalidImg', true);
			$HTMLPurifier_Config->set('Core.LexerImpl', 'DirectLex');
			$HTMLPurifier_Config->set('Cache.SerializerPath', WP_CONTENT_DIR.'/uploads/kboard_htmlpurifier');
			$GLOBALS['KBOARD']['HTMLPurifier_Config'] = $HTMLPurifier_Config;
			$GLOBALS['KBOARD']['HTMLPurifier'] = HTMLPurifier::getInstance();
			unset($HTMLPurifier_Config);
		}
		$data = $GLOBALS['KBOARD']['HTMLPurifier']->purify($data, $GLOBALS['KBOARD']['HTMLPurifier_Config']);
	}
	return trim($data);
}

/**
 * 허용된 도메인의 아이프레임만 남기고 모두 제거한다.
 * @param string $data
 * @return string
 */
function kboard_safeiframe($data){
	if(is_array($data)) return array_map('kboard_safeiframe', $data);
	
	/*
	 * 허가된 도메인 호스트 (화이트리스트)
	 */
	$whitelist = kboard_iframe_whitelist(true);
	
	// kboard_iframe_whitelist 필터
	$whitelist = apply_filters('kboard_iframe_whitelist', $whitelist);
	
	preg_match_all('/<iframe.+?src="(.+?)".+?[^>]*+>/is', $data, $matches);
	
	$iframe = $matches[0];
	$domain = $matches[1];
	
	foreach($domain as $key=>$value){
		$value = 'http://' . preg_replace('/^(http:\/\/|https:\/\/|\/\/)/i', '', $value);
		$url = parse_url($value);
		if(!in_array($url['host'], $whitelist)){
			$data = str_replace($iframe[$key].'</iframe>', '', $data);
			$data = str_replace($iframe[$key], '', $data);
		}
	}
	
	// 풀스크린 허용
	$data = preg_replace('/<iframe(.*?)>/is', '<iframe$1 allowfullscreen>', $data);
	
	return $data;
}

/**
 * 모든 html을 제거한다.
 * @param object $data
 */
function kboard_htmlclear($data){
	if(is_array($data)) return array_map('kboard_htmlclear', $data);
	$data = sanitize_text_field($data);
	return htmlspecialchars($data);
}

/**
 * 아이프레임 화이트리스트를 반환한다.
 * @param boolean $to_array
 */
function kboard_iframe_whitelist($to_array=false){
	/*
	 * 허가된 도메인 호스트 (화이트리스트)
	 */
	$whitelist = 'google.com' . PHP_EOL;
	$whitelist .= 'www.google.com' . PHP_EOL;
	$whitelist .= 'youtube.com' . PHP_EOL;
	$whitelist .= 'www.youtube.com' . PHP_EOL;
	$whitelist .= 'maps.google.com' . PHP_EOL;
	$whitelist .= 'maps.google.co.kr' . PHP_EOL;
	$whitelist .= 'docs.google.com' . PHP_EOL;
	$whitelist .= 'tv.naver.com' . PHP_EOL;
	$whitelist .= 'serviceapi.nmv.naver.com' . PHP_EOL;
	$whitelist .= 'serviceapi.rmcnmv.naver.com' . PHP_EOL;
	$whitelist .= 'videofarm.daum.net' . PHP_EOL;
	$whitelist .= 'tv.kakao.com' . PHP_EOL;
	$whitelist .= 'player.vimeo.com' . PHP_EOL;
	$whitelist .= 'w.soundcloud.com' . PHP_EOL;
	$whitelist .= 'slideshare.net' . PHP_EOL;
	$whitelist .= 'www.slideshare.net' . PHP_EOL;
	$whitelist .= 'channel.pandora.tv' . PHP_EOL;
	$whitelist .= 'mgoon.com' . PHP_EOL;
	$whitelist .= 'www.mgoon.com' . PHP_EOL;
	$whitelist .= 'tudou.com' . PHP_EOL;
	$whitelist .= 'www.tudou.com' . PHP_EOL;
	$whitelist .= 'player.youku.com' . PHP_EOL;
	$whitelist .= 'videomega.tv' . PHP_EOL;
	$whitelist .= 'mtab.clickmon.co.kr' . PHP_EOL;
	$whitelist .= 'tab2.clickmon.co.kr';
	
	$iframe_whitelist_data = get_option('kboard_iframe_whitelist');
	$iframe_whitelist_data = trim($iframe_whitelist_data);
	
	if(!$iframe_whitelist_data){
		$iframe_whitelist_data = $whitelist;
	}
	
	if($to_array){
		$iframe_whitelist_data = explode(PHP_EOL, $iframe_whitelist_data);
		return array_map('trim', $iframe_whitelist_data);
	}
	return $iframe_whitelist_data;
}

if(!function_exists('hash_pbkdf2')){
	/**
	 * hash_pbkdf2
	 * @link http://php.net/manual/en/function.hash-pbkdf2.php#118301
	 * @param string $algo
	 * @param string $password
	 * @param string $salt
	 * @param int $count
	 * @param int $length
	 * @param string $raw_output
	 * @return string
	 */
	function hash_pbkdf2($algo, $password, $salt, $count, $length = 0, $raw_output = false){
		if(!in_array(strtolower($algo), hash_algos())) trigger_error(__FUNCTION__ . '(): Unknown hashing algorithm: ' . $algo, E_USER_WARNING);
		if(!is_numeric($count)) trigger_error(__FUNCTION__ . '(): expects parameter 4 to be long, ' . gettype($count) . ' given', E_USER_WARNING);
		if(!is_numeric($length)) trigger_error(__FUNCTION__ . '(): expects parameter 5 to be long, ' . gettype($length) . ' given', E_USER_WARNING);
		if($count <= 0) trigger_error(__FUNCTION__ . '(): Iterations must be a positive integer: ' . $count, E_USER_WARNING);
		if($length < 0) trigger_error(__FUNCTION__ . '(): Length must be greater than or equal to 0: ' . $length, E_USER_WARNING);
		$output = '';
		$block_count = $length ? ceil($length / strlen(hash($algo, '', $raw_output))) : 1;
		for($i=1; $i<=$block_count; $i++){
			$last = $xorsum = hash_hmac($algo, $salt . pack('N', $i), $password, true);
			for($j=1; $j<$count; $j++){
				$xorsum ^= ($last = hash_hmac($algo, $last, $password, true));
			}
			$output .= $xorsum;
		}
		if(!$raw_output) $output = bin2hex($output);
		return $length ? substr($output, 0, $length) : $output;
	}
}

/**
 * 텍스트의 해시값을 반환한다.
 * @param string $text
 * @param string $salt
 * @param number $length
 * @return string
 */
function kboard_hash($text, $salt, $length=0){
	switch(strlen($text)%8){
		case 0 : $salt = AUTH_KEY . md5($salt); break;
		case 1 : $salt = SECURE_AUTH_KEY . md5($salt); break;
		case 2 : $salt = LOGGED_IN_KEY . md5($salt); break;
		case 3 : $salt = NONCE_KEY . md5($salt); break;
		case 4 : $salt = AUTH_SALT . md5($salt); break;
		case 5 : $salt = SECURE_AUTH_SALT . md5($salt); break;
		case 6 : $salt = LOGGED_IN_SALT . md5($salt); break;
		case 7 : $salt = NONCE_SALT . md5($salt); break;
	}
	return '$kboard$v1$' . hash_pbkdf2('sha256', $text, $salt, 100000, $length);
}