Signed-off-by: Daniel <845765@qq.com>
This commit is contained in:
Daniel 2026-01-28 21:24:36 +08:00
parent 7c9acda465
commit 399a38893e
No known key found for this signature in database
GPG key ID: 86211BA83DF03017

View file

@ -24,7 +24,9 @@ import (
"net/http"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"time"
"github.com/88250/gulu"
@ -225,8 +227,12 @@ func getFile(c *gin.Context) {
}
func refuseToAccess(c *gin.Context, fileAbsPath string, ret *gulu.Result) bool {
// 规范化并解析符号链接,防止通过大小写或符号链接绕过
fileNorm := normalizeAndResolve(fileAbsPath)
// 禁止访问配置文件 conf/conf.json
if filepath.Join(util.ConfDir, "conf.json") == fileAbsPath {
confPath := normalizeAndResolve(filepath.Join(util.ConfDir, "conf.json"))
if fileNorm == confPath {
ret.Code = http.StatusForbidden
ret.Msg = http.StatusText(http.StatusForbidden)
c.JSON(http.StatusAccepted, ret)
@ -234,7 +240,8 @@ func refuseToAccess(c *gin.Context, fileAbsPath string, ret *gulu.Result) bool {
}
// 禁止访问 data/snippets/conf.json
if filepath.Join(util.DataDir, "snippets", "conf.json") == fileAbsPath {
snippetPath := normalizeAndResolve(filepath.Join(util.DataDir, "snippets", "conf.json"))
if fileNorm == snippetPath {
ret.Code = http.StatusForbidden
ret.Msg = http.StatusText(http.StatusForbidden)
c.JSON(http.StatusAccepted, ret)
@ -242,7 +249,8 @@ func refuseToAccess(c *gin.Context, fileAbsPath string, ret *gulu.Result) bool {
}
// 禁止访问 data/templates 目录
if util.IsSubPath(filepath.Join(util.DataDir, "templates"), fileAbsPath) {
templatesBase := normalizeAndResolve(filepath.Join(util.DataDir, "templates"))
if util.IsSubPath(templatesBase, fileNorm) {
ret.Code = http.StatusForbidden
ret.Msg = http.StatusText(http.StatusForbidden)
c.JSON(http.StatusAccepted, ret)
@ -251,6 +259,22 @@ func refuseToAccess(c *gin.Context, fileAbsPath string, ret *gulu.Result) bool {
return false
}
// normalizeAndResolve 将路径转为绝对、解析符号链接并清理;在需要时转为小写以实现不区分大小写比较
func normalizeAndResolve(p string) string {
if abs, err := filepath.Abs(p); err == nil {
p = abs
}
if eval, err := filepath.EvalSymlinks(p); err == nil {
p = eval
}
p = filepath.Clean(p)
// 在 Windows 和 macOS 上文件系统通常为不区分大小写,使用小写统一比较
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
p = strings.ToLower(p)
}
return p
}
func readDir(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)