Небезопасная десериализация в 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-инъекциям, отказу в обслуживании и так далее.
--