From 6bfe152681a8a0bf7670f63a43ecdc9d731805b6 Mon Sep 17 00:00:00 2001 From: Arcturus Date: Sun, 22 Sep 2024 10:16:54 +0900 Subject: [PATCH] patch secure: https://github.com/gnuboard/gnuboard5/commit/764cb349575e4a9d7d8e0bc43eaa918cfaed70e4 --- .../adm/contentformupdate.php | 54 +++++++++-- AvocadoEdition_Light/bbs/content.php | 7 +- AvocadoEdition_Light/lib/common.lib.php | 94 +++++++++++++++---- 3 files changed, 124 insertions(+), 31 deletions(-) diff --git a/AvocadoEdition_Light/adm/contentformupdate.php b/AvocadoEdition_Light/adm/contentformupdate.php index aca5754..d1e4c13 100644 --- a/AvocadoEdition_Light/adm/contentformupdate.php +++ b/AvocadoEdition_Light/adm/contentformupdate.php @@ -1,6 +1,6 @@ 관리자 모드에서 게시판관리->내용 관리를 먼저 확인해 주세요.'); } - - // 내용 $sql = " select * from {$g5['content_table']} where co_id = '$co_id' "; $co = sql_fetch($sql); @@ -18,10 +16,11 @@ $g5['title'] = $co['co_subject']; if (is_include_path_check($co['co_include_head'])) - @include_once($co['co_include_head']); + @include_once $co['co_include_head']; else - include_once('./_head.php'); + include_once './_head.php'; +$co['co_tag_filter_use'] = 1; $str = conv_content($co['co_content'], $co['co_html'], $co['co_tag_filter_use']); // $src 를 $dst 로 변환 diff --git a/AvocadoEdition_Light/lib/common.lib.php b/AvocadoEdition_Light/lib/common.lib.php index 2f9b93c..4f80a40 100644 --- a/AvocadoEdition_Light/lib/common.lib.php +++ b/AvocadoEdition_Light/lib/common.lib.php @@ -24,7 +24,8 @@ function get_microtime() // 한페이지에 보여줄 행, 현재페이지, 총페이지수, URL function get_paging($write_pages, $cur_page, $total_page, $url, $add = "") { - if (!$write_pages) $write_pages = 5; + if (!$write_pages) + $write_pages = 5; $url = preg_replace('#&page=[0-9]*#', '', $url) . '&page='; $str = ''; @@ -36,8 +37,9 @@ function get_paging($write_pages, $cur_page, $total_page, $url, $add = "") $start_page = (((int) (($cur_page - 1) / $write_pages)) * $write_pages) + 1; $end_page = $start_page + $write_pages - 1; - if ($end_page >= $total_page) $end_page = $total_page; - + if ($end_page >= $total_page) + $end_page = $total_page; + if ($start_page > 1) $str .= 'navigate_before' . PHP_EOL; @@ -1515,7 +1517,7 @@ function sql_query($sql, $error = G5_DISPLAY_SQL_ERROR, $link = null) if (preg_match("#^desc(?:ribe)?\s+(.*)#i", $sql)) { $sql = preg_replace_callback("#^desc(?:ribe)?\s+(.*)#i", '_callback_sql_show_tables', trim($sql)); } - + if (function_exists('mysqli_query') && G5_MYSQLI_USE) { if ($error) { $result = @mysqli_query($link, $sql) or die("

$sql

" . mysqli_errno($link) . " : " . mysqli_error($link) . "

error file : {$_SERVER['SCRIPT_NAME']}"); @@ -3406,24 +3408,80 @@ function get_write_token($bo_table) // POST로 넘어온 토큰과 세션에 저장된 토큰 비교 function check_write_token($bo_table) { - /*if(!$bo_table) - alert('올바른 방법으로 이용해 주십시오.', G5_URL); - - $token = get_session('ss_write_'.$bo_table.'_token'); - set_session('ss_write_'.$bo_table.'_token', ''); - - if(!$token || !$_REQUEST['token'] || $token != $_REQUEST['token']) { - alert('올바른 방법으로 이용해 주십시오.', G5_URL); - }*/ - + return true; } -// include 하는 경로에 data file 경로가 포함되어 있는지 체크합니다. -function is_include_path_check($path = '') +// include 하는 경로에 data file 경로나 안전하지 않은 경로가 있는지 체크합니다. +function is_include_path_check($path = '', $is_input = '') { - if (!$path || preg_match('/\/data\/(file|editor)\/[A-Za-z0-9_]{1,20}\//', $path)) { - return false; + if ($path) { + if ($is_input) { + // 장태진 @jtjisgod 추가 + // 보안 목적 : rar wrapper 차단 + + if (stripos($path, 'rar:') !== false || stripos($path, 'php:') !== false || stripos($path, 'zlib:') !== false || stripos($path, 'bzip2:') !== false || stripos($path, 'zip:') !== false || stripos($path, 'data:') !== false || stripos($path, 'phar:') !== false) { + return false; + } + + $replace_path = str_replace('\\', '/', $path); + $slash_count = substr_count(str_replace('\\', '/', $_SERVER['SCRIPT_NAME']), '/'); + $peer_count = substr_count($replace_path, '../'); + + if ($peer_count && $peer_count > $slash_count) { + return false; + } + + try { + // whether $path is unix or not + $unipath = strlen($path) == 0 || $path[0] != '/'; + $unc = substr($path, 0, 2) == '\\\\' ? true : false; + // attempts to detect if path is relative in which case, add cwd + if (strpos($path, ':') === false && $unipath && !$unc) { + $path = getcwd() . DIRECTORY_SEPARATOR . $path; + if ($path[0] == '/') { + $unipath = false; + } + } + + // resolve path parts (single dot, double dot and double delimiters) + $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path); + $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen'); + $absolutes = array(); + foreach ($parts as $part) { + if ('.' == $part) { + continue; + } + if ('..' == $part) { + array_pop($absolutes); + } else { + $absolutes[] = $part; + } + } + $path = implode(DIRECTORY_SEPARATOR, $absolutes); + // resolve any symlinks + // put initial separator that could have been lost + $path = !$unipath ? '/' . $path : $path; + $path = $unc ? '\\\\' . $path : $path; + } catch (Exception $e) { + //echo 'Caught exception: ', $e->getMessage(), "\n"; + return false; + } + + if (preg_match('/\/data\/(file|editor|qa|cache|member|member_image|session|tmp)\/[A-Za-z0-9_]{1,20}\//i', $replace_path)) { + return false; + } + if ((preg_match('/\.\.\//i', $replace_path) || preg_match('/^\/.*/i', $replace_path)) && preg_match('/plugin\//i', $replace_path) && preg_match('/okname\//i', $replace_path)) { + return false; + } + } + + $extension = pathinfo($path, PATHINFO_EXTENSION); + + if ($extension && preg_match('/(jpg|jpeg|png|gif|bmp|conf)$/i', $extension)) { + return false; + } } + return true; }