Как сделать формы в CakePHP более безопасными

December 3, 2008 | By admin | Filed in: CakePHP, Переводы.

Если кто не знал, teknoid пишет отличные статьи про кейкПХП. А пока я не могу так же, продолжаем серию переводов. На этот раз данный пост.

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

Начнем с основ, а потом немного все усложним…

Для начала рассмотрим простую модель:

class User extends AppModel {

var $name = 'User';

var $validate = array(
'name'=>array('rule'=>'notEmpty'),
'email'=>array('rule'=>'email'),
'password'=>array(
'Cannot be empty' => array('rule'=>'notEmpty'),
'Must be at least 4 chars' => array('rule'=>array('minLength', 4))
)
);
}

Здесь у нас определены несколько правил валидации (заметьте, отсутствует правило ‘required’=>true, которое запутывает некоторых людей и является для них источником проблем).

Теперь представим себе злого хакера, который хочет путем различных манипуляций с полями формы, например, сохранить пустое значение для поля ‘name’ в БД. Если мы не защитим форму, ему будет очень просто удалить поле из массива данных (используя какую-нибудь простейшую хакерскую программу), а из-за этого валидация поля проводиться не будет, следовательно, данные будут сохранены с пустым полем “name”.

Так как же нам избежать подобной ситуации, используя компонент Security?

Создадим контроллер:

class UsersController extends AppController {

var $name = 'Users';
var $components = array('Security');

function add() {
if(!empty($this->data)) {
$this->User->save($this->data);
}
}
}

И простое представление для действия “add”:

echo $form->create();
echo $form->inputs(array('name', 'email', 'password'));
echo $form->end('Register');

Довольно просто, да?
Мы уже обезопасили нашу форму при помощи всего одной строки кода:

var $components = array('Security');

Давайте объясню, что при этом происходит внутри…

Компонент Security создает хеш, основанный на полях формы, которые создаются хелпером Form. Если кто-то пытается производить махинации с полями (добавляя, удаляя, или изменяя поле), хеш не будет совпадать с тем, который ожидает компонент, и действие add() выполнено не будет.

Да, все так просто. Можете попробовать поиграться с формой, используя, например, вот этот аддон для ФФ: https://addons.mozilla.org/en-US/firefox/addon/1290.

Как вы можете заметить, действие не выполнится, при этом никаких ошибок пользователь не увидит (в большинстве случаев результатом будет пустой экран). По-моему, вполне достаточно для… таких пользователей. Зачем делать приложение дружественным для них?

Но давайте все-таки пойдем им навстречу. В любом случае, это хорошее упражнение.

Для начала мы расширим контроллер методом beforeFilter():

 function beforeFilter() {
$this->Security->blackHoleCallback = 'fail';
}

Строка $this->Security->blackHoleCallback = ‘fail’; сообщает компоненту Security, что нужно вызвать определенный нами метод fail() в случае, если кто-то попытается взломать нашу форму.

Создадим метод fail():

function fail() {
$this->cakeError('youSuck');
}

Данный метод, в свою очередь, вызовет метод youSuck(), который нужно определить в обработчике ошибок app_error.php.

Так что если у вас его пока нет, создайте файл app_error.php в папке /app/.

class AppError extends ErrorHandler {
function youSuck() {
$this->controller->set(array(
'name' => __('You are an evil person', true)
));

$this->__outputMessage('bad_user');
}
}

Теперь нам нужно представление bad_user.ctp, которое нужно разместить в /app/views/errors/bad_user.ctp

[вордпресс глючит, код вставить не получилось]

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

Надеюсь, вы поняли, как компонент Security помогает усилить безопасность вашего приложения при помощи всего лишь 2-3 строк кода. Мы также рассмотрели небольшой пример собственного обработчика ошибок.

[комментарий к посту от Nate Abele]

Использование $this->Security->requireAuth(’add’); добавляет еще один тип защиты. По умолчанию (без вызова разных методов) компонент Security генерирует хеш для форм для проверки на хакерские манипуляции. Добавление requireAuth(), с другой стороны, записывает случайный хеш в сессию, и этот хеш также добавляется в форму. При POST-запросах эти хеши сравниваются. Это защищает от атак CSRF, а также является единственным видом защиты, который будет работать (?) с Ajax или в случае с несколькими вкладками браузера.


Tags: , ,

One comment on “Как сделать формы в CakePHP более безопасными

  1. teknoid says:

    спасибо за переводы 😉

Leave a Reply