В предыдущих постах мы рассказывали о четырёх типовых уязвимостях веб-приложений и о том, как разработчикам предусмотреть защиту от них при написании кода.
Сегодня поговорим о трёх методах, которые помогут противостоять злоумышленникам 👇
1. Нормализация путей. В чем заключается?
👍 Два и более слэшей подряд заменяются на один.
👍 Корректно обрабатываются "." и "..": убираются из текущего пути или заменяются на директорию выше уровнем соответственно. Всё происходит в рамках переданной строки, поэтому, например, если начать нормализацию с "..", скрипт бросит исключение.
Помимо этого в классе есть набор функций для получения имени, расширения, пути и прочей информации, но в этой статье я на них останавливаться не буду.
Как надо
👍 Всегда нужно знать директорию, в которой должен лежать файл: DOCUMENT_ROOT, tmp, upload и т.д.
👍 Если от пользователя ждём только название или относительный путь, нормализуем его и конкатенируем с нужной папкой.
👍 Если вдруг по какой-то причине из запроса прилетает абсолютный путь, нормализуем его и проверяем, что начинается он из допустимого места.
2. Десериализация. Что поможет сделать код безопаснее?
👍 JSON
Если есть возможность представлять данные в каком-то другом формате, то лучше использовать его. Самый простой и надёжный вариант - JSON.
👍 ['allowed_classes' => false]
Если всё-таки планируем получать что-то от пользователя, нельзя позволить ему внедрять какие-то объекты в наш код. Для этого в функции unserialize() есть второй аргумент, в который можно либо передать массив разрешённых безопасных классов, либо запретить вообще любые классы:
👍 CheckSerializedData
В main/tools.php есть функция CheckSerializedData, которая с помощью регулярного выражения определяет наличие объектов в сериализованной строке и возвращает false, если что-то нашлось. Способ чуть менее надёжный, чем белый список или полный запрет классов, но тоже имеет место.
Криптоподпись (Signer)
Передача важных данных по незащищённым каналам несёт в себе потенциальную опасность — пользователь может подменить данные, добавить вредоносный код. Чтобы защититься от этой уязвимости, необходимо подтверждать авторство данных, а в нашем случае — передаваемых значений. Для этого существует криптоподпись — валидируя ее, можно понять, действительно ли данные не менялись в процессе передачи.
Представим, что вы отправили пользователю какой-то набор параметров и ждёте, что он передаст их в другое место. Передать он, может, и передаст, но по пути обязательно что-нибудь подменит. Для защиты от этого нужна подпись. Отправляем пользователю подписанное значение, и если потом подпись окажется некорректной, значит мы имеем дело с хакером.
👉Подробнее читайте в статье