Pull to refresh

Защита веб-приложения на Phalcon + AngularJS от CSRF атак

Reading time 3 min
Views 5.8K
Привет всем! Не так давно столкнулся с проблемой защиты веб-приложения написанного на Phalcon PHP Framework вместе с AngularJS. Проблема заключалась в том что на странице есть несколько форм, которые посылают AJAX-запросы на сервер. Как подружить два фреймворка в вопросах безопасности, централизованного решения я не нашёл, пришлось его собирать по кусочкам из разных источников. И в этой статье я бы хотел предложить всем кто столкнулся, или столкнётся с такой проблемой, готовое рабочее решение.

Генерируем токен в meta-теге


К сожалению источника я сейчас не помню, но не раз замечал что между тегов частенько в meta лежали токены на крупных сайтах. Если вы посмотрите документацию Phalcon, то увидите что генерация токена происходит в форме. Вот так по-умолчанию генерируется токен в форме:

<input type="hidden" name="<?php echo $this->security->getTokenKey() ?>" value="<?php echo $this->security->getToken() ?>"/>

А что делать если формы две? На форуме было решение, но оно было с использованием сторонней библиотеки, что в моём случае не было хорошим решением, поэтому ещё немного порыскав на форуме, я нашёл решение генерировать токен в meta-теге.
<meta name="token" title="<?= $this->security->getTokenKey() ?>" content="<?= $this->security->getToken() ?>"/>


Крепим токен ко всем AJAX запросам


Прочитав документацию AngularJS по работе с токенами, там предлагается передавать токен в заголовке с именем X-XSRF-TOKEN, но увы в Phalcon нужно было писать отдельную библиотеку для обработки таких токенов. У меня нет на это времени, я ленивый, поэтому пришлось найти другое более просто решение.

var app = angular.module('selfmd', [], function ($httpProvider) 
{
    $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';

    $httpProvider.defaults.transformRequest = [function (data) {
        if (data === undefined) {
            data = {};
        }
        var token = $('meta[name=token]');
        data[token.attr('title')] = token.attr('content');
        return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
    }];

}

Помимо простоты, оно ещё и гибкое, ибо абсолютно все AJAX запросы, отправленные с помощью функции $http защищены токеном, который Phalcon легко и удобно воспринимает стандартными средствами.

 if ($this->security->checkToken()) 
{
        //Токен верный
 }


Возможные проблемы и решения


1. Если человек захочет посмотреть исходный код страницы (не через firebug, а в отдельном окне), то при загрузке с генерируется новый токен, и вернувшись на страницу ни один запрос не будет обработан. Возможно это и хорошо, нечего лезть в исходный код.
2. Если вдруг на странице не будет favicon, или же будет пустой background-image: url(""); то браузер запрашивая эти данные, с генерирует незаметно для нас новый токен. Я дня два или три потратил на то чтобы найти причину отказа токену, и меньше всего я мог подозревать блок с пустым background-image: url("");
3. А как защитить формы без AJAX, и без $http? Очень просто!
В контроллере добавляем новые скоупы:

    var token = $('meta[name=token]');

    $scope.token_id = token.attr('title');
    $scope.token_val = token.attr('content');

А в вьюхе выводим их в скрытом поле:

<input type="hidden" name="{{token_id}}" value="{{token_val}}"/>

Теперь все формы защищены, Phalcon доволен привычным ему данным, и не задействует лишних библиотек, а Angular без проблем цепляем ко всем $http токен.

Послесловие


Я далеко не специалист по безопасности, я не гуру PHP, я просто решаю задачи, которые возникают когда я занимаюсь любимым делом. Я не нашёл такого же удобного и понятного решения, именно поэтому мне захотелось им поделится. Это решение я использую в реальном проекте, пока не было замечено проблем. Скорее всего вы в комментариях укажите мне на ошибки, и я буду вам благодарен. С Phalcon и AngularJS я работаю с августа этого года, до этого я работал с CodeIgniter и jQuery, поэтому сильно не судите за такое решение задачи, если оно оказалось не таким крутым, как мне казалось.

Спасибо за внимание. Если вам интересно почитать про Phalcon, подписывайтесь, у меня есть ещё несколько полезных решений проблем при работе с ним.
Tags:
Hubs:
-4
Comments 21
Comments Comments 21

Articles