Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1000 CNY

100.0%

CVE-2021-3899 PoC — Canonical Apport 竞争条件问题漏洞

Source
Associated Vulnerability
Title:Canonical Apport 竞争条件问题漏洞 (CVE-2021-3899)
Description:There is a race condition in the 'replaced executable' detection that, with the correct local configuration, allow an attacker to execute arbitrary code as root.
Description
race condition in apport lead to Local Privilege Escalation on Ubuntu
Readme
# CVE-2021-3899 PoC

## Reproduce
0. Install an older version of apport: `sudo apt-get install apport=2.20.11-0ubuntu27` (any version <= 2.20.11-0ubuntu27.10 is fine, but you have to download the source code)
1. (optional) set small pid\_max. otherwise it will take a longer time to prepare for pid rollback. `echo 10000 | sudo tee /proc/sys/kernel/pid_max`
2. allow anybody to run ping as root: add `ALL ALL=(root) NOPASSWD: /usr/bin/ping` in /etc/sudoers
3. run multiple times of `ulimit -c unlimited; ./exploit`
4. you should see a file at `/etc/logrotate.d/core`
5. open another shell run `nc -lvcp 1234`
6. wait until logrotate is triggered, you can:
    1. adjust the clock one minutes earlier than crontab-daily trigger, and wait. (check /etc/crontab)
    2. run `sudo logrotate -vf /usr/sbin/logrotate /etc/logrotate.conf` to trigger logrotate immediately. (just same as `/etc/cron.daily/logrotate`)
7. there will be a reverse root shell connect to 127.0.0.1:1234

## Detail
Apport will check if pid is reused, by check if the start time of the process is later than apport self:
```
  # /usr/share/apport/apport
  594 apport_start = get_apport_starttime()
  595 process_start = get_process_starttime()
  596 if process_start > apport_start:
  597 error_log('process was replaced after Apport started, ignoring')
  598 sys.exit(0)
```

But this pid could be re-used just after apport launched. In such case, `get_apport_starttime() == get_process_starttime()`.

So, an you can let apport drop a core file with `-rw------- root:root`, if you can re-ocupy this PID with another process running under `uid==0`:
1. prepare a process X to crash, whose pid is A
2. repeating fork process, until current pid reaches A - 2
3. make process X crash, apport will be launched by kernel with pid A - 1. We kill process X, so pid A is now free.
4. run command `sudo ping 8.8.8.8` with cwd `/etc/logrotate.d/`. a process running under root:root will re-occupy pid A.
5. Since the start time of sudo and apport are same, the check of line 596 is bypassed. Apport then drop a core file of process X in /etc/logrotate.d
File Snapshot

[4.0K] /data/pocs/51db82e5786a815ba2778d76aad4caa6b2286578 ├── [ 520] crash.asm ├── [1.3K] exploit.c ├── [ 277] Makefile └── [2.1K] README.md 0 directories, 4 files
Shenlong Bot has cached this for you
Remarks
    1. It is advised to access via the original source first.
    2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
    3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →