update check_url_host ref: https://github.com/gnuboard/gnuboard5/issues/261
This commit is contained in:
parent
39adda76cc
commit
df218c0157
3 changed files with 43 additions and 46 deletions
|
|
@ -159,9 +159,6 @@ $_system->addons = load_libs(__DIR__ . "/addons", "addon");
|
||||||
// $_system->modules = load_libs(__DIR__ . "/modules", "model");
|
// $_system->modules = load_libs(__DIR__ . "/modules", "model");
|
||||||
// $_system->modules = load_libs(__DIR__ . "/modules");
|
// $_system->modules = load_libs(__DIR__ . "/modules");
|
||||||
|
|
||||||
// arc: 이 이벤트는 before 가 없습니다.
|
|
||||||
EventHandler::triggerEvent("gnuboard.loadlibs.after", $_system);
|
|
||||||
|
|
||||||
function g5_path()
|
function g5_path()
|
||||||
{
|
{
|
||||||
$result['path'] = str_replace('\\', '/', dirname(__FILE__));
|
$result['path'] = str_replace('\\', '/', dirname(__FILE__));
|
||||||
|
|
@ -183,6 +180,9 @@ $g5_path = g5_path();
|
||||||
|
|
||||||
include_once $g5_path['path'] . '/config.php'; // 설정 파일
|
include_once $g5_path['path'] . '/config.php'; // 설정 파일
|
||||||
|
|
||||||
|
// arc: 이 이벤트는 before 가 없습니다.
|
||||||
|
EventHandler::triggerEvent("gnuboard.loadlibs.after", $_system);
|
||||||
|
|
||||||
unset($g5_path);
|
unset($g5_path);
|
||||||
|
|
||||||
// Cloudflare 환경을 고려한 https 사용여부
|
// Cloudflare 환경을 고려한 https 사용여부
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ date_default_timezone_set("Asia/Seoul");
|
||||||
/********************
|
/********************
|
||||||
경로 상수
|
경로 상수
|
||||||
********************/
|
********************/
|
||||||
|
|
||||||
define('G5_DOMAIN', '');
|
define('G5_DOMAIN', '');
|
||||||
define('G5_HTTPS_DOMAIN', '');
|
define('G5_HTTPS_DOMAIN', '');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -568,7 +568,6 @@ function conv_content($content, $html, $filter = true)
|
||||||
return $content;
|
return $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// http://htmlpurifier.org/
|
// http://htmlpurifier.org/
|
||||||
// Standards-Compliant HTML Filtering
|
// Standards-Compliant HTML Filtering
|
||||||
// Safe : HTML Purifier defeats XSS with an audited whitelist
|
// Safe : HTML Purifier defeats XSS with an audited whitelist
|
||||||
|
|
@ -610,9 +609,9 @@ function html_purifier($html)
|
||||||
$config->set('HTML.Nofollow', true); // rel=nofollow 으로 스팸유입을 줄임
|
$config->set('HTML.Nofollow', true); // rel=nofollow 으로 스팸유입을 줄임
|
||||||
}
|
}
|
||||||
$config->set('URI.SafeIframeRegexp', '%^(https?:)?//(' . preg_replace('/\\\?\./', '\.', $safeiframe) . ')%');
|
$config->set('URI.SafeIframeRegexp', '%^(https?:)?//(' . preg_replace('/\\\?\./', '\.', $safeiframe) . ')%');
|
||||||
$config->set('Attr.AllowedFrameTargets', array('_blank'));
|
$config->set('Attr.AllowedFrameTargets', ['_blank']);
|
||||||
//유튜브, 비메오 전체화면 가능하게 하기
|
//유튜브, 비메오 전체화면 가능하게 하기
|
||||||
$config->set('Filter.Custom', array(new HTMLPurifier_Filter_Iframevideo()));
|
$config->set('Filter.Custom', [new HTMLPurifier_Filter_Iframevideo()]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* HTMLPurifier 설정을 변경할 수 있는 Event hook
|
* HTMLPurifier 설정을 변경할 수 있는 Event hook
|
||||||
|
|
@ -1601,7 +1600,7 @@ function sql_query($sql, $error = G5_DISPLAY_SQL_ERROR, $link = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
EventHandler::triggerEvent("gnuboard.sql_query_after", $result, $sql, $error);
|
EventHandler::triggerEvent("gnuboard.sql_query_after", $result, $sql, $error);
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2317,7 +2316,7 @@ function delete_cache_latest($bo_table)
|
||||||
foreach ($files as $filename)
|
foreach ($files as $filename)
|
||||||
unlink($filename);
|
unlink($filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
EventHandler::triggerEvent("gnuboard.delete_cache_latest", $bo_table);
|
EventHandler::triggerEvent("gnuboard.delete_cache_latest", $bo_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2378,7 +2377,7 @@ function delete_editor_thumbnail($contents)
|
||||||
unlink($filename);
|
unlink($filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EventHandler::triggerEvent("gnuboard.delete_editor_thumbnail_after", $contents, $matchs);
|
EventHandler::triggerEvent("gnuboard.delete_editor_thumbnail_after", $contents, $matchs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3173,7 +3172,7 @@ function member_delete($mb_id)
|
||||||
|
|
||||||
// 아이콘 삭제
|
// 아이콘 삭제
|
||||||
@unlink(G5_DATA_PATH . '/member/' . substr($mb_id, 0, 2) . '/' . $mb_id . '.gif');
|
@unlink(G5_DATA_PATH . '/member/' . substr($mb_id, 0, 2) . '/' . $mb_id . '.gif');
|
||||||
|
|
||||||
EventHandler::triggerEvent("gnuboard.member_delete_after", $mb_id);
|
EventHandler::triggerEvent("gnuboard.member_delete_after", $mb_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3283,37 +3282,42 @@ function login_password_check($mb, $pass, $hash)
|
||||||
|
|
||||||
return check_password($pass, $hash);
|
return check_password($pass, $hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 동일한 host url 인지
|
// 동일한 host url 인지
|
||||||
function check_url_host($url, $msg = '', $return_url = G5_URL, $is_redirect = false)
|
function check_url_host($url, $msg = '', $return_url = G5_URL, $is_redirect = false)
|
||||||
{
|
{
|
||||||
if (!$msg)
|
if (!$msg) {
|
||||||
$msg = 'url에 타 도메인을 지정할 수 없습니다.';
|
$msg = 'url에 타 도메인을 지정할 수 없습니다.';
|
||||||
|
}
|
||||||
|
|
||||||
if (run_replace('check_url_host_before', '', $url, $msg, $return_url, $is_redirect) === 'is_checked') {
|
if (run_replace('check_url_host_before', '', $url, $msg, $return_url, $is_redirect) === 'is_checked') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// KVE-2021-1277 Open Redirect 취약점 해결
|
|
||||||
if (preg_match('#\\\0#', $url)) {
|
if (preg_match('#\\\0#', $url)) {
|
||||||
alert('url 에 올바르지 않은 값이 포함되어 있습니다.');
|
alert('url 에 올바르지 않은 값이 포함되어 있습니다.');
|
||||||
}
|
}
|
||||||
|
|
||||||
while (($replace_url = preg_replace(array('/\/{2,}/', '/\\@/'), array('//', ''), urldecode($url))) != $url) {
|
// remove consecutive slashes
|
||||||
|
$patterns = ['/\/{2,}/', '/\\@/'];
|
||||||
|
$replacements = ['/', ''];
|
||||||
|
while (($replace_url = preg_replace($patterns, $replacements, urldecode($url))) != $url) {
|
||||||
$url = $replace_url;
|
$url = $replace_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
$p = @parse_url(trim($url));
|
$p = @parse_url(trim($url));
|
||||||
$host = preg_replace('/:[0-9]+$/', '', $_SERVER['HTTP_HOST']);
|
// ref: https://github.com/gnuboard/gnuboard5/issues/261
|
||||||
|
$host = preg_replace('/:[0-9]+$/', '', G5_DOMAIN ?: G5_HTTPS_DOMAIN ?: $_SERVER['HTTP_HOST']);
|
||||||
$is_host_check = false;
|
$is_host_check = false;
|
||||||
|
|
||||||
// url을 urlencode 를 2번이상하면 parse_url 에서 scheme와 host 값을 가져올수 없는 취약점이 존재함
|
// decode url if necessary
|
||||||
if ($is_redirect && !isset($p['host']) && urldecode($url) != $url) {
|
if ($is_redirect && !isset($p['host']) && urldecode($url) != $url) {
|
||||||
$i = 0;
|
$max_iterations = 3;
|
||||||
while ($i <= 3) {
|
for ($i = 0; $i <= $max_iterations; $i++) {
|
||||||
$url = urldecode($url);
|
$decoded = urldecode($url);
|
||||||
if (urldecode($url) == $url)
|
if ($decoded === $url)
|
||||||
break;
|
break;
|
||||||
$i++;
|
$url = $decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (urldecode($url) == $url) {
|
if (urldecode($url) == $url) {
|
||||||
|
|
@ -3323,22 +3327,19 @@ function check_url_host($url, $msg = '', $return_url = G5_URL, $is_redirect = fa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if(stripos($url, 'http:') !== false) {
|
// check host for redirect
|
||||||
// if(!isset($p['scheme']) || !$p['scheme'] || !isset($p['host']) || !$p['host'])
|
|
||||||
// alert('url 정보가 올바르지 않습니다.', $return_url);
|
|
||||||
// }
|
|
||||||
|
|
||||||
//php 5.6.29 이하 버전에서는 parse_url 버그가 존재함
|
|
||||||
//php 7.0.1 ~ 7.0.5 버전에서는 parse_url 버그가 존재함
|
|
||||||
if ($is_redirect && (isset($p['host']) && $p['host'])) {
|
if ($is_redirect && (isset($p['host']) && $p['host'])) {
|
||||||
$bool_ch = false;
|
$sensitive_parts = ['user', 'host'];
|
||||||
foreach (array('user', 'host') as $key) {
|
$has_sensitive_chars = false;
|
||||||
if (isset($p[$key]) && strpbrk($p[$key], ':/?#@')) {
|
foreach ($sensitive_parts as $part) {
|
||||||
$bool_ch = true;
|
if (isset($p[$part]) && strpbrk($p[$part], ':/?#@')) {
|
||||||
|
$has_sensitive_chars = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($bool_ch) {
|
|
||||||
$regex = '/https?\:\/\/' . $host . '/i';
|
if ($has_sensitive_chars) {
|
||||||
|
$regex = '/https?\:\/\/' . preg_quote($host, '/') . '/i';
|
||||||
if (!preg_match($regex, $url)) {
|
if (!preg_match($regex, $url)) {
|
||||||
$is_host_check = true;
|
$is_host_check = true;
|
||||||
}
|
}
|
||||||
|
|
@ -3346,16 +3347,15 @@ function check_url_host($url, $msg = '', $return_url = G5_URL, $is_redirect = fa
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((isset($p['scheme']) && $p['scheme']) || (isset($p['host']) && $p['host']) || $is_host_check) {
|
if ((isset($p['scheme']) && $p['scheme']) || (isset($p['host']) && $p['host']) || $is_host_check) {
|
||||||
//if ($p['host'].(isset($p['port']) ? ':'.$p['port'] : '') != $_SERVER['HTTP_HOST']) {
|
if (run_replace('check_same_url_host', ($p['host'] != $host) || $is_host_check, $p, $host, $is_host_check, $return_url, $is_redirect)) {
|
||||||
if (run_replace('check_same_url_host', (($p['host'] != $host) || $is_host_check), $p, $host, $is_host_check, $return_url, $is_redirect)) {
|
echo "<script>
|
||||||
echo '<script>' . PHP_EOL;
|
alert('url에 타 도메인을 지정할 수 없습니다.');
|
||||||
echo 'alert("url에 타 도메인을 지정할 수 없습니다.");' . PHP_EOL;
|
document.location.href = '{$return_url}';
|
||||||
echo 'document.location.href = "' . $return_url . '";' . PHP_EOL;
|
</script>
|
||||||
echo '</script>' . PHP_EOL;
|
<noscript>
|
||||||
echo '<noscript>' . PHP_EOL;
|
<p>{$msg}</p>
|
||||||
echo '<p>' . $msg . '</p>' . PHP_EOL;
|
<p><a href='{$return_url}'>돌아가기</a></p>
|
||||||
echo '<p><a href="' . $return_url . '">돌아가기</a></p>' . PHP_EOL;
|
</noscript>";
|
||||||
echo '</noscript>' . PHP_EOL;
|
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3365,9 +3365,7 @@ function check_url_host($url, $msg = '', $return_url = G5_URL, $is_redirect = fa
|
||||||
function clean_query_string($query, $amp = true)
|
function clean_query_string($query, $amp = true)
|
||||||
{
|
{
|
||||||
$qstr = trim($query);
|
$qstr = trim($query);
|
||||||
|
|
||||||
parse_str($qstr, $out);
|
parse_str($qstr, $out);
|
||||||
|
|
||||||
if (is_array($out)) {
|
if (is_array($out)) {
|
||||||
$q = [];
|
$q = [];
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue