Pull to refresh

Обнаружена уязвимость функционала «remember me» в Laravel

Reading time 2 min
Views 17K

Некоторое время назад был опубликован пост с подробным описанием уязвимости функционала «remember me» в фреймворке Laravel. Она позволяла имперсонировать любого пользователя путем создания поддельного кука логина. Разработчики тогда сказали что дыру закрыли. Но более подробный взгляд показывает что гидре отрубали лишь одну голову. Даже если вы не используете данный фреймворк вам все равно будет полезно узнать как не надо имплементировать такой функционал у себя на сайте.



Главной проблемой является то что токен авторизации в Laravel являет собой просто зашифрованный id пользователя. Почему это плохо? Во-первых если украсть или подобрать ключ используемый для шифровки можно залогиниться под любым пользователем, при этом не придется подбирать его пароль. Конечно получить такой ключ достаточно трудно, но вот например недавно обнаруженная уязвимость OpenSSL Hartbleed позволила бы это сделать. Но это не главная проблема.

Что будет если кто-то украдет ваш куки?

Фактически ваш аккаунт уже украден навсегда и вы ничего не можете с этим сделать. Поскольку это просто ваш id, то такой куки нет срока годности, с ним можно будет зайти даже через год и даже если вы поменяете пароль. Это открывает захватчику еще одну дверь: если он однажды подобрал ваш пароль, залогинился а затем сохранил куки себе, то смена пароля вам опять таки уже не поможет. Давайте добавим сюда то, что перехватить ваши пакеты когда вы пользуетесь открытым WIFI ( например в Макдональдс ) очень и очень просто.

Если не ID, то что?

Есть много вариантов как сделать remember_me безопасно, все они нуждаются в каком-то уникальном рандомном токене, например:

1) Создаем табличку в которой сохраняем: user_id, token, expires_on, ip
2) При логине с включенным «remember me» создаем новый случайный токен, записываем IP пользователя а также задаем срок годности токена.
3) Когда пользователь приходит с токеном, мы проверяем его валидность по табличке
4) Логиним пользователя
5) Удаляем старый токен
6) Создаем новый токен как в пункте 2 и отдаем его пользователю

Поскольку токен полностью рандомный подобрать его фактически невозможно. Украсть его намного труднее, так как использовать его можно только один раз. Как дополнительный бонус у нас есть привязка к IP пользователя. Кому интересна подробная имплементация советую прочитать пост на stackoverflow в котором подробно описана вся процедура авторизации пользователя. Я навел упрощенный пример здесь для того чтобы в контрасте показать насколько примитивен подход Laravel.

Мораль: нельзя доверять безопасность своего приложения фреймворку и надеяться что все сдалали за вас. Кстати создатель фреймворка очень плохо воспринял критику своего подхода и продемонстрировал полное непонимание подхода с токенами.
Tags:
Hubs:
+49
Comments 20
Comments Comments 20

Articles