I encountered an issue of data inconsistency which is potentially a security issue.
Here is what happened:
-
A user (UserA) is logged in in on tab of the navigator. This tab sends POST requests to the server.
-
In another tab of the navigator, another user is logged in. In my case this is done through an url generated from the backoffice which acts as a login process.
-
After the other user (UserB) is logged in in the second tab, the first tab sends a post request to the server. The server validates this request as a request of the second user because of session/cookie information, and validates the CSRF token because the CSRF token did not change.
Analysis:
-
Changing the user does not change the CSRF token.
-
The post operation of UserA in the first tab is validated because the CSRF token is ok, and is attributed to UserB because the Session/Cookie says it is UserB.
-
The session does not seem to be detroyed when changing a user - it may be destroyed when the user logs out.
-
Calling ‘login’ does not destroy the session. I haven’t checked if a session is tab specific - I suppose it is not.
My current solution/workaround is to force a change of the CSRF token when the user changes. So my extension of the CWebUser class now has the following code:
protected function changeIdentity($id, $name, $states) {
parent::changeIdentity($id, $name, $states);
$request=Yii::app()->getRequest();
if($request->enableCsrfValidation) {
$request->getCookies()->remove($request->csrfTokenName);
}
}
I do not particularly like this code because it supposes the CHttpRequest works a certain way, but I did not see a better way to do this for the moment.
Identifying this explains some of the strange behaviors I have seen in the past in my web application. I am happy that I could finally pin it down.