diff --git a/crmeb/app/adminapi/controller/v1/setting/SystemConfig.php b/crmeb/app/adminapi/controller/v1/setting/SystemConfig.php index 3184ec3ad..e0bfe7031 100644 --- a/crmeb/app/adminapi/controller/v1/setting/SystemConfig.php +++ b/crmeb/app/adminapi/controller/v1/setting/SystemConfig.php @@ -110,7 +110,7 @@ class SystemConfig extends AuthController if (is_array($data['config_tab_id'])) $data['config_tab_id'] = end($data['config_tab_id']); if (!$data['info']) return app('json')->fail('请输入配置名称'); if (!$data['menu_name']) return app('json')->fail('请输入字段名称'); - // if (!$data['desc']) return app('json')->fail('请输入配置简介'); + if (!$data['desc']) return app('json')->fail('请输入配置简介'); if ($data['sort'] < 0) { $data['sort'] = 0; } @@ -294,7 +294,7 @@ class SystemConfig extends AuthController * @param $status * @return mixed */ - public function setStatus($id, $status) + public function set_status($id, $status) { if ($status == '' || $id == 0) { return app('json')->fail('参数错误'); @@ -307,7 +307,7 @@ class SystemConfig extends AuthController /** * 基础配置 * */ - public function editBasics(Request $request) + public function edit_basics(Request $request) { $tabId = $this->request->param('tab_id', 1); if (!$tabId) { @@ -320,7 +320,7 @@ class SystemConfig extends AuthController /** * 保存数据 true * */ - public function saveBasics(Request $request) + public function save_basics(Request $request) { $post = $this->request->post(); foreach ($post as $k => $v) { @@ -461,13 +461,6 @@ class SystemConfig extends AuthController return app('json')->success('修改成功'); } if (isset($post['param_filter_data'])) { - $rules = preg_split('/\r\n|\r|\n/', $post['param_filter_data'], -1, PREG_SPLIT_NO_EMPTY); - foreach ($rules as $rule) { - $rule = trim($rule); - if ($rule !== '' && @preg_match($rule, '') === false) { - return app('json')->fail('WAF配置规则格式错误:' . $rule); - } - } $post['param_filter_data'] = base64_encode($post['param_filter_data']); } if (isset($post['product_type_config'])) { @@ -562,7 +555,7 @@ class SystemConfig extends AuthController * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ - public function headerBasics(SystemConfigTabServices $services) + public function header_basics(SystemConfigTabServices $services) { [$type, $pid] = $this->request->getMore([ [['type', 'd'], 0], @@ -582,7 +575,7 @@ class SystemConfig extends AuthController * @param $name * @return mixed */ - public function getSystem($name) + public function get_system($name) { $value = sys_config($name); return app('json')->success(compact('value')); @@ -593,7 +586,7 @@ class SystemConfig extends AuthController * @param $tabId * @return mixed */ - public function getConfigList($tabId) + public function get_config_list($tabId) { $list = $this->services->getReadList($tabId); $data = []; diff --git a/crmeb/app/common.php b/crmeb/app/common.php index 62f8976a7..9c0fc9e10 100644 --- a/crmeb/app/common.php +++ b/crmeb/app/common.php @@ -614,10 +614,31 @@ if (!function_exists('put_image')) { $filename = time() . "." . $ext; } + // SSRF 防护:验证 URL 安全性 + $urlParts = parse_url($url); + if (!$urlParts || !isset($urlParts['scheme']) || !in_array($urlParts['scheme'], ['http', 'https'])) { + return false; + } + $host = $urlParts['host'] ?? ''; + if (!$host) { + return false; + } + // 阻止访问内网地址和私有 IP + $ip = gethostbyname($host); + if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) { + return false; + } + // 保存文件到指定目录 $imgData = file_get_contents($url); + if ($imgData === false) { + return false; + } $pattern = '/<\?php(.*?)\?>/s'; $imgData = preg_replace($pattern, '', $imgData); + // 额外过滤短标签 + $imgData = preg_replace('/<\?=(.*?)\?>/s', '', $imgData); + $imgData = preg_replace('/<\?[\s](.*?)\?>/s', '', $imgData); if ($imgData !== false) { $path = 'uploads' . DS . 'qrcode' . DS . $filename; if (file_put_contents($path, $imgData) !== false) { @@ -670,23 +691,9 @@ if (!function_exists('filter_str')) { */ function filter_str($str) { - $param_filter_type = (int)sys_config('param_filter_type'); + $param_filter_type = sys_config('param_filter_type'); if ($param_filter_type != 0) { - $ruleData = base64_decode((string)sys_config('param_filter_data'), true); - $rules = preg_split('/\r\n|\r|\n/', $ruleData === false ? '' : $ruleData, -1, PREG_SPLIT_NO_EMPTY); - $rules = array_values(array_filter(array_map('trim', $rules), function ($rule) { - return $rule !== '' && @preg_match($rule, '') !== false; - })); - if (!$rules) return $str; - - $str = (string)$str; - if (preg_match('/^\s*([a-z][a-z0-9+.-]*):/i', $str, $matches)) { - $dangerSchemes = ['gopher', 'doc', 'php', 'glob', 'file', 'phar', 'zlib', 'zlib_filter', 'ftp', 'ldap', 'dict', 'ogg', 'data', 'javascript', 'vbscript']; - if (in_array(strtolower($matches[1]), $dangerSchemes, true)) { - throw new \Exception('接口请求失败:非法操作!'); - } - } - + $rules = preg_split('/\r\n|\r|\n/', base64_decode(sys_config('param_filter_data'))); if ($param_filter_type == 1) { foreach ($rules as $item) { if (preg_match($item, $str)) { @@ -694,8 +701,14 @@ if (!function_exists('filter_str')) { } } } - $filterStr = preg_replace($rules, '', $str); - $str = $filterStr === null ? $str : $filterStr; + if (filter_var($str, FILTER_VALIDATE_URL)) { + $url = parse_url($str); + if (!isset($url['scheme'])) return $str; + $host = $url['scheme'] . '://' . $url['host']; + $str = $host . preg_replace($rules, '', str_replace($host, '', $str)); + } else { + $str = preg_replace($rules, '', $str); + } } return $str; }