Тема: [Corp 4.5] Ошибка "Подозрение на CSRF" (form_csrf, lib_csrf)

Неожиданная ошибка "Подозрение на атаку Cross-Site Request Forgery" на странице с двумя формами
Версия движка: 4.5 Corporate
Версия ОС: Windows 7 Домашняя расширенная SP1
Версия браузера: Firefox 25.0
Окружение: Денвер-3 2012-09-16, Apache 2.2.22, PHP-5.3.13, MySQL-5.5.25

Здесь на форуме уже порядочно было жалоб на эту ошибку (большОе количество, кстати, невтемных, по собственной вине). Ситуация в моем случае:

* на странице имеются две формы; в обоих из них вызов form_csrf() присутствует;
* обе формы по-отдельности друг от друга работают корректно - ошибки с CSRF не вываливается; по-отдельности, - имеется в виду, когда на странице находится только одна из форм;
* при наличии двух форм корректно, без ошибки CSRF, работает только первая (та, в которой первой была вызвана хелпер-функция form_csrf); при сабмите второй формы как раз и происходит эта проблема с CSRF;

В чем еще лулз, - иногда ошибка сама по себе пропадает.
При этом чистка кэша не дает никакого эффекта (вручную чистится все файлы в system/cache).

Дополнительные сведения:
* кука ci_session в браузере всегда присутствует: и при нормальном результате, и при ошибке CSRF;
* в куке ci_session коллекция ci_tokens присутствует всегда; причем в ней никогда не бывает "работающего" токена;
* количество токенов в коллекции ci_tokens имеет тенденцию постоянно расти; ситуации, в которых это происходит, точно зафиксировать не удалось;

Замечено, что ошибка стабильно воспроизводится на этой странице после того, как логнуться в админку и сразу выйти из нее.

Условия, при которых ошибка пропадает, точно не удалось зафиксировать. Сначала было замечено, что это произошло при изменении файла lib_csrf, но ни разу не удалось воспроизвести. Как-то вроде после полной очистки кэша ошибка пропала, но тоже воспроизвести не получилось.

Предположительно, что ошибка находится где-то в библиотеке lib_csrf, но явного места причины пока не увидел.

Thumbs up +1 Thumbs down

2

Re: [Corp 4.5] Ошибка "Подозрение на CSRF" (form_csrf, lib_csrf)

Удалось выяснить непосредственную причину проблемы. Суть в том, что синглтоне CI за время выполнения запроса успевает поменяться значение свойства session. А этим свойством как раз и пользуется экземпляр библиотеки Lib_csrf при проверке anti-forgery-токенов (через вызовы $this->ci->session).

В начале исполнения запроса, когда отрабатывает конструктор Lib_csrf, в свойстве session содержится экземпляр библиотеки Native_session. Класс Native_session в качестве хранилища сессионной информации использует память сервера - $_SESSION. При начальной инициализации экземпляр Lib_csrf получает набор anti-forgery-маркеров из CI->session (а фактически из $_SESSION). Как правило, набор состоял из одного маркера. В случае, если возвращалось два, - проблема как бы "само собой пропадала" (тот самый лулз).

Далее в какой-то момент исполнения запроса значение CI->session перебивалось экземпляром класса CI_Session. Класс CI_Session в качестве хранилища сессионной информации использует куку ci_session (это название по-умолчанию) и при соответствующих настройках может также сбрасывать данные в БД.

Теперь собственно, как все происходит. В первой раз при вызове form_csrf из Lib_csrf достается один токен. Теперь у него внутренняя коллекция пустая. Для второй формы при вызове хелпера form_csrf токенов у Lib_csrf наготове уже нету и он пытается сгенерить новые. Запускается процедура генерации токенов, которая первым делом лезет в сессию и опять пытается достать текущий набор токенов. Только теперь обращение уже идет не к Native_session, а к CI_Session, - то есть, к коллекции, полученной из кукисов. А там содержится совершенно другой набор маркеров. В итоге второй форме возвращается какой-то токен, про который $_SESSION ничего не знает.

Проблема уже появилась. Теперь сабмитим форму (с токеном, про который $_SESSION ничего на знает), на сервере в конструкторе Lib_csrf выполняется проверка валидности токена. Но на этот момент, как было уже сказано, Lib_csrf работает через Native_session (а значит, через $_SESSION) и следовательно полученный с формы маркер будет расценен навалидным, - в $_SESSION его не содержится. Вот и получаем в итоге "Подозрение на атаку Cross-Site Request Forgery".

Thumbs up Thumbs down

3

Re: [Corp 4.5] Ошибка "Подозрение на CSRF" (form_csrf, lib_csrf)

Было приятно читать, разжеванный код.  cool

Сделаю обновления вашего магазина до актуальной версии системы со вем переносом ваших товаров, просьба писать в приват.
https://novabench.com/image/742206.png

4

Re: [Corp 4.5] Ошибка "Подозрение на CSRF" (form_csrf, lib_csrf)

Виновником ситуации с перебиванием сессионного объекта оказался метод captcha() библиотеки DX_Auth:

        $this->ci->load->library('session');

Достаточно его было закомментировать, и все проблемы разом пропали.

Но это еще ладно, DX_Auth, хоть и была виновата в порче сессии, но проблема-то на самом деле гораздо серьезнее:

1. либа lib_csrf оказалась уязвимой к невинным изменениям кода на стороне; кто угодно может вызвать у себя $this->ci->load->library('session') - в модуле, или в шаблоне, - в такой загрузке нет ничего криминального;

2. загрузчик MX_Loader вместо того, чтобы по коду "session" вернуть уже существующий зарегистрированный экземпляр, создал новый экземпляр другого класса.

PS: Пока искал проблему, заметил, что повсеместно вызовА load->library('session') закомментированы. Видимо, с какими-то сходными граблями в процессе разработки столкнуться тоже пришлось.
Кстати, попутно с проблемой подозрения на CSRF решилась также проблема и с капчей - на тех же самых страницах с двумя формами не валидировались абсолютно правильно введенные капчи.

Thumbs up Thumbs down

5

Re: [Corp 4.5] Ошибка "Подозрение на CSRF" (form_csrf, lib_csrf)

Я пробовал комментировать строчку

$this->ci->load->library('session');

но ничего не помогло.

Все равно выдает «подозрение» при отправке feedback на мультиязычном сайте.

Личная документация по ImageCMS: https://goo.gl/LzA09F

6

Re: [Corp 4.5] Ошибка "Подозрение на CSRF" (form_csrf, lib_csrf)

Роман пишет:

выдает «подозрение» при отправке feedback на мультиязычном сайте.

Если у вас на странице feedback нет другой формы, то скорее всего ваша проблема не имеет отношение к проблеме топикстартера. Здесь обсуждается проблема наличия двух форм на одной странице и сопутствующей ошибке CSRF.

Когда то разрабатывал модули для ImageCMS Corporate

7

Re: [Corp 4.5] Ошибка "Подозрение на CSRF" (form_csrf, lib_csrf)

Получается, мне лучше создать новую тему?

Личная документация по ImageCMS: https://goo.gl/LzA09F