diff --git a/application/admin/command/Api.php b/application/admin/command/Api.php index d9d79c4e..d8098414 100644 --- a/application/admin/command/Api.php +++ b/application/admin/command/Api.php @@ -163,7 +163,7 @@ class Api extends Command if ($getting_namespace === true) { //If the token is a string or the namespace separator... - if (is_array($token) && in_array($token[0], [T_STRING, T_NS_SEPARATOR])) { + if (is_array($token) && in_array($token[0], version_compare(PHP_VERSION, '8.0.0', '<') ? [T_STRING, T_NS_SEPARATOR] : [T_NAME_QUALIFIED])) { //Append the token's value to the name of the namespace $namespace .= $token[1]; diff --git a/application/admin/common.php b/application/admin/common.php index c9db617f..2622b4ac 100755 --- a/application/admin/common.php +++ b/application/admin/common.php @@ -18,8 +18,8 @@ if (!function_exists('build_select')) { */ function build_select($name, $options, $selected = [], $attr = []) { - $options = is_array($options) ? $options : explode(',', $options); - $selected = is_array($selected) ? $selected : explode(',', $selected); + $options = is_array($options) ? $options : explode(',', $options ?? ''); + $selected = is_array($selected) ? $selected : explode(',', $selected ?? ''); return Form::select($name, $options, $selected, $attr); } } diff --git a/application/admin/controller/Addon.php b/application/admin/controller/Addon.php index 8d11cf4a..355ddab6 100644 --- a/application/admin/controller/Addon.php +++ b/application/admin/controller/Addon.php @@ -319,9 +319,8 @@ class Addon extends Backend { $offset = (int)$this->request->get("offset"); $limit = (int)$this->request->get("limit"); - $filter = $this->request->get("filter"); - $search = $this->request->get("search"); - $search = htmlspecialchars(strip_tags($search)); + $filter = $this->request->get("filter", ''); + $search = $this->request->get("search", '', 'strip_tags,htmlspecialchars'); $onlineaddons = $this->getAddonList(); $filter = (array)json_decode($filter, true); $addons = get_addon_list(); diff --git a/application/admin/controller/Index.php b/application/admin/controller/Index.php index 7a6a6a4a..c387bf82 100644 --- a/application/admin/controller/Index.php +++ b/application/admin/controller/Index.php @@ -66,7 +66,7 @@ class Index extends Backend */ public function login() { - $url = $this->request->get('url', 'index/index'); + $url = $this->request->get('url', 'index/index', 'url_clean'); if ($this->auth->isLogin()) { $this->success(__("You've logged in, do not login again"), $url); } diff --git a/application/common.php b/application/common.php index 68b9e582..b7359b81 100755 --- a/application/common.php +++ b/application/common.php @@ -11,7 +11,7 @@ if (!function_exists('__')) { /** * 获取语言变量值 * @param string $name 语言变量名 - * @param array $vars 动态变量值 + * @param string | array $vars 动态变量值 * @param string $lang 语言 * @return mixed */ @@ -41,7 +41,7 @@ if (!function_exists('format_bytes')) { function format_bytes($size, $delimiter = '', $precision = 2) { $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB'); - for ($i = 0; $size >= 1024 && $i < 6; $i++) { + for ($i = 0; $size >= 1024 && $i < 5; $i++) { $size /= 1024; } return round($size, $precision) . $delimiter . $units[$i]; @@ -467,6 +467,19 @@ if (!function_exists('xss_clean')) { } } +if (!function_exists('url_clean')) { + /** + * 清理URL + */ + function url_clean($url) + { + if (!check_url_allowed($url)) { + return ''; + } + return xss_clean($url); + } +} + if (!function_exists('check_ip_allowed')) { /** * 检测IP是否允许 @@ -485,6 +498,36 @@ if (!function_exists('check_ip_allowed')) { } } +if (!function_exists('check_url_allowed')) { + /** + * 检测URL是否允许 + * @param string $url URL + * @return bool + */ + function check_url_allowed($url = null) + { + //允许的主机列表 + $allowedHostArr = [ + strtolower(request()->host()) + ]; + + //如果是站内相对链接则允许 + if (preg_match("/^[\/a-z][a-z0-9][a-z0-9\.\/]+\$/i", $url) && substr($url, 0, 2) !== '//') { + return true; + } + + //如果是站外链接则需要判断HOST是否允许 + if (preg_match("/((http[s]?:\/\/)+(?>[a-z\-0-9]{2,}\.){1,}[a-z]{2,8})(?:\s|\/)/i", $url)) { + + if (in_array(strtolower(parse_url($url, PHP_URL_HOST)), $allowedHostArr)) { + return true; + } + } + + return false; + } +} + if (!function_exists('build_suffix_image')) { /** * 生成文件后缀图片 diff --git a/application/common/behavior/Common.php b/application/common/behavior/Common.php index af9e1cfe..369adb3d 100644 --- a/application/common/behavior/Common.php +++ b/application/common/behavior/Common.php @@ -63,7 +63,7 @@ class Common } // 切换多语言 if (Config::get('lang_switch_on')) { - $lang = $request->get('lang'); + $lang = $request->get('lang', ''); if (preg_match("/^([a-zA-Z\-_]{2,10})\$/i", $lang)) { \think\Cookie::set('think_var', $lang); } diff --git a/application/index/controller/User.php b/application/index/controller/User.php index a785fa04..ebceecbe 100644 --- a/application/index/controller/User.php +++ b/application/index/controller/User.php @@ -129,9 +129,8 @@ class User extends Frontend } } //判断来源 - $referer = $this->request->server('HTTP_REFERER'); - if (!$url && (strtolower(parse_url($referer, PHP_URL_HOST)) == strtolower($this->request->host())) - && !preg_match("/(user\/login|user\/register|user\/logout)/i", $referer)) { + $referer = $this->request->server('HTTP_REFERER', '', 'url_clean'); + if (!$url && $referer && !preg_match("/(user\/login|user\/register|user\/logout)/i", $referer)) { $url = $referer; } $this->view->assign('captchaType', config('fastadmin.user_register_captcha')); @@ -147,7 +146,7 @@ class User extends Frontend { $url = $this->request->request('url', '', 'trim,xss_clean'); if ($this->auth->id) { - $this->success(__('You\'ve logged in, do not login again'), $url ? $url : url('user/index')); + $this->success(__('You\'ve logged in, do not login again'), $url ?: url('user/index')); } if ($this->request->isPost()) { $account = $this->request->post('account'); @@ -175,7 +174,6 @@ class User extends Frontend $result = $validate->check($data); if (!$result) { $this->error(__($validate->getError()), null, ['token' => $this->request->token()]); - return false; } if ($this->auth->login($account, $password)) { $this->success(__('Logged in successful'), $url ? $url : url('user/index')); @@ -184,9 +182,8 @@ class User extends Frontend } } //判断来源 - $referer = $this->request->server('HTTP_REFERER'); - if (!$url && (strtolower(parse_url($referer, PHP_URL_HOST)) == strtolower($this->request->host())) - && !preg_match("/(user\/login|user\/register|user\/logout)/i", $referer)) { + $referer = $this->request->server('HTTP_REFERER', '', 'url_clean'); + if (!$url && $referer && !preg_match("/(user\/login|user\/register|user\/logout)/i", $referer)) { $url = $referer; } $this->view->assign('url', $url); diff --git a/composer.json b/composer.json index 9ea4c30e..1108d7f4 100755 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "require": { "php": ">=7.2.0", "topthink/framework": "dev-master", - "topthink/think-captcha": "^1.0", + "topthink/think-captcha": "^1.0.9", "topthink/think-installer": "^1.0.14", "topthink/think-queue": "1.1.6", "topthink/think-helper": "^1.0.7", @@ -38,6 +38,10 @@ { "type": "git", "url": "https://gitee.com/fastadminnet/framework.git" + }, + { + "type": "git", + "url": "https://gitee.com/fastadminnet/think-captcha.git" } ] }