Laravel 8调用exec执行shell命令时用户输入URL格式化错误如何解决
问题核心原因
你当前的格式化逻辑存在3处核心问题:
- 多余调用了
htmlspecialchars():该函数用于转义输出到HTML页面的特殊字符,完全不适合处理要传入shell命令的域名/IP参数,不会提升命令执行安全性,反而可能篡改合法的域名/IP内容 - 字符串替换顺序不合理:将
https://、http://和单独的https、http放在同一个替换数组中,可能出现前缀匹配错误,比如https.example.com会被错误截断为.example.com - 缺少合法校验:没有对处理后的内容做域名/IP合法性校验,无法过滤无效输入和恶意内容
修正方案
1. 调整格式化函数逻辑,新增合法性校验
protected function formatTracerouteUrl($input) { // 先移除所有不可见控制字符、全角/半角空白字符 $formatted = preg_replace('/[[:cntrl:]\s]/u', '', $input); // 优先移除完整协议前缀和www前缀 $formatted = str_ireplace(['https://', 'http://', 'www.'], '', $formatted); // 移除末尾的路径斜杠 $formatted = rtrim($formatted, '/'); // 提取纯域名/IP部分(如果输入还带路径、参数等后缀) if (str_contains($formatted, '/')) { $formatted = strtok($formatted, '/'); } $formatted = trim($formatted); // 合法性校验:仅允许合法IP或域名通过 $isValidIp = filter_var($formatted, FILTER_VALIDATE_IP); $isValidDomain = filter_var($formatted, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME); if (!$isValidIp && !$isValidDomain) { throw new \InvalidArgumentException('传入的域名/IP格式不合法'); } return $formatted; }
2. 命令执行逻辑保留escapeshellarg即可
try { $target = $this->formatTracerouteUrl($request->input('url')); exec('mtr --json --max-time 30 ' . escapeshellarg($target), $out, $code); // 后续处理返回结果 } catch (\InvalidArgumentException $e) { // 参数错误返回对应提示 return response()->json(['msg' => $e->getMessage()], 400); }
补充说明
你遇到的报错ping request could not find host domain-monitor.io .就是因为原逻辑没有清理输入中的不可见字符,或多余的转义逻辑在域名末尾增加了异常字符,修正后的逻辑已经增加了全局控制字符、空白字符清理,可解决该问题。
内容的提问来源于stack exchange,提问作者Ryan H
相关产品推荐
相关产品推荐

