Skip to content

TOB-K8S-033: Services use questionable default functions #81138

@cji

Description

@cji

This issue was reported in the Kubernetes Security Audit Report

Description
Many services in Kubernetes use questionable default functions, such as insecure random number generation or dangerous temporary file creation.

In regards to random number generation, many services, including kubelet, api-server, kube-scheduler, kube-proxy, seed the random number generator in the following manner.

rand.Seed(time.Now().UnixNano())

Figure 27.1: The common method of seeding rand with time in Kubernetes.

Generally this is okay. The code properly uses crypto/rand for cryptographic operations like key generations. No cryptographic primitives were observed incorrectly using math/rand.

However, due to this seeding, certain identifiers are predictable and simplify aspects of an exploitation chain. In Figure 33.2, the node is assigned a random name that could be guessable to an attacker who knows uptime information.

func (kubemarkController *KubemarkController) addNodeToNodeGroup(nodeGroup string) error {
	node := kubemarkController.nodeTemplate.DeepCopy()
        ...
	node.Name = fmt.Sprintf("%s-%d", nodeGroup, kubemarkController.rand.Int63())
        ...
        client.CoreV1().ReplicationControllers(node.Namespace).Create(node)
}

Figure 27.2: An example of using time-seeded values to add a node to a group.

Another concerning function was found in the kubectl create --edit command, which creates a temporary file to edit objects before creation. This temporary file is created via a custom tempFile function (Figure 33.3) called by LaunchTempFile (Figure 33.4). It is possible to create all possible temporary files that would be used, leading to the kubectl create --edit command to fail.

There is also a potential race condition in LaunchTempFile between closing the file and opening it later in the editor. However, since the file is created with 0600 permissions, this appears to be a non-issue.

func tempFile(prefix, suffix string) (f *os.File, err error) {
	dir := os.TempDir()

	for i := 0; i < 10000; i++ {
		name := filepath.Join(dir, prefix+randSeq(5)+suffix)
		f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
		if os.IsExist(err) {
			continue
		}
		break
	}
	return
}

Figure 27.3: The tempFile function definition.

func (e Editor) LaunchTempFile(prefix, suffix string, r io.Reader) ([]byte, string, error) {
	f, err := tempFile(prefix, suffix)
	if err != nil {
		return nil, "", err
	}
	defer f.Close()
	path := f.Name()
	if _, err := io.Copy(f, r); err != nil {
		os.Remove(path)
		return nil, path, err
	}
	// This file descriptor needs to close so the next process (Launch) can claim it.
	f.Close()
	if err := e.Launch(path); err != nil {
		return nil, path, err
	}
	bytes, err := ioutil.ReadFile(path)
	return bytes, path, err
}

Figure 27.4: The LaunchTempFile function definition.

Exploit Scenario
If an attacker needs to know the name or identifier of a service, Pod, or node that is infeasible to brute force, the attacker may be able to deduce the uptime from the current environment and enumerate possible seeds, narrowing the space of possible names and identifiers.

Regarding the tempFile, the attacker can create all possible temporary files (36**5 = 60466176), preventing the kubectl create --edit from creating the temporary file.

Recommendation
Short term, seed the random number generator using a less predictable seed.

Long term, investigate whether the standard library ioutil.TempFile function would be a viable replacement for the current tempFile implementation. Ensure appropriate use of math/rand and crypto/rand, and ensure correct random number generator seeding.

Anything else we need to know?:

See #81146 for current status of all issues created from these findings.

The vendor gave this issue an ID of TOB-K8S-033 and it was finding 30 of the report.

The vendor considers this issue Low Severity.

To view the original finding, begin on page 75 of the Kubernetes Security Review Report

Environment:

  • Kubernetes version: 1.13.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/securitykind/bugCategorizes issue or PR as related to a bug.lifecycle/frozenIndicates that an issue or PR should not be auto-closed due to staleness.needs-triageIndicates an issue or PR lacks a `triage/foo` label and requires one.priority/important-longtermImportant over the long term, but may not be staffed and/or may need multiple releases to complete.sig/nodeCategorizes an issue or PR as relevant to SIG Node.wg/security-auditCategorizes an issue or PR as relevant to WG Security Audit.

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions