Комментарии 10
А самый прикол в том, что никакой проблемы непосредственно в сериализации и десериализации нет. Получение доступа к сериализованным данным полностью эквивалентно получению данных к самому объекту. А если кто-то предоставил возможность достучаться до самого объекта, то тут проблема не в его наличии, а в самом факте предоставления доступа.
В первом же примере уязвимость не в десериализации, а в принципе в хранении непубличного кода в публичной директории. Косяк времён Колчака, который поправлен вообще везде, кроме адской легасятины, вроде Wordpress, Bitrix и прочих, сохраняющих в себе эту "дыру" ради, подозреваю, обратной совместимости.
P.S. Если что, статья отличная. Замечание, просто что б читающие потом не начали говорить что "сериализация небезопасна". Описанная проблема просто более масштабна.
P.P.S. Я бы ещё предложил тег PHP добавить ;)
А вордпрес же сейчас симфони?
Мне кажется тут дело совсем не в архитектуре фреймворка а именно в механизме сериализации и десереализации объектов. Предположим какой то сайт на той же Ларе решит хранить какие то пользовательские настройки в куках в виде сериализованного массива. Скажете так не бывает? Да сплошь и рядом. Это же выглядит безопасно? Вроде да. А если злоумышленник заменит в своих куках сериализованный массив на сериализованный объект, в котором будет магический метод __wakeup , в котором произвольный код? Который будет выполнен автоматически в том месте, где вызывается unserialize. Нужно или проверять до десериализации, а что же нам пришло - массив или объект, разбирая сериализованную строку на низком уровне. Или не использовать сериализацию там, где сериализованные данные могут быть модифицированы на стороне пользователя.
Скажете так не бывает?
Такая же распространённость, по-моему, как SQL-инъекции. Ошибка такого же уровня.
Это же выглядит безопасно? Вроде да.
Ээээ... Да? Предоставление состояния бека на клиент безопасно? Хм... Ну по-мне, так же безопасно как хранить пароль в открытом виде в JWT токене.
Веб никуда не денется без хранения состояния бэка на клиенте, в том или ином виде. Это неизбежное зло. Хотя бы идентификатор сессии хранить на клиенте нужно, а это уже "состояние". Также очевидно, что абсолютно любые данные, приходящие на бэк с клиента должны быть проверены и отфильтрованы перед использованием. В случае с сериализованными сущностями, такую проверку придется делать дважды, перед десериализацией и после, так как "использование" идет уже при десериализации, неявным образом. Вот и все, что я хотел сказать.
Ну да, у метода десериализации есть фильтрация классов (вторым аргументом), однако, есть подозрение, что инженер, использующий этот механизм языка чтобы хранить что-то на клиенте, вместо какого-нибудь json_encode/json_decode - проигнорирует и подобные ограничения.
Ну просто даже будучи джуном мне в голову не приходило использовать сереализацию подобным образом. Это же прям дыра. И я только сейчас, через столько лет, после вашего комментария, понял накой фиг нужен второй аргумент у deserialize, считая его абсолютно бессмысленным.
сериализованный объект, в котором будет магический метод __wakeup , в котором произвольный код?
Вы не совсем правильно поняли. В атакуемой системе должен быть класс с методом __wakeup(), внутри которого есть вызов произвольного кода. Только тогда эксплоит сработает. В самих сериализованных данных передаётся только имя этого класса.
И ещё уточню: этот класс должен быть эагружен до десериализации или доступен по autoload , иначе будет ошибка.
Я вот представить себе не могу, зачем такой подход может вообще понадобиться. На уровне
eval( $_REQUEST['command'] );
Согласен с тобой. Действительно, проблема не в самой сериализации, а в том, как и где хранятся данные. Если доступ к объекту открыт, то это уже вопрос архитектуры и безопасности приложения. Хранение непубличного кода в публичной директории — это классическая ошибка, и, к сожалению, многие системы до сих пор с этим не справились. В данном случае это сделано намеренно, чтобы пользователь имел доступ к коду в рамках лабораторных работ, но в реальной жизни такие ошибки тоже встречаются. Я бы еще отметил, что существует opensource, в котором такие вещи тоже можно встретить. Весь смысл в том, чтобы данную уязвимость в идеале изучать с доступом к коду.
Сериализацию в принципе лучше использовать только в случае крайней необходимости. Даже если хранить сериализованные данные только в бд, доступ к которой для пользователя обмазан валидаторами, нет никаких гарантий что через какую то уязвимость или неосмотрительность разработчика этот доступ будет получен.
Так что лучше гонять джейсончики. Хотя и с ними можно зафакапиться...
Небезопасная десериализация в PHP: Как создать собственный эксплойт