Repository: kubernetes
Issue: TOB-K8S-008: Arbitrary file paths without bounding
Labels: kind/bug,priority/backlog,area/security,sig/node,help wanted,priority/important-longterm,lifecycle/frozen,wg/security-audit,triage/accepted

This issue was reported in the [Kubernetes Security Audit Report](https://github.com/kubernetes/community/blob/master/wg-security-audit/findings/Kubernetes%20Final%20Report.pdf)

**Description**
Kubernetes as a whole accesses files across the system, including: logs, configuration files, and container descriptions. However, the system does not include a whitelist of safe file locations, nor does it include a more-centralized configuration of where values should be consumed from. For example, the following reads, compresses, and then removes the original file:

```
 // compressLog compresses a log to log.gz with gzip.
func (c *containerLogManager) compressLog(log string) error {
    r, err := os.Open(log)
    if err != nil {
        return fmt.Errorf("failed to open log %q: %v", log, err)
    }
    defer r.Close()
    tmpLog := log + tmpSuffix
    f, err := os.OpenFile(tmpLog, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
    if err != nil {
        return fmt.Errorf("failed to create temporary log %q: %v", tmpLog, err)
    }
    defer func() {
        // Best effort cleanup of tmpLog.
        os.Remove(tmpLog)
    }()
    defer f.Close()
    w := gzip.NewWriter(f)
    defer w.Close()
    if _, err := io.Copy(w, r); err != nil {
        return fmt.Errorf("failed to compress %q to %q: %v", log, tmpLog, err)
    }
    compressedLog := log + compressSuffix
    if err := os.Rename(tmpLog, compressedLog); err != nil {
        return fmt.Errorf("failed to rename %q to %q: %v", tmpLog, compressedLog, err)
    }
    // Remove old log file.
    if err := os.Remove(log); err != nil {
        return fmt.Errorf("failed to remove log %q after compress: %v", log, err)
    }
    return nil
}
```
Figure 23.1: Log compression in pkg/kubelet/logs/container_log_manager.go

While not concerning in and of itself, we recommend a more general approach to file locations and permissions at an architectural level. Furthermore, files such as the SSH authorized_keys file are lenient in what they accept; lines that do not match a key are simply ignored. Attackers with access to configuration data and a write location may be able to parlay this access into an attack such as inserting new keys into a log stream. 

**Exploit Scenario**
Alice runs a cluster in production. Eve, a developer, does not have access to the production environment, but does have access to configuration files. Eve uses this access to remove sensitive files from the cluster’s file system, rendering the system inoperable.

**Recommendation**
Short term, audit all locations that handle file processing, and ensure that they include as much validation as possible. This should ensure that the paths are reasonable for what the component expects, and do not overwrite sensitive locations unless absolutely necessary. 

Long term, combine this solution with TOB-K8S-004: File Permissions and TOB-K8S-006: Hard-coded credential paths. A central solution that combines permissions and data validation from a single source will help limit mistakes that overwrite files, and make changes to file system interaction easier from a central location.

**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-008 and it was finding 25 of the report.

The vendor considers this issue Low Severity.

To view the original finding, begin on page 67 of the [Kubernetes Security Review Report](https://github.com/kubernetes/community/blob/master/wg-security-audit/findings/Kubernetes%20Final%20Report.pdf)

**Environment**:

- Kubernetes version: 1.13.4