PHP Tricks
Загальне розташування кукісів:
Це також стосується кукісів phpMyAdmin.
Кукіси:
Місця:
Обхід порівнянь в PHP
Легкі порівняння/Типове джерело ( == )
Якщо використовується ==
в PHP, то існують неочікувані випадки, коли порівняння не працює як очікувалося. Це тому, що "==" порівнює лише значення, перетворені у той самий тип, якщо ви також хочете порівняти тип порівнюваних даних, вам потрібно використовувати ===
.
Таблиці порівнянь PHP: https://www.php.net/manual/en/types.comparisons.php
"string" == 0 -> True
Рядок, який не починається з числа, дорівнює числу"0xAAAA" == "43690" -> True
Рядки, складені з чисел у десятковому або шістнадцятковому форматі, можуть бути порівняні з іншими числами/рядками з результатом True, якщо числа були однакові (числа в рядку інтерпретуються як числа)"0e3264578" == 0 --> True
Рядок, що починається з "0e" і за яким слідує будь-що, буде дорівнювати 0"0X3264578" == 0X --> True
Рядок, що починається з "0" і за яким слідує будь-яка літера (X може бути будь-якою літерою) і за яким слідує будь-що, буде дорівнювати 0"0e12334" == "0" --> True
Це дуже цікаво, оскільки у деяких випадках ви можете контролювати введення рядка "0" та деякий вміст, який хешується і порівнюється з ним. Тому, якщо ви можете надати значення, яке створить хеш, що починається з "0e" і без будь-якої літери, ви можете обійти порівняння. Ви можете знайти вже захешовані рядки з цим форматом тут: https://github.com/spaze/hashes"X" == 0 --> True
Будь-яка літера в рядку дорівнює цілому числу 0
Додаткова інформація за посиланням https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09
in_array()
Типове джерело також впливає на функцію in_array()
за замовчуванням (вам потрібно встановити true для третього аргументу, щоб зробити строге порівняння):
strcmp()/strcasecmp()
Якщо ця функція використовується для будь-якої перевірки автентифікації (наприклад, перевірка пароля) і користувач контролює один бік порівняння, він може відправити порожній масив замість рядка як значення пароля (https://example.com/login.php/?username=admin&password[]=
) і обійти цю перевірку:
Та ж помилка виникає з strcasecmp()
Суворе приведення типів
Навіть якщо використовується ===
, можуть виникати помилки, які роблять порівняння вразливим до суворого приведення типів. Наприклад, якщо порівняння перетворює дані в інший тип об'єкта перед порівнянням:
preg_match(/^.*/)
preg_match()
може бути використано для перевірки введення користувача (він перевіряє, чи є слово/регулярний вираз з чорного списку присутнім у введенні користувача, і якщо його немає, код може продовжити виконання).
Обхід нового рядка
Однак, коли визначається початок регулярного виразу, preg_match()
перевіряє лише перший рядок введення користувача, тому якщо ви якимось чином можете надіслати введення у кількох рядках, ви зможете обійти цю перевірку. Приклад:
Для обходу цієї перевірки ви можете надіслати значення з новими рядками, закодованими у URL (%0A
) або, якщо ви можете надіслати JSON дані, надішліть їх у декількох рядках:
Знайдіть приклад тут: https://ramadistra.dev/fbctf-2019-rceservice
Обхід помилки довжини
(Цей обхід, схоже, був спробований на PHP 5.2.5, і я не зміг зробити його працюючим на PHP 7.3.15)
Якщо ви можете передати preg_match()
дійсний великий ввід, він не зможе обробити його, і ви зможете обійти перевірку. Наприклад, якщо він блокує JSON, ви можете відправити:
Прохід ReDoS
Хитрість з: https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223
Коротко кажучи, проблема виникає через те, що функції preg_*
в PHP базуються на бібліотеці PCRE. У PCRE деякі регулярні вирази збігаються за допомогою багатьох рекурсивних викликів, які використовують багато стекового простору. Можливо встановити обмеження на кількість дозволених рекурсій, але в PHP це обмеження за замовчуванням становить 100 000, що більше, ніж вміщується в стеку.
У цьому обговоренні на Stackoverflow також було посилання на те, де більш детально говориться про цю проблему. Наше завдання було тепер зрозумілим:
Надіслати вхідні дані, які змусили б регулярний вираз виконати 100 000+ рекурсій, спричиняючи SIGSEGV, що змусить функцію preg_match()
повернути false
, тим самим змушуючи додаток вважати, що наш ввід не є зловмисним, кинувши сюрприз в кінці навантаження щось на зразок {system(<дужепоганакоманда>)}
для отримання SSTI --> RCE --> прапорця :).
Ну, в термінах регулярних виразів, ми фактично не робимо 100 тис. "рекурсій", а замість цього ми рахуємо "кроки відстеження назад", як це стверджує документація PHP, за замовчуванням це становить 1 000 000 (1М) у змінній pcre.backtrack_limit
.
Щоб досягти цього, 'X'*500_001
призведе до 1 мільйона кроків відстеження назад (500 тис. вперед і 500 тис. назад):
Типове заміни для захисту PHP коду
Виконання після перенаправлення (EAR)
Якщо PHP перенаправляє на іншу сторінку, але після встановлення заголовка Location
не викликається функція die
або exit
, PHP продовжує виконання та додає дані до тіла сторінки:
Експлуатація траверсу шляху та включення файлів
Перевірте:
pageFile Inclusion/Path traversalДодаткові хитрощі
register_globals: У PHP < 4.1.1.1 або якщо неправильно сконфігуровано, register_globals може бути активований (або їх поведінка імітується). Це означає, що в глобальних змінних, таких як $_GET, якщо вони мають значення, наприклад $_GET["param"]="1234", ви можете отримати доступ до нього через $param. Таким чином, надсилаючи HTTP-параметри, ви можете перезаписати змінні, які використовуються в коді.
PHPSESSION cookies тієї ж домену зберігаються в одному місці, тому якщо в межах домену використовуються різні cookies в різних шляхах, ви можете зробити так, щоб шлях отримував доступ до cookie шляху, встановлюючи значення cookie іншого шляху. Таким чином, якщо обидва шляхи отримують доступ до змінної з однаковою назвою, ви можете зробити так, щоб значення цієї змінної в path1 застосовувалося до path2. А потім path2 буде вважати дійсними змінні path1 (давши cookie назву, яка відповідає їй в path2).
Коли у вас є імена користувачів користувачів машини. Перевірте адресу: /~<USERNAME>, щоб переглянути, чи активовані каталоги php.
password_hash/password_verify
Ці функції зазвичай використовуються в PHP для генерації хешів від паролів та для перевірки, чи правильний пароль порівняно з хешем.
Підтримувані алгоритми: PASSWORD_DEFAULT
та PASSWORD_BCRYPT
(починається з $2y$
). Зверніть увагу, що PASSWORD_DEFAULT часто є таким самим, як PASSWORD_BCRYPT. І наразі PASSWORD_BCRYPT має обмеження розміру вводу 72 байти. Тому, коли ви намагаєтеся згештувати щось більше, ніж 72 байти з цим алгоритмом, буде використано лише перші 72 байти:
Обхід HTTP-заголовків за допомогою зловживання помилками PHP
Якщо сторінка PHP виводить помилки та повертає деякий ввід, наданий користувачем, користувач може змусити сервер PHP вивести деякий вміст достатньо довгий, щоб при спробі додати заголовки до відповіді сервер викинув помилку. У наступному сценарії зловмисник змусив сервер викинути деякі великі помилки, і, як видно на екрані, коли PHP спробував змінити інформацію заголовка, він не зміг (так, наприклад, заголовок CSP не був відправлений користувачеві):
Виконання коду
system("ls"); `ls`; shell_exec("ls");
Перевірте це для більш корисних функцій PHP
Для виконання коду в аргументі "replace" потрібно щонайменше одне співпадіння. Ця опція preg_replace була застарілою починаючи з PHP 5.5.0.
RCE через Eval()
RCE через Assert()
Ця функція в php дозволяє вам виконувати код, який написаний у вигляді рядка, щоб повернути true або false (і в залежності від цього змінити виконання). Зазвичай змінна користувача буде вставлена посередині рядка. Наприклад:
assert("strpos($_GET['page']),'..') === false")
--> У цьому випадку для отримання RCE ви могли б зробити:
Вам потрібно розібрати синтаксис коду, додати свій пейлоуд, а потім виправити його знову. Ви можете використовувати логічні операції такі як "and" або "%26%26" або "|". Зверніть увагу, що "or", "||" не працює, оскільки якщо перша умова є істинною, наш пейлоуд не буде виконаний. Так само ";" не працює, оскільки наш пейлоуд не буде виконаний.
Інша опція - додати до рядка виконання команди: '.highlight_file('.passwd').'
Інша опція (якщо у вас є внутрішній код) - змінити деяку змінну для зміни виконання: $file = "hola"
RCE через usort()
Ця функція використовується для сортування масиву елементів за допомогою конкретної функції. Для зловживання цією функцією:
Ви також можете використовувати // для коментування решти коду.
Щоб дізнатися кількість дужок, які вам потрібно закрити:
?order=id;}//
: ми отримуємо повідомлення про помилку (Parse error: syntax error, unexpected ';'
). Ймовірно, нам не вистачає однієї або декількох дужок.?order=id);}//
: ми отримуємо попередження. Схоже, що все вірно.?order=id));}//
: ми отримуємо повідомлення про помилку (Parse error: syntax error, unexpected ')' i
). Ймовірно, у нас занадто багато закриваючих дужок.
RCE через .httaccess
Якщо ви можете завантажити файл .htaccess, то ви можете налаштувати кілька речей і навіть виконати код (налаштовуючи файли з розширенням .htaccess можна виконувати).
Різні оболонки .htaccess можна знайти тут
RCE через змінні середовища
Якщо ви знайдете вразливість, яка дозволяє вам змінювати змінні середовища в PHP (і ще одну для завантаження файлів, хоча з додатковими дослідженнями, можливо, це можна обійти), ви можете скористатися цим для отримання RCE.
LD_PRELOAD
: Ця змінна середовища дозволяє завантажувати довільні бібліотеки при виконанні інших виконуваних файлів (хоча в цьому випадку це може не працювати).PHPRC
: Вказує PHP, де знаходиться його файл конфігурації, зазвичай називаєтьсяphp.ini
. Якщо ви можете завантажити власний файл конфігурації, тоді використовуйтеPHPRC
, щоб вказати PHP на нього. Додайте записauto_prepend_file
, вказавши другий завантажений файл. Цей другий файл містить звичайний PHP-код, який потім виконується виконавчим середовищем PHP перед будь-яким іншим кодом.
Завантажте файл PHP, що містить наш код оболонки
Завантажте другий файл, що містить директиву
auto_prepend_file
, яка вказує препроцесору PHP виконати файл, який ми завантажили на кроці 1Встановіть змінну
PHPRC
на файл, який ми завантажили на кроці 2.
Отримайте більше інформації про виконання цієї ланцюгової реакції з оригінального звіту.
PHPRC - ще один варіант
Якщо ви не можете завантажувати файли, ви можете використовувати в FreeBSD "файл"
/dev/fd/0
, який міститьstdin
, як тіло запиту, відправленого доstdin
:curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'
Або для отримання RCE, увімкніть
allow_url_include
та додайте файл з кодом PHP у base64:curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary $'allow_url_include=1\nauto_prepend_file="data://text/plain;base64,PD8KICAgcGhwaW5mbygpOwo/Pg=="'
Техніка з цього звіту.
Статичний аналіз PHP
Перегляньте, чи можете вставити код у виклики цих функцій (з тут):
Якщо ви відлажуєте додаток на PHP, ви можете глобально увімкнути виведення помилок в /etc/php5/apache2/php.ini
, додавши display_errors = On
, та перезапустити apache: sudo systemctl restart apache2
Розшифрування PHP-коду
Ви можете використовувати веб-сайт www.unphp.net для розшифрування php-коду.
Обгортки та протоколи PHP
Обгортки та протоколи PHP можуть дозволити вам обійти захист від запису та читання в системі та скомпрометувати її. Для додаткової інформації перевірте цю сторінку.
Xdebug неавтентифікований RCE
Якщо ви бачите, що Xdebug увімкнено у виведенні phpconfig()
, вам слід спробувати отримати RCE через https://github.com/nqxcode/xdebug-exploit
Змінні змінні
Використання RCE через новий $_GET["a"]($_GET["b"])
Якщо на сторінці ви можете створити новий об'єкт будь-якого класу, ви, можливо, зможете отримати RCE, перевірте наступну сторінку, щоб дізнатися як:
pagePHP - RCE abusing object creation: new $_GET["a"]($_GET["b"])Виконання PHP без літер
https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/
Використання вісімкової системи числення
XOR
XOR (ексклюзивне або) - це бінарний оператор, який повертає істину лише в тому випадку, коли операнди мають різні значення.
XOR простий код оболонки
Згідно з цим описом, можливо згенерувати простий код оболонки таким чином:
Таким чином, якщо ви можете виконати довільний PHP без цифр та літер, ви можете надіслати запит на виконання довільного PHP, використовуючи такий витів, наприклад:
Для більш детального пояснення перевірте https://ctf-wiki.org/web/php/php/#preg_match
XOR Shellcode (всередині eval)
Подібно до Perl
Last updated