Новая система безопасности ядра

UPDATE. По результатам обсуждений в систему защиты внесены изменения — откорректировал описание в топике. Особенно большое спасибо benone, Wizard, onthefly за активное обсуждение проблемы.

Раньше в движке для обеспечения защиты от несанкционированных действий использовалась проверка переменной $_SERVER['HTTP_REFERER']. Но иногда это создавало дополнительные проблемы, поэтому было решено ввести новый механизм защиты (готов к использованию начиная с ревизии #551).

Защита данных, полученных через GET-запрос.

Проблема: Некоторые действия выполняются, после перехода пользователя по ссылке, например, удаление топиков. При этом, естественно, проверяется авторизация пользователя. Но, злоумышленник, может подгрузить вам эту страницу на другом сайте в невидимом фрейме и вы удалите топик сами того, не подозревая.

Основная идея решения такова:

1) Завершая свою работу, модуль Security генерирует уникальный 32-х символьный ключ, зависящий от идентификатора сессии (считается, что идентификатор сессии стянуть практически невозможно).
2) В шаблонах, ссылки подобного рода генерируются с добавлением параметра ?security_ls_key=…
3) При переходе по такой «критической» ссылке, Security сравнивает security-key из ссылки с рассчитанным значением для данного идентификатора сессии.

Такой механизм означает, что потенциальный злоумышленник теперь просто-напросто не знает по какому адресу нужно вас перенаправить для удаления топика, блога, вашего разлогирования и т.д — ссылка будет действовать только в рамках одной сессии.

Защита данных переданных POST запросом.

При отправке POST-запросов из форм на сервер также отправляется security-key, который валидируется методом, описанным выше.

Все ajax запросы были переведены в режим явной отправки переменных в POST, а в обработчиках соответственно добавлена проверка isPost().

P.S. На всякий случай старый метод ValidateReferal() сохранен, т.е. при желании можно переключиться в старый режим проверки.

41 комментарий

avatar
Чего-то я не могу понять, а что мешает злоумышленнику передать пост-запрос в том же самом айфрейме?
avatar
Разве для отправки такого запроса в ЛС не нужно выполнять иных действий, кроме как открыть определённый url?
avatar
это как? вроде как доступ через js во фрейм запрещен
avatar
Ни один из известных мне браузеров не поддерживает таких фокусов.
avatar
ща, сек
avatar
Сейчас работает старая система) С ней не получилось форму отправить
avatar
Я вообще не особенно разбираюсь во фреймах, но что межает пользователю просто создать форму где-то и отправить ее на сервер)
avatar
Такой ключ не позволит создать трастовую форму на левом сайте. Он гарантирует, что пост-запрос получен от авторизованного клиента и по его прямому волеизъявлению.
avatar
Какой ключ?
Защита действий, инициированных POST-запросом обеспечивается проверкой авторизации пользователя. Исходя из этого простого соображения, все ajax запросы были переведены в режим явной отправки переменных в POST, а в обработчиках соответственно добавлена проверка isPost().
avatar
вот этот
2) В шаблонах, ссылки подобного рода генерируются с добавлением параметра ?security_ls_key=…

или я неправильно понял автора?
avatar
только при GET запросе
avatar
Мешает то, что пользователь должные быть авторизирован.
avatar
Если ты сам можешь послать форму с другого сайта и при этом, куки будут твои, то за тебя ее же может послать javascript, а ты этого и не заметишь.
avatar
Разумеется, зайти на страничку злоумышенника придется тебе)
avatar
проблема в том, что доступ к кукам только с необходимого домена, поэтому и можно было послать GET запрос через фрейм, где был доступ к кукам. POST запрос нельзя через фрейм послать, его можно тупо послать с сайта злоумышленника, но тогда не будет доступа к кукам :)
avatar
«его можно тупо послать с сайта злоумышленника, но тогда не будет доступа к кукам :)»…
Это в новой версии проверка?

сейчас в старой версии(на holywars.10slov.ru) закомментировал

//$oEngine->Security_ValidateSendForm();

Захожу на holywars.10slov.ru, авторизируюсь.
Захожу на yavsesam.ru/example.php ввожу id топика и жму «добавить».

Комментарий появляется в базе holywars, но не выводится (не разбирался почему, может кеш).
В commentAdd.php после строчки

$oEngine->User_GetUserCurrent();
Возвращает авторизированного пользователя.


Кстати, на холиварсах че-то статика не отображается, надо разобраться…
avatar
«его можно тупо послать с сайта злоумышленника, но тогда не будет доступа к кукам :)»…
Это в новой версии проверка?

Насколько я понимаю, речь о том, что невозможно получить доступ к кукам другого домена (due to browser security policy). Поэтому отправленный POST-запрос с другого сайта будет не опасен, т.к. авторизации всё равно не будет.
avatar
в плане? Если ты авторизирован и я тебе даю ссылку типа yavsesam.ru/example.php в которой автоматом жмется кнопка «Сабмит» и на создается топик с ссылкой на мой любимый сайт. А тебе показывается картинка с ребенком =)
avatar
Хм. Да.
window.onload = function(){
	document.getElementById('form_comment').submit();
}
avatar
А почему бы не использовать тот самый ключ и в пост-запросах? Ведь перехватить его и использовать на сайте злоумышленника будет довольно сложно.
avatar
О том и речь. Так обычно и делается. Причем, передавать можно в том же экшене (url'е формы).
avatar
Но в этом случае пользователь увидит, что был переброшен на другой сайт. И что тем самым удалил свой топик, блог какой-нибудь важный, поменял себе пароль. И больше на плохой сайт не пойдёт. Всё не так безнадёжно ))
avatar
По-хорошему он ничего не заметит) Будет смотреть на картинку с ребенком.
avatar
Как это? Отправка формы повлечёт за собой перенаправление на тот сайт. Это ж не аякс.
avatar
Да, это касается аякс-запросов, которые могут сделать всё незаметно для пользователя.
avatar
Ну разумеется, форма будет отправляться не напрямую, а так как я отправляю этот комментарий.
avatar
Через аякс? Попробуй.
avatar
А чего там пробовать) Какая разница?)
avatar
Аякс-запросы на другой домен работать не будут. Как раз due to browser security policy.

Будет работать (да-да, забыл я про это) лишь прямая отправка формы. Но она и повлечёт за собой переадресацию на тот сайт, поэтому пользователь должен (просто обязан) это заметить.
avatar
Ой, не слышал о таком. Может и есть такое, проверять лень. Кстати, в таком случае можно попробовать открыть попап, который отсылает форму и закрывается или опять же фреймы.

Но это всё уже не так важно. Главное, что можно отправить форму и она примется.
avatar
Да, это касается аякс-запросов, которые могут сделать всё незаметно для пользователя.

Это было добавлением к
невозможно получить доступ к кукам другого домена (due to browser security policy). Поэтому отправленный POST-запрос с другого сайта будет не опасен, т.к. авторизации всё равно не будет.
avatar
верно, просчитались :)
будем фиксить путем добавления ключа
avatar
Вообще-то разрешён, но только если в фрейме тот же домен. Это если быть точным :)
avatar
В деле безопасности работа на опережение (т.е. до того как взломали) уже отлично.
avatar
Предлагал подобный способ изначально:)
  • Hrom
  • -1
avatar
Зато теперь начало валится с надписью — «Hacking attemp!» при нажатие на Создать блог. Рейтинг был повышен, кэш почищен, сессия из таблички тоже, тестилось на 2х юзераx — проблемы у обоих те же. Релиз из репозитория ветки trunk.

livestreet.ru/blog/2045.html — единственное что путное было найдено.
avatar
Номер ревизии?
avatar
549
avatar
550 тоже самое
avatar
В тексте статьи указан номер стабильной ревизии: #548. Сейчас идет смена механизма подсчета кода и закрытие POST-запросов.
avatar
В #551 исправлено (уже с новой системой проверки).
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.