fix: 解决部分接口命令注入问题 (#1690)

This commit is contained in:
ssongliu 2023-07-17 16:34:29 +08:00 committed by GitHub
parent 1d6f1b0ef3
commit e17b80cff4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 58 additions and 7 deletions

View file

@ -18,6 +18,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/buserr" "github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/common" "github.com/1Panel-dev/1Panel/backend/utils/common"
"github.com/1Panel-dev/1Panel/backend/utils/docker" "github.com/1Panel-dev/1Panel/backend/utils/docker"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
@ -552,6 +553,9 @@ func (u *ContainerService) ContainerLogClean(req dto.OperationWithName) error {
} }
func (u *ContainerService) ContainerLogs(wsConn *websocket.Conn, container, since, tail string, follow bool) error { func (u *ContainerService) ContainerLogs(wsConn *websocket.Conn, container, since, tail string, follow bool) error {
if cmd.CheckIllegal(container, since, tail) {
return buserr.New(constant.ErrCmdIllegal)
}
command := fmt.Sprintf("docker logs %s", container) command := fmt.Sprintf("docker logs %s", container)
if tail != "0" { if tail != "0" {
command += " -n " + tail command += " -n " + tail

View file

@ -14,8 +14,10 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/app/model" "github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/compose" "github.com/1Panel-dev/1Panel/backend/utils/compose"
"github.com/1Panel-dev/1Panel/backend/utils/docker" "github.com/1Panel-dev/1Panel/backend/utils/docker"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
@ -127,6 +129,9 @@ func (u *ContainerService) PageCompose(req dto.SearchWithPage) (int64, interface
} }
func (u *ContainerService) TestCompose(req dto.ComposeCreate) (bool, error) { func (u *ContainerService) TestCompose(req dto.ComposeCreate) (bool, error) {
if cmd.CheckIllegal(req.Path) {
return false, buserr.New(constant.ErrCmdIllegal)
}
composeItem, _ := composeRepo.GetRecord(commonRepo.WithByName(req.Name)) composeItem, _ := composeRepo.GetRecord(commonRepo.WithByName(req.Name))
if composeItem.ID != 0 { if composeItem.ID != 0 {
return false, constant.ErrRecordExist return false, constant.ErrRecordExist
@ -143,6 +148,9 @@ func (u *ContainerService) TestCompose(req dto.ComposeCreate) (bool, error) {
} }
func (u *ContainerService) CreateCompose(req dto.ComposeCreate) (string, error) { func (u *ContainerService) CreateCompose(req dto.ComposeCreate) (string, error) {
if cmd.CheckIllegal(req.Name, req.Path) {
return "", buserr.New(constant.ErrCmdIllegal)
}
if err := u.loadPath(&req); err != nil { if err := u.loadPath(&req); err != nil {
return "", err return "", err
} }
@ -177,6 +185,9 @@ func (u *ContainerService) CreateCompose(req dto.ComposeCreate) (string, error)
} }
func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error { func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error {
if cmd.CheckIllegal(req.Path, req.Operation) {
return buserr.New(constant.ErrCmdIllegal)
}
if _, err := os.Stat(req.Path); err != nil { if _, err := os.Stat(req.Path); err != nil {
return fmt.Errorf("load file with path %s failed, %v", req.Path, err) return fmt.Errorf("load file with path %s failed, %v", req.Path, err)
} }
@ -195,6 +206,9 @@ func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error {
} }
func (u *ContainerService) ComposeUpdate(req dto.ComposeUpdate) error { func (u *ContainerService) ComposeUpdate(req dto.ComposeUpdate) error {
if cmd.CheckIllegal(req.Name, req.Path) {
return buserr.New(constant.ErrCmdIllegal)
}
if _, err := os.Stat(req.Path); err != nil { if _, err := os.Stat(req.Path); err != nil {
return fmt.Errorf("load file with path %s failed, %v", req.Path, err) return fmt.Errorf("load file with path %s failed, %v", req.Path, err)
} }

View file

@ -17,6 +17,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/buserr" "github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/common" "github.com/1Panel-dev/1Panel/backend/utils/common"
"github.com/1Panel-dev/1Panel/backend/utils/compose" "github.com/1Panel-dev/1Panel/backend/utils/compose"
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
@ -77,6 +78,10 @@ var formatMap = map[string]string{
} }
func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*model.DatabaseMysql, error) { func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*model.DatabaseMysql, error) {
if cmd.CheckIllegal(req.Name, req.Username, req.Password, req.Format, req.Permission) {
return nil, buserr.New(constant.ErrCmdIllegal)
}
if req.Username == "root" { if req.Username == "root" {
return nil, errors.New("Cannot set root as user name") return nil, errors.New("Cannot set root as user name")
} }
@ -184,6 +189,10 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error
} }
func (u *MysqlService) ChangePassword(info dto.ChangeDBInfo) error { func (u *MysqlService) ChangePassword(info dto.ChangeDBInfo) error {
if cmd.CheckIllegal(info.Value) {
return buserr.New(constant.ErrCmdIllegal)
}
var ( var (
mysql model.DatabaseMysql mysql model.DatabaseMysql
err error err error
@ -253,6 +262,9 @@ func (u *MysqlService) ChangePassword(info dto.ChangeDBInfo) error {
} }
func (u *MysqlService) ChangeAccess(info dto.ChangeDBInfo) error { func (u *MysqlService) ChangeAccess(info dto.ChangeDBInfo) error {
if cmd.CheckIllegal(info.Value) {
return buserr.New(constant.ErrCmdIllegal)
}
var ( var (
mysql model.DatabaseMysql mysql model.DatabaseMysql
err error err error

View file

@ -304,7 +304,6 @@ func OperateFirewallPort(oldPorts, newPorts []int) error {
return err return err
} }
for _, port := range newPorts { for _, port := range newPorts {
if err := client.Port(fireClient.FireInfo{Port: strconv.Itoa(port), Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { if err := client.Port(fireClient.FireInfo{Port: strconv.Itoa(port), Protocol: "tcp", Strategy: "accept"}, "add"); err != nil {
return err return err
} }

View file

@ -79,7 +79,7 @@ func (u *ImageRepoService) List() ([]dto.ImageRepoOption, error) {
func (u *ImageRepoService) Create(req dto.ImageRepoCreate) error { func (u *ImageRepoService) Create(req dto.ImageRepoCreate) error {
if cmd.CheckIllegal(req.Username, req.Password, req.DownloadUrl) { if cmd.CheckIllegal(req.Username, req.Password, req.DownloadUrl) {
return buserr.New(constant.ErrRepoConn) return buserr.New(constant.ErrCmdIllegal)
} }
imageRepo, _ := imageRepoRepo.Get(commonRepo.WithByName(req.Name)) imageRepo, _ := imageRepoRepo.Get(commonRepo.WithByName(req.Name))
if imageRepo.ID != 0 { if imageRepo.ID != 0 {
@ -148,7 +148,7 @@ func (u *ImageRepoService) Update(req dto.ImageRepoUpdate) error {
return errors.New("The default value cannot be deleted !") return errors.New("The default value cannot be deleted !")
} }
if cmd.CheckIllegal(req.Username, req.Password, req.DownloadUrl) { if cmd.CheckIllegal(req.Username, req.Password, req.DownloadUrl) {
return buserr.New(constant.ErrRepoConn) return buserr.New(constant.ErrCmdIllegal)
} }
repo, err := imageRepoRepo.Get(commonRepo.WithByID(req.ID)) repo, err := imageRepoRepo.Get(commonRepo.WithByID(req.ID))
if err != nil { if err != nil {

View file

@ -11,6 +11,7 @@ import (
"time" "time"
"github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/cmd" "github.com/1Panel-dev/1Panel/backend/utils/cmd"
@ -146,6 +147,9 @@ func (u *SSHService) UpdateByFile(value string) error {
} }
func (u *SSHService) GenerateSSH(req dto.GenerateSSH) error { func (u *SSHService) GenerateSSH(req dto.GenerateSSH) error {
if cmd.CheckIllegal(req.EncryptionMode, req.Password) {
return buserr.New(constant.ErrCmdIllegal)
}
currentUser, err := user.Current() currentUser, err := user.Current()
if err != nil { if err != nil {
return fmt.Errorf("load current user failed, err: %v", err) return fmt.Errorf("load current user failed, err: %v", err)

View file

@ -42,6 +42,7 @@ var (
ErrTypePasswordExpired = "ErrPasswordExpired" ErrTypePasswordExpired = "ErrPasswordExpired"
ErrNameIsExist = "ErrNameIsExist" ErrNameIsExist = "ErrNameIsExist"
ErrDemoEnvironment = "ErrDemoEnvironment" ErrDemoEnvironment = "ErrDemoEnvironment"
ErrCmdIllegal = "ErrCmdIllegal"
) )
// app // app
@ -107,7 +108,6 @@ var (
ErrInUsed = "ErrInUsed" ErrInUsed = "ErrInUsed"
ErrObjectInUsed = "ErrObjectInUsed" ErrObjectInUsed = "ErrObjectInUsed"
ErrPortRules = "ErrPortRules" ErrPortRules = "ErrPortRules"
ErrRepoConn = "ErrRepoConn"
) )
// runtime // runtime

View file

@ -13,6 +13,7 @@ ErrNotSupportType: "The system does not support the current type: {{ .detail }}"
ErrNameIsExist: "Name is already exist" ErrNameIsExist: "Name is already exist"
ErrDemoEnvironment: "Demo server, prohibit this operation!" ErrDemoEnvironment: "Demo server, prohibit this operation!"
ErrCmdTimeout: "Command execution timed out" ErrCmdTimeout: "Command execution timed out"
ErrCmdIllegal: "The command contains illegal characters. Please modify and try again!"
#app #app
ErrPortInUsed: "{{ .detail }} port already in use" ErrPortInUsed: "{{ .detail }} port already in use"
@ -83,7 +84,6 @@ ErrTypeOfRedis: "The recovery file type does not match the current persistence m
#container #container
ErrInUsed: "{{ .detail }} is in use and cannot be deleted" ErrInUsed: "{{ .detail }} is in use and cannot be deleted"
ErrObjectInUsed: "This object is in use and cannot be deleted" ErrObjectInUsed: "This object is in use and cannot be deleted"
ErrRepoConn: "The repository information contains illegal characters"
ErrPortRules: "The number of ports does not match, please re-enter!" ErrPortRules: "The number of ports does not match, please re-enter!"
#runtime #runtime

View file

@ -13,6 +13,7 @@ ErrNotSupportType: "系統暫不支持當前類型: {{ .detail }}"
ErrNameIsExist: "名稱已存在" ErrNameIsExist: "名稱已存在"
ErrDemoEnvironment: "演示伺服器,禁止此操作!" ErrDemoEnvironment: "演示伺服器,禁止此操作!"
ErrCmdTimeout: "指令執行超時!" ErrCmdTimeout: "指令執行超時!"
ErrCmdIllegal: "執行命令中存在不合法字符,請修改後重試!"
#app #app
ErrPortInUsed: "{{ .detail }} 端口已被佔用!" ErrPortInUsed: "{{ .detail }} 端口已被佔用!"
@ -83,7 +84,6 @@ ErrTypeOfRedis: "恢復文件類型與當前持久化方式不符,請修改後
#container #container
ErrInUsed: "{{ .detail }} 正被使用,無法刪除" ErrInUsed: "{{ .detail }} 正被使用,無法刪除"
ErrObjectInUsed: "該對象正被使用,無法刪除" ErrObjectInUsed: "該對象正被使用,無法刪除"
ErrRepoConn: "倉庫資訊中存在不合法的字符"
ErrPortRules: "端口數目不匹配,請重新輸入!" ErrPortRules: "端口數目不匹配,請重新輸入!"
#runtime #runtime

View file

@ -13,6 +13,7 @@ ErrNotSupportType: "系统暂不支持当前类型: {{ .detail }}"
ErrNameIsExist: "名称已存在" ErrNameIsExist: "名称已存在"
ErrDemoEnvironment: "演示服务器,禁止此操作!" ErrDemoEnvironment: "演示服务器,禁止此操作!"
ErrCmdTimeout: "命令执行超时!" ErrCmdTimeout: "命令执行超时!"
ErrCmdIllegal: "执行命令中存在不合法字符,请修改后重试!"
#app #app
ErrPortInUsed: "{{ .detail }} 端口已被占用!" ErrPortInUsed: "{{ .detail }} 端口已被占用!"
@ -83,7 +84,6 @@ ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后
#container #container
ErrInUsed: "{{ .detail }} 正被使用,无法删除" ErrInUsed: "{{ .detail }} 正被使用,无法删除"
ErrObjectInUsed: "该对象正被使用,无法删除" ErrObjectInUsed: "该对象正被使用,无法删除"
ErrRepoConn: "仓库信息中存在不合法的字符"
ErrPortRules: "端口数目不匹配,请重新输入!" ErrPortRules: "端口数目不匹配,请重新输入!"
#runtime #runtime

View file

@ -4,6 +4,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/cmd" "github.com/1Panel-dev/1Panel/backend/utils/cmd"
) )
@ -114,6 +116,10 @@ func (f *Firewall) ListAddress() ([]FireInfo, error) {
} }
func (f *Firewall) Port(port FireInfo, operation string) error { func (f *Firewall) Port(port FireInfo, operation string) error {
if cmd.CheckIllegal(operation, port.Protocol, port.Port) {
return buserr.New(constant.ErrCmdIllegal)
}
stdout, err := cmd.Execf("firewall-cmd --zone=public --%s-port=%s/%s --permanent", operation, port.Port, port.Protocol) stdout, err := cmd.Execf("firewall-cmd --zone=public --%s-port=%s/%s --permanent", operation, port.Port, port.Protocol)
if err != nil { if err != nil {
return fmt.Errorf("%s port failed, err: %s", operation, stdout) return fmt.Errorf("%s port failed, err: %s", operation, stdout)
@ -122,6 +128,9 @@ func (f *Firewall) Port(port FireInfo, operation string) error {
} }
func (f *Firewall) RichRules(rule FireInfo, operation string) error { func (f *Firewall) RichRules(rule FireInfo, operation string) error {
if cmd.CheckIllegal(operation, rule.Address, rule.Protocol, rule.Port, rule.Strategy) {
return buserr.New(constant.ErrCmdIllegal)
}
ruleStr := "" ruleStr := ""
if strings.Contains(rule.Address, "-") { if strings.Contains(rule.Address, "-") {
std, err := cmd.Execf("firewall-cmd --permanent --new-ipset=%s --type=hash:ip", rule.Address) std, err := cmd.Execf("firewall-cmd --permanent --new-ipset=%s --type=hash:ip", rule.Address)

View file

@ -4,6 +4,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/cmd" "github.com/1Panel-dev/1Panel/backend/utils/cmd"
) )
@ -131,6 +133,9 @@ func (f *Ufw) Port(port FireInfo, operation string) error {
default: default:
return fmt.Errorf("unsupport strategy %s", port.Strategy) return fmt.Errorf("unsupport strategy %s", port.Strategy)
} }
if cmd.CheckIllegal(port.Protocol, port.Port) {
return buserr.New(constant.ErrCmdIllegal)
}
command := fmt.Sprintf("%s %s %s", f.CmdStr, port.Strategy, port.Port) command := fmt.Sprintf("%s %s %s", f.CmdStr, port.Strategy, port.Port)
if operation == "remove" { if operation == "remove" {
@ -156,6 +161,10 @@ func (f *Ufw) RichRules(rule FireInfo, operation string) error {
return fmt.Errorf("unsupport strategy %s", rule.Strategy) return fmt.Errorf("unsupport strategy %s", rule.Strategy)
} }
if cmd.CheckIllegal(operation, rule.Protocol, rule.Address, rule.Port) {
return buserr.New(constant.ErrCmdIllegal)
}
ruleStr := fmt.Sprintf("%s %s ", f.CmdStr, rule.Strategy) ruleStr := fmt.Sprintf("%s %s ", f.CmdStr, rule.Strategy)
if operation == "remove" { if operation == "remove" {
ruleStr = fmt.Sprintf("%s delete %s ", f.CmdStr, rule.Strategy) ruleStr = fmt.Sprintf("%s delete %s ", f.CmdStr, rule.Strategy)