[PT-BR] Proteção Contra Logout CSRF

  1. Visão Geral
  2. Tutorial: Como se livrar do Logout CSRF no Yii
  3. Nota
  4. Referências

Visão Geral

CSRF

CSRF é o acrônimo para Cross-site request forgery.
CSRF é um ataque que forca o usuário a executar ações não desejadas numa aplicação Web na qual ele está autenticado.

Para ajudar a mitigar a ameaça, todas as requisições que causam efeitos colaterais devem ser protegidas.
Medidas de controle incluem o uso de tokens de validação em forms.

Logout CSRF

Este tipo de CSRF explora o fato de que a URL de logout está usualmente desprotegida.
O Logout CSRF não representa uma grande ameaça, mas é irritante para os usuários.

Logout CSRF e o Yii

O Yii é um framework bastante seguro. Mas na versão 1.1.7 (e possivelmente outras), o código gerado pelo comando "yiic webapp" não é protegido contra o Logout CSRF.
Quando você habilita a validação de CSRF, todos os forms terão um token de validação e estarão mais protegidos contra CSRF, mas o link de logout não é um form e permanece desprotegido.
Se você quer ajudar a proteger os seus usuários contra esta irritação, siga o tutorial abaixo.

Tutorial: Como se livrar do Logout CSRF no Yii

A estratégia adotada nste tutorial é ter um link único para cada usuário. Nós vamos alcançar isso usando o token do Yii e validando-o antes de efetivamente fazer o loout do usuário.
Siga os três simples passos abaixo.

1. Habilite a proteção para CSRF

Para habilitar a proteção padrão do Yii contra CSRF, configure o componente CHttpRequest como o código abaixo:

return array(
    'components'=>array(
        'request'=>array(
            'enableCsrfValidation'=>true,
        ),
    ),
);

Veja a documentação de CHttpRequest::enableCsrfValidation para mais detalhes.

2. Adicione o token no link de logout

Vá até o seu arquivo de layout e altere a rota para o link de logout. Você precisa adicionar o parâmetro token. O seu valor virá do cookie de CSRF, usando Yii::app()->getRequest()->getCsrfToken()
O código vai ficar parecido com:

array('label'=>'Logout ('.Yii::app()->user->name.')', 'url'=>array('/site/logout', 'token'=>Yii::app()->getRequest()->getCsrfToken()), 'visible'=>!Yii::app()->user->isGuest)

Faça o mesmo quando criar um novo link para a ação de logout.

3. Adicione o token de validação na ação de logout

Na sua ação de loout (por padrão em SiteController), adicione o parâmetro $token ao método, como abaixo:

public function actionLogout($token)

O parâmetro $token receberá o token do parâmetro GET.
Adicione o código de validação no início do método:

if ($token !== Yii::app()->getRequest()->getCsrfToken())
	throw new CHttpException(400, Yii::t('app', 'Invalid request. Please do not repeat this request again.'));

No final, o método ficará parecido com:

public function actionLogout($token) {
	if ($token !== Yii::app()->getRequest()->getCsrfToken())
		throw new CHttpException(400, Yii::t('app', 'Invalid request. Please do not repeat this request again.'));

	Yii::app()->user->logout();
	$this->redirect(Yii::app()->homeUrl);
}

E os seus usuários estarão um pouco mais protegidos!

Nota

Este tutorial não tem a intenção de cobrir todos os aspectos do CSRF.Por favor leia as referências abaixo para entender melhor este tipo de ameaça.
Eu não afirmo que ao seguir este tutorial você estará 100% protegido contra o Logout CSRF ou outra ameaça de segurança. Nada é 100% seguro. Por favor leia as referências abaixo, elas são um bom início. A informação é a sua melhor ferramenta.

Referências

O artigo original, em inglês.

Yii guide: Security. Leitura necessária.

CSRF na Wikipedia

CSRF no OWASP

Documentação de CHttpRequest