beego中文件路径参数必须做白名单校验,因getfile、savetofile等操作若直接使用未校验的用户输入(如filename),易遭../路径遍历攻击;静态资源需用beego.beforestatic拦截,xsrf对此无效。

Beego 中文件路径参数必须做白名单校验
任意文件下载漏洞在 Beego 里最常出现在 GetFile、SaveToFile 或手动拼接路径读取文件的逻辑中。只要用户输入(如 fileName、path)未经校验就直接参与 os.Open、os.Stat 或 io.ReadFile,就极可能被 ../ 绕过。Beego 不会自动拦截这类路径遍历,它只管路由和渲染,不干涉你读什么文件。
正确做法是:对所有可控路径参数强制走白名单校验,而非简单过滤 ../ —— 因为编码绕过(%2e%2e%2f)、双写(....//)、空字节截断等手法很容易击穿黑名单。
- 用
filepath.Clean()规范化路径后,再检查是否以允许目录为前缀(例如/var/www/uploads/) - 禁止使用
strings.Contains(fileName, "..")这类松散判断;应使用filepath.Rel(allowedBase, fullPath)确保结果不包含.. - 若参数本该是纯文件名(不含路径),就直接拒绝任何含
/、\、..的输入
静态资源访问必须用 beego.BeforeStatic 拦截
很多人误以为在 beego.BeforeRouter 里加权限检查就能保护 /static/ 下的文件,但 Beego 对静态资源请求是绕过整个路由系统的 —— 它由独立的静态文件处理器直出响应,BeforeRouter、BeforeExec 全部失效。
如果你有类似 /static/users/123/private/report.pdf 这种需鉴权的私有静态资源,唯一可靠入口是 beego.BeforeStatic:
- 注册时路径要带正则,例如
/static/users/:id([0-9]+)/private/*,避免宽泛匹配 - 在过滤器函数里必须显式调用
sess, _ := beego.GlobalSessions.SessionStart(...)获取会话,不能依赖控制器上下文 - 校验失败时调用
ctx.Abort()并返回403,不要只写日志或跳转
SaveToFile 和临时文件清理必须配对使用
Beego 的 SaveToFile 本身不校验路径安全性,且生成的文件默认留在磁盘上,既可能被重复下载,也可能堆积占满空间。尤其当文件名来自用户输入时,攻击者可构造 ../../../etc/passwd 直接覆盖系统文件(如果进程有权限)。
安全写法要同时满足三点:
- 保存前对目标路径做白名单约束,例如只允许保存到
./tmp/uploads/下的子目录 - 用
filepath.Join(baseDir, safeName)拼接,禁用用户传入的完整路径 - 下载完成后必须触发清理:用
os.Remove()删除临时文件,或更稳妥地用os.RemoveAll()清空单次会话专属子目录;注意不要在defer里删 —— HTTP 响应结束 ≠ 客户端下载完成
XSRF 机制对文件下载无防护作用
Beego 的 EnableXSRF = true 只影响 POST/PUT/DELETE 请求体中的 _xsrf 校验,而文件下载几乎全是 GET 请求(如 ?file=xxx)。开启 XSRF 后,你依然能用浏览器直接打开恶意链接触发下载,它完全不拦。
这意味着:XSRF 是防 CSRF 的,不是防路径遍历的。混淆这两者会导致严重误判。
真正关键的是路径校验 + 静态资源拦截 + 临时文件生命周期管理 —— 这三处任何一个疏漏,都可能让一个简单的下载接口变成服务器的后门。











