DDexec / EverythingExec

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Контекст

У Linux для запуску програми вона повинна існувати як файл, вона повинна бути доступна якимось чином через ієрархію файлової системи (це просто як працює execve()). Цей файл може знаходитися на диску або в оперативній пам'яті (tmpfs, memfd), але вам потрібен шлях до нього. Це дуже спрощує контроль за тим, що запускається в системі Linux, дозволяє виявляти загрози та інструменти зловмисників або запобігати їм спробувати виконати що-небудь своє (наприклад, не дозволяючи непривілейованим користувачам розміщувати виконувані файли де завгодно).

Але ця техніка призначена змінити все це. Якщо ви не можете запустити процес, який вам потрібен... тоді ви захоплюєте один вже існуючий.

Ця техніка дозволяє вам обійти загальні техніки захисту, такі як тільки для читання, noexec, білістинг імен файлів, білістинг хешів...

Залежності

Остаточний скрипт залежить від наступних інструментів для роботи, вони повинні бути доступні в системі, яку ви атакуєте (зазвичай ви знайдете їх скрізь):

dd
bash | zsh | ash (busybox)
head
tail
cut
grep
od
readlink
wc
tr
base64

Техніка

Якщо ви можете довільно змінювати пам'ять процесу, то можете захопити його. Це можна використовувати для захоплення вже існуючого процесу та заміни його іншою програмою. Це можна досягти, використовуючи виклик системного виклику ptrace() (що вимагає можливості виконання системних викликів або наявності gdb в системі) або, що цікавіше, записуючи в /proc/$pid/mem.

Файл /proc/$pid/mem є однозначним відображенням всього адресного простору процесу (наприклад, від 0x0000000000000000 до 0x7ffffffffffff000 в x86-64). Це означає, що читання або запис у цей файл за зсувом x те саме, що читання або зміна вмісту за віртуальною адресою x.

Тепер ми маємо чотири основні проблеми:

  • Загалом, тільки root та власник програми файлу можуть змінювати його.

  • ASLR.

  • Якщо ми спробуємо прочитати або записати адресу, яка не відображена в адресному просторі програми, ми отримаємо помилку вводу-виводу.

Ці проблеми мають рішення, які, хоча вони не є ідеальними, є досить ефективними:

  • Більшість оболонкових інтерпретаторів дозволяють створювати файлові дескриптори, які потім будуть успадковані дочірніми процесами. Ми можемо створити fd, що вказує на файл mem оболонки з правами запису... тому дочірні процеси, які використовують цей fd, зможуть змінювати пам'ять оболонки.

  • ASLR навіть не проблема, ми можемо перевірити файл maps оболонки або будь-який інший з procfs, щоб отримати інформацію про адресний простір процесу.

  • Тому нам потрібно використовувати lseek() у файлі. З оболонки це не можна зробити, якщо не використовувати погано відомий dd.

Детальніше

Кроки досить прості і не потребують жодних спеціальних знань для їх розуміння:

  • Розібрати бінарний файл, який ми хочемо запустити, та завантажувач, щоб дізнатися, які відображення їм потрібні. Потім створити "shell"код, який буде виконувати, загалом кажучи, ті самі кроки, які робить ядро при кожному виклику execve():

  • Створити вказані відображення.

  • Прочитати бінарні файли в них.

  • Налаштувати дозволи.

  • Нарешті ініціалізувати стек з аргументами для програми та розмістити допоміжний вектор (необхідний завантажувачем).

  • Перейти до завантажувача та дозволити йому зробити все інше (завантажити бібліотеки, необхідні для програми).

  • Отримати з файлу syscall адресу, на яку процес повернеться після виклику системного виклику, який він виконує.

  • Перезаписати це місце, яке буде виконуваним, нашим "shell"кодом (через mem ми можемо змінювати незаписувані сторінки).

  • Передати програму, яку ми хочемо запустити, в stdin процесу (її буде read() цим "shell"кодом).

  • На цьому етапі все залежить від завантажувача, який завантажить необхідні бібліотеки для нашої програми та перейде до неї.

Перевірте інструмент на https://github.com/arget13/DDexec

EverythingExec

Є кілька альтернатив для dd, одна з яких, tail, наразі є програмою за замовчуванням для lseek() через файл mem (що було єдиним метою використання dd). Зазначені альтернативи:

tail
hexdump
cmp
xxd

Встановивши змінну SEEKER, ви можете змінити використаний пошуковик, наприклад:

SEEKER=cmp bash ddexec.sh ls -l <<< $(base64 -w0 /bin/ls)

Якщо ви знайдете інший дійсний пошуковик, який не реалізований у скрипті, ви все ще можете використовувати його, встановивши змінну SEEKER_ARGS:

SEEKER=xxd SEEKER_ARGS='-s $offset' zsh ddexec.sh ls -l <<< $(base64 -w0 /bin/ls)

Заблокуйте це, EDRs.

Посилання

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Last updated