CVE-2021-32699 (Go, published 2021-06-22T20:15Z)
Description: value: Wings is the control plane software for the open source Pterodactyl game management system. All versions of Pterodactyl Wings prior to `1.4.4` are vulnerable to system resource exhaustion due to improper container process limits being defined. A malicious user can consume more resources than intended and cause downstream impacts to other clients on the same hardware, eventually causing the physical server to stop responding. Users should upgrade to `1.4.4` to mitigate the issue. There is no non-code based workaround for impacted versions of the software. Users running customized versions of this software can manually set a PID limit for containers created.
Severity: LOW (CVSS v3 base score: 6.5)
Weakness: CWE-770 \u2014 Allocation of Resources Without Limits or Throttling
The product allocates a reusable resource or group of resources on behalf of an actor without imposing any restrictions on the size or number of resources that can be allocated, in violation of the intended security policy for that actor.
Repository: https://github.com/pterodactyl/wings
Files changed:
config/config_docker.go
environment/docker/container.go
environment/settings.go
Commit message: [security] enforce process limits at a per-container level to avoid abusive clients impacting other instances


Vulnerable code:
// The build settings for a given server that impact docker container creation and
// resource limits for a server instance.
// Converts the CPU limit for a server build into a number that can be better understood
// by the Docker environment. If there is no limit set, return -1 which will indicate to
// Docker that it has unlimited CPU quota.
// Set the hard limit for memory usage to be 5% more than the amount of memory assigned to
// the server. If the memory limit for the server is < 4G, use 10%, if less than 2G use
// 15%. This avoids unexpected crashes from processes like Java which run over the limit.
// Returns the amount of swap available as a total in bytes. This is returned as the amount
// of memory available to the server initially, PLUS the amount of additional swap to include
// which is the format used by Docker.
// Ugly hacky function to handle environment variables that get passed through as not-a-string
// from the Panel. Ideally we'd just say only pass strings, but that is a fragile idea and if a
// string wasn't passed through you'd cause a crash or the server to become unavailable. For now
// try to handle the most likely values from the JSON and hope for the best.

Fixed code:

	// ContainerPidLimit sets the total number of processes that can be active in a container
	// at any given moment. This is a security concern in shared-hosting environments where a
	// malicious process could create enough processes to cause the host node to run out of
	// available pids and crash.
	ContainerPidLimit int64 `default:"256" json:"container_pid_limit" yaml:"container_pid_limit"`
	pids := l.ProcessLimit()
		PidsLimit:         &pids,
	"github.com/pterodactyl/wings/config"
// Limits is the build settings for a given server that impact docker container
// creation and resource limits for a server instance.
// ConvertedCpuLimit converts the CPU limit for a server build into a number
// that can be better understood by the Docker environment. If there is no limit
// set, return -1 which will indicate to Docker that it has unlimited CPU quota.
// MemoryOverheadMultiplier sets the hard limit for memory usage to be 5% more
// than the amount of memory assigned to the server. If the memory limit for the
// server is < 4G, use 10%, if less than 2G use 15%. This avoids unexpected
// crashes from processes like Java which run over the limit.
// ConvertedSwap returns the amount of swap available as a total in bytes. This
// is returned as the amount of memory available to the server initially, PLUS
// the amount of additional swap to include which is the format used by Docker.
// ProcessLimit returns the process limit for a container. This is currently
// defined at a system level and not on a per-server basis.
func (r *Limits) ProcessLimit() int64 {
	return config.Get().Docker.ContainerPidLimit
}

// Get is an ugly hacky function to handle environment variables that get passed
// through as not-a-string from the Panel. Ideally we'd just say only pass
// strings, but that is a fragile idea and if a string wasn't passed through
// you'd cause a crash or the server to become unavailable. For now try to
// handle the most likely values from the JSON and hope for the best.