Open giovaz94 opened 6 years ago
You should use separate csrf cookie additionally to identity cookie.
Added configuration for csrfCookie:
'request' => [
'csrfParam' => '_sitenameCSRF', // Modified params
'csrfCookie' => [
'httpOnly' => true,
'path' => '/backend',
],
],
Problem is still occurring. validateCsrfTokenInternal can't verify tokens because $clientSuppliedToken() and $trueToken() are different.
Do you have any AJAX calls?
Yes, I've got a Ajax call in the page after the login but is handled with _csrf :
$.ajax({
url: '".$dashUrl"',
cache: false,
method: 'POST',
data: { uuid : window.name, _sitenameCSRF: yii.getCsrfToken() },
dataType: 'json'
});
Problem is still persisting.
I know that error is throwed on line 166 of yii/web/Controller in the beforeAction() method but , being a 400 error should be a client error ? List of status code.
Trying to login and logout multiple times with different Browsers I've noticed that on 10 attempts the error shows up:
Safari 12.0 => 1 time on 10 attemps (with clear cache and all cookies deleted), Google Chrome 69.0.3497.100 => 4 time on 10 attemps (with clear cache and all cookies deleted), Mozilla Firefox 62.0.3 => 3 time on 10 attemps (with clear cache and all cookies deleted),
I don't know if this information is relevant considering that Client and Internal csrf token is generated by Yii.
Well, I'm afraid we can do nothing about it since we don't know how to reproduce it.
That could be some kind of pre-fetch from the browser that asyncronously refreshes the token...
just to confirm that we are also experience the exact same issue.
yii2 2.0.15.1
In Login Page.
there's a custom ajax requesto to refresh the verification code (the Captcha Widget from yii2)
randomly users get the same error, but they seem to be logged in.
Experienced with Chrome latest version, Firefox latest and on Edge..
@njasm yes, seems similar, don't know in your case if this can be also caused by the ajax sending wrong _csrf token but in that case i think you'll get a console error.
Anyway user randomly get the error but with a refresh of the page they seems to logged in. Don't know what cause this behavior.
Ok, seems that the error is caused by regenerating _csrf token in login method on yii\web\User class on line 261.
I've overwriting this method and removed the line ( so it doesn't regenerate the token). This makes application doesn't cause the Bad Request error but also generate a security issue.
Any solution for this ?
Can you reproduce it w/o AJAX?
Consider the reason for prefetching of favicon.ico https://segmentfault.com/q/1010000004450797
Yii2 2.0.15.1 Advanced Template. The same issue on login page. Can't reproduce, because saw it about two times for 3 months
Yii2 2.0.15.1 PHP 7.2.10
Today, too, faced with this problem. This only plays on the server, I can't repeat locally.
Moving to 2.0.17 since it's not clear how to reproduce it and what causes it.
Confirm this issue on PHP v7.2.x on my server environment but does not happen on PHP 7.1.x on my local environment with the same latest yii2 version involving ajax call. Is it something to do with the PHP version?
Ah ok - I think I debugged the source of the problem. Its not CSRF but apparently the exit
in PHP 7.2.x is different.
If you have a controller action for an ajax response that returns a JSON like this - you may get a bad request in PHP 7.2
public function actionAjaxOutput()
{
echo \yii\helpers\Json::encode(['output' => 'something', 'message' => 'something']);
// this will throw a bad request in PHP 7.2
}
Instead change the above code to something like below:
public function actionAjaxOutput()
{
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ['output' => 'something', 'message' => 'something'];
// works fine in PHP 7.2.x
}
I'm using that option. Everything is fine PHP 7.2.x
[
'class' => ContentNegotiator::class,
'formats' => [
'application/json' => Response::FORMAT_JSON
]
],
Always return in controller, echo will cause problems.
Faced with same problem recently on login and signup pages.
[yii\web\HttpException:400] yii\web\BadRequestHttpException: Unable to verify your data submission.
This message shows up randomly in the log file for some users. My idea is that users has slow Internet connection and they hit "Login" button many times which causes CSRF to regenerate.
I made a small screencast how to reproduce the issue in the fresh Yii2 Advanced template install. Also I enabled Network Throttling = Slow 3G in the Chrome dev tools. Please take a look: http://recordit.co/a4XN1oASDR
Any ideas how to fix that?
You could disabled the submit button with javascript
$('form').on('beforeValidate', function (e) {
$(e.target).find(':submit').prop('disabled', true);
}).on('afterValidate', function (e) {
$(e.target).find(':submit').prop('disabled', false);
});
You could disabled the submit button with javascript
$(document).ready(function() { $("form#my_form").submit(function() { $('button[type=submit], input[type=submit]').prop('disabled',true); return true; }); });
Nice workaround, thank you!
Moving to 2.0.17 since it's not clear how to reproduce it and what causes it.
привет так же столкнулся с аналогичной проблемой Yii2 version 2.0.14.2 при первой загрузке страницы (т.е. пользователь впервые зашел)
возникает это вот почему: protected function regenerateCsrfToken() { $request = Yii::$app->getRequest(); if ($request->enableCsrfCookie || $this->enableSession) { $request->getCsrfToken(true); } }
здесь vendor/yiisoft/yii2/web/User.php происходит перегенерация токена и кука изменяется а токен в метатеге и скрытых полях форм остается старым
страница на которой это можно обнаружить должна отправлять аякс запросы
есть вопрос зачем в этом методе вызывается $request->getCsrfToken(true); с $regenerate = true ? пока что решил проблему перегрузив метод но хотелось бы знать что будет в будущих версиях чтоб не навредить
зачем в этом методе вызывается $request->getCsrfToken(true); с $regenerate = true ?
Чтобы нельзя было воспользоваться токеном отлогинившегося пользователя. См. #15783
привет)
зачем в этом методе вызывается $request->getCsrfToken(true); с $regenerate = true ?
Чтобы нельзя было воспользоваться токеном отлогинившегося пользователя. См. #15783
но дело в том что сейчас это создает проблемы только для "честных пользователей" в ситуациях которую я описал выше при первом заходе на страницу где после загрузки страницы происходят аякс запросы. значение куки изменяется в этом случае а токен в метатеге и скрытых инпутах остается старым.
наверное это не очень здорово так делать я вот поотлаживал и вижу что устаревшие пары кука + токен - все рабочие и с ними можно проходить цсрф защиту - т.е. для "недобросовестных юзеров" (для которых цсрф и включаем) проблем нет - один раз можно получить пару и спамить с ней сколько влезет.
вот на скринах как выглядит тест: https://monosnap.com/file/kKApRHVS2N7ykLkZMXXs3GLXRPk3DB - взял 4 пары кука + токен и прогнал через цсрф защиту https://monosnap.com/file/ithyKc1Cc1QSyHXi7T3edA6B3HaYkm - все 4 пары успешно проходят защиту
т.е. в текущей реализации перегенерация не добавляет стойкости цсрф защите но создает проблемы при штатном использовании сайта где она используется (только при первом посещении за сессию и если со страницы после готовности идут аяксы)
поэтому пока что выкрутились перегрузив этот метод: public function getCsrfToken($regenerate = false) чтобы перегенерации не происходило если токен есть в куках
Same issue. Can this be related to a reverse proxy (such as Apache Traffic Server - cached page with form and old CSRF token)?
Absolutely. CSRF token can not be used with full page caching on proxy level.
Absolutely. CSRF can not be used with full page caching on proxy level.
1) I reloaded CSRF token in form via AJAX call with timestamp parameter (to bypass the proxy cache):
$.ajax('/customer/login?t=<?= time() ?>', {
success: function (data) {
let token = $(data).find('form > input[name="' + yii.getCsrfParam() + '"]').val();
$('form > input[name="' + yii.getCsrfParam() + '"]').val(token);
}
});
2) I added hidden input in form view with date and time:
Html::hiddenInput('timestamp', date('Y-m-d H:i:s'))
And date and time is actual. Form is not loaded from the cache. It is freshly generated and there are still problems with the CSRF token. I really don't know where the problem is.
It could be that something is doing more AJAX requests in background and triggering CSRF token regeneration so token is obsolete by the time you are using it.
How to solve this: the user opens 2x login form in two tabs:
That is expected from CSRF protection. If you absolutely don't want this behavior then disable it.
I don't want disable CSRF protection, this worked for me:
public function beforeAction($action) { if($action->id === 'login' && Yii::$app->user->isGuest === false){ $this->redirect('index')->send(); exit; } return parent::beforeAction($action); }
I hope this solves random CSRF token validation errors. We'll see ...
From time to time, I also encounter that bug on the login form. But what I'm worried about, is that the password is stored in plain text in the log file! See this issue #8763 for instance. The op has a "Bad Request exception" after submitting the login form, and inside the log file, we can clearly see the password in plain text.
I experience the same issue, here is a partial copy-paste of the log file :
2020-09-23 15:53:32 [192.168.1.101][-][-][error][yii\web\HttpException:400] exception 'yii\web\BadRequestHttpException' ... Stack trace:
0 ...
... 2020-09-23 15:53:32 [109.130.141.39][103][dhpo7eeq655jg9mn99dd68q3j5][info][application] $_GET = []
$_POST = [ '_csrf' => 'oZzuAvpt8vRwdG_sjg6ij4mCP7Mxm4v_oL--gWU4SUbIy7EwlFjAwTksW438ff325_dV_wboyq_uj8fHUAAkLQ==' 'LoginForm' => [ 'login' => 'user_AT_hotmail.com' 'password' => 'mySuperPasswordInPlainText' 'rememberMe' => '0' ] 'ajax' => 'LoginForm' ] ...
I know it's not a bug 'per se', but I think this can lead to a security issue. How can I prevent that to happen? How hard would it be to mark the password with ** (6 star signs) as default?
Related to https://github.com/yiisoft/yii2/issues/16295
Hi! I've started to get the same error 400 - on some of POST requests, made with jquery. My problem was that the code from yii.js ( initCsrfHandler() ), which should initialize csrf headers for all requests was executed later than executed jquery requests.
What steps will reproduce the problem?
Also I have 'cookieValidationKey' property setted :
What is the expected result?
Login in the application.
What do you get instead?
Additional info
This issue appear Randomly, sometimes I can login successfully and sometimes not. On getting the error reload resolve the problem; I'm redirected inside the application and the user is logged. Disabling csrfValidation resolve the problem but it compromise the application security.
I dumped the function that validate the token:
In some cases variables $clientSuppliedToken and $trueToken have different values causing validateCsrfTokenInternal to return FALSE.
Also reporting this similar issue: 353181592