Баг в ссылках отслеживания, который ломает подписанные URL
Баг может быть опасным, если он ломает только самое важное.
Я обнаружил баг в mail-history: он идеально работает с обычными ссылками, но дает сбой на подписанных URL. Это ломает ссылки для подтверждения email и подписанные ссылки на скачивание. Это именно те ссылки, где один неверный символ заставляет Laravel отклонить запрос.
Вот как это произошло.
mail-history отслеживает клики по email, переписывая ваш HTML. Она изменяет каждую ссылку так, чтобы сначала запрос проходил через эндпоинт перенаправления. Этот эндпоинт фиксирует клик, а затем отправляет пользователя по реальному адресу назначения.
Для этого система шифрует исходный URL в ссылку отслеживания.
Проблема начинается, когда система извлекает URL из отрендеренного HTML. К тому моменту, как код считывает тело письма, Laravel уже экранирует HTML. Амперсанд (&) в ссылке превращается в &.
Обычная ссылка вроде https://example.com/page работает нормально. В ней нет амперсандов.
Но подписанный URL выглядит так: https://example.com/email/verify/1/abc?expires=123&signature=deadbeef
В HTML он превращается в: https://example.com/email/verify/1/abc?expires=123&signature=deadbeef
Код шифрует эту строку &. Когда пользователь кликает, система расшифровывает её и отправляет его на URL, содержащий &. Laravel пытается проверить подпись, но проверка не проходит, так как символы не совпадают с оригиналом.
Исправление — это всего одна строка кода. Вы должны декодировать HTML-сущности перед тем, как шифровать URL.
$originalUrl = html_entity_decode($matches[2], ENT_QUOTES | ENT_HTML5);
Это превращает & обратно в & перед началом шифрования. Теперь расшифрованная ссылка байт в байт совпадает с исходным подписанным URL.
Я также добавил тест, чтобы предотвратить повторение этой ошибки. Тест проверяет, что расшифрованный URL содержит настоящий &, а не &.
Такие мелкие исправления легко потерять при последующей чистке кода. Всегда пишите тест, который указывает на конкретную причину сбоя.
Уроки для вас:
- Если вы извлекаете данные из отрендеренного HTML, считайте, что они экранированы.
- Браузер исправит экранированные символы за вас. Шифрование и перенаправления — нет.
- Используйте тесты для защиты исправлений в одну строку.
Источник: https://dev.to/nasrulhazim/the-tracking-link-bug-that-only-breaks-signed-urls-38c
