VYPR
High severityNVD Advisory· Published Jul 18, 2023· Updated Oct 18, 2024

Command injection in firewall ip functionality in 1Panel

CVE-2023-37477

Description

1Panel is an open source Linux server operation and maintenance management panel. An OS command injection vulnerability exists in 1Panel firewall functionality. A specially-crafted HTTP request can lead to arbitrary command execution. An attacker can make an authenticated HTTP request to trigger this vulnerability. 1Panel firewall functionality /hosts/firewall/ip endpoint read user input without validation, the attacker extends the default functionality of the application, which execute system commands. An attacker can execute arbitrary code on the target system, which can lead to a complete compromise of the system. This issue has been addressed in commit e17b80cff49 which is included in release version 1.4.3. Users are advised to upgrade. There are no known workarounds for this vulnerability.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/1Panel-dev/1PanelGo
< 1.4.31.4.3

Affected products

1

Patches

1
e17b80cff497

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

https://github.com/1Panel-dev/1PanelssongliuJul 17, 2023via ghsa
12 files changed · +58 7
  • backend/app/service/container_compose.go+14 0 modified
    @@ -14,8 +14,10 @@ import (
     
     	"github.com/1Panel-dev/1Panel/backend/app/dto"
     	"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/global"
    +	"github.com/1Panel-dev/1Panel/backend/utils/cmd"
     	"github.com/1Panel-dev/1Panel/backend/utils/compose"
     	"github.com/1Panel-dev/1Panel/backend/utils/docker"
     	"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) {
    +	if cmd.CheckIllegal(req.Path) {
    +		return false, buserr.New(constant.ErrCmdIllegal)
    +	}
     	composeItem, _ := composeRepo.GetRecord(commonRepo.WithByName(req.Name))
     	if composeItem.ID != 0 {
     		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) {
    +	if cmd.CheckIllegal(req.Name, req.Path) {
    +		return "", buserr.New(constant.ErrCmdIllegal)
    +	}
     	if err := u.loadPath(&req); err != nil {
     		return "", err
     	}
    @@ -177,6 +185,9 @@ func (u *ContainerService) CreateCompose(req dto.ComposeCreate) (string, 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 {
     		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 {
    +	if cmd.CheckIllegal(req.Name, req.Path) {
    +		return buserr.New(constant.ErrCmdIllegal)
    +	}
     	if _, err := os.Stat(req.Path); err != nil {
     		return fmt.Errorf("load file with path %s failed, %v", req.Path, err)
     	}
    
  • backend/app/service/container.go+4 0 modified
    @@ -18,6 +18,7 @@ import (
     	"github.com/1Panel-dev/1Panel/backend/buserr"
     	"github.com/1Panel-dev/1Panel/backend/constant"
     	"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/docker"
     	"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 {
    +	if cmd.CheckIllegal(container, since, tail) {
    +		return buserr.New(constant.ErrCmdIllegal)
    +	}
     	command := fmt.Sprintf("docker logs %s", container)
     	if tail != "0" {
     		command += " -n " + tail
    
  • backend/app/service/database_mysql.go+12 0 modified
    @@ -17,6 +17,7 @@ import (
     	"github.com/1Panel-dev/1Panel/backend/buserr"
     	"github.com/1Panel-dev/1Panel/backend/constant"
     	"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/compose"
     	_ "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) {
    +	if cmd.CheckIllegal(req.Name, req.Username, req.Password, req.Format, req.Permission) {
    +		return nil, buserr.New(constant.ErrCmdIllegal)
    +	}
    +
     	if req.Username == "root" {
     		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 {
    +	if cmd.CheckIllegal(info.Value) {
    +		return buserr.New(constant.ErrCmdIllegal)
    +	}
    +
     	var (
     		mysql model.DatabaseMysql
     		err   error
    @@ -253,6 +262,9 @@ func (u *MysqlService) ChangePassword(info dto.ChangeDBInfo) error {
     }
     
     func (u *MysqlService) ChangeAccess(info dto.ChangeDBInfo) error {
    +	if cmd.CheckIllegal(info.Value) {
    +		return buserr.New(constant.ErrCmdIllegal)
    +	}
     	var (
     		mysql model.DatabaseMysql
     		err   error
    
  • backend/app/service/firewall.go+0 1 modified
    @@ -304,7 +304,6 @@ func OperateFirewallPort(oldPorts, newPorts []int) error {
     		return err
     	}
     	for _, port := range newPorts {
    -
     		if err := client.Port(fireClient.FireInfo{Port: strconv.Itoa(port), Protocol: "tcp", Strategy: "accept"}, "add"); err != nil {
     			return err
     		}
    
  • backend/app/service/image_repo.go+2 2 modified
    @@ -79,7 +79,7 @@ func (u *ImageRepoService) List() ([]dto.ImageRepoOption, error) {
     
     func (u *ImageRepoService) Create(req dto.ImageRepoCreate) error {
     	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))
     	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 !")
     	}
     	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))
     	if err != nil {
    
  • backend/app/service/ssh.go+4 0 modified
    @@ -11,6 +11,7 @@ import (
     	"time"
     
     	"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/global"
     	"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 {
    +	if cmd.CheckIllegal(req.EncryptionMode, req.Password) {
    +		return buserr.New(constant.ErrCmdIllegal)
    +	}
     	currentUser, err := user.Current()
     	if err != nil {
     		return fmt.Errorf("load current user failed, err: %v", err)
    
  • backend/constant/errs.go+1 1 modified
    @@ -42,6 +42,7 @@ var (
     	ErrTypePasswordExpired = "ErrPasswordExpired"
     	ErrNameIsExist         = "ErrNameIsExist"
     	ErrDemoEnvironment     = "ErrDemoEnvironment"
    +	ErrCmdIllegal          = "ErrCmdIllegal"
     )
     
     // app
    @@ -107,7 +108,6 @@ var (
     	ErrInUsed       = "ErrInUsed"
     	ErrObjectInUsed = "ErrObjectInUsed"
     	ErrPortRules    = "ErrPortRules"
    -	ErrRepoConn     = "ErrRepoConn"
     )
     
     // runtime
    
  • backend/i18n/lang/en.yaml+1 1 modified
    @@ -13,6 +13,7 @@ ErrNotSupportType: "The system does not support the current type: {{ .detail }}"
     ErrNameIsExist: "Name is already exist"
     ErrDemoEnvironment: "Demo server, prohibit this operation!"
     ErrCmdTimeout: "Command execution timed out!"
    +ErrCmdIllegal: "The command contains illegal characters. Please modify and try again!"
     
     #app
     ErrPortInUsed: "{{ .detail }} port already in use"
    @@ -83,7 +84,6 @@ ErrTypeOfRedis: "The recovery file type does not match the current persistence m
     #container 
     ErrInUsed: "{{ .detail }} 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!"
     
     #runtime
    
  • backend/i18n/lang/zh-Hant.yaml+1 1 modified
    @@ -13,6 +13,7 @@ ErrNotSupportType: "系統暫不支持當前類型: {{ .detail }}"
     ErrNameIsExist: "名稱已存在"
     ErrDemoEnvironment: "演示伺服器,禁止此操作!"
     ErrCmdTimeout: "指令執行超時!"
    +ErrCmdIllegal: "執行命令中存在不合法字符,請修改後重試!"
     
     #app
     ErrPortInUsed: "{{ .detail }} 端口已被佔用!"
    @@ -83,7 +84,6 @@ ErrTypeOfRedis: "恢復文件類型與當前持久化方式不符,請修改後
     #container
     ErrInUsed: "{{ .detail }} 正被使用,無法刪除"
     ErrObjectInUsed: "該對象正被使用,無法刪除"
    -ErrRepoConn: "倉庫資訊中存在不合法的字符"
     ErrPortRules: "端口數目不匹配,請重新輸入!"
     
     #runtime
    
  • backend/i18n/lang/zh.yaml+1 1 modified
    @@ -13,6 +13,7 @@ ErrNotSupportType: "系统暂不支持当前类型: {{ .detail }}"
     ErrNameIsExist: "名称已存在"
     ErrDemoEnvironment: "演示服务器,禁止此操作!"
     ErrCmdTimeout: "命令执行超时!"
    +ErrCmdIllegal: "执行命令中存在不合法字符,请修改后重试!"
     
     #app
     ErrPortInUsed: "{{ .detail }} 端口已被占用!"
    @@ -83,7 +84,6 @@ ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后
     #container 
     ErrInUsed: "{{ .detail }} 正被使用,无法删除"
     ErrObjectInUsed: "该对象正被使用,无法删除"
    -ErrRepoConn: "仓库信息中存在不合法的字符"
     ErrPortRules: "端口数目不匹配,请重新输入!"
     
     #runtime
    
  • backend/utils/firewall/client/firewalld.go+9 0 modified
    @@ -4,6 +4,8 @@ import (
     	"fmt"
     	"strings"
     
    +	"github.com/1Panel-dev/1Panel/backend/buserr"
    +	"github.com/1Panel-dev/1Panel/backend/constant"
     	"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 {
    +	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)
     	if err != nil {
     		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 {
    +	if cmd.CheckIllegal(operation, rule.Address, rule.Protocol, rule.Port, rule.Strategy) {
    +		return buserr.New(constant.ErrCmdIllegal)
    +	}
     	ruleStr := ""
     	if strings.Contains(rule.Address, "-") {
     		std, err := cmd.Execf("firewall-cmd --permanent --new-ipset=%s --type=hash:ip", rule.Address)
    
  • backend/utils/firewall/client/ufw.go+9 0 modified
    @@ -4,6 +4,8 @@ import (
     	"fmt"
     	"strings"
     
    +	"github.com/1Panel-dev/1Panel/backend/buserr"
    +	"github.com/1Panel-dev/1Panel/backend/constant"
     	"github.com/1Panel-dev/1Panel/backend/utils/cmd"
     )
     
    @@ -131,6 +133,9 @@ func (f *Ufw) Port(port FireInfo, operation string) error {
     	default:
     		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)
     	if operation == "remove" {
    @@ -156,6 +161,10 @@ func (f *Ufw) RichRules(rule FireInfo, operation string) error {
     		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)
     	if operation == "remove" {
     		ruleStr = fmt.Sprintf("%s delete %s ", f.CmdStr, rule.Strategy)
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.