I came across a simplified Page Token implementation, that did not keep its promise. It’s a good lesson on when to use Page Tokens and how.
In a recent pen test, I saw that a normal logged in user can access the admin pages too. I could do this by simply copy pasting the URL of the admin pages, after logging in as a normal user. The application treats the request as valid as it is coming from a logged in user and serves the page. The application did not check whether the user has the privileges to access the page. We could thus do an escalation of privilege attack.
The right thing is for the application to check the privileges of the user before serving any page. It can be implemented simplest by storing an authorization table in the database – which user/role may access which page. Whenever a user requests a page, the application should check whether the user has appropriate privileges in the authorization table. This is how an application can avoid simple attacks like we used to escalate privileges.
However, the client chose to implement a simplified page token to solve this problem. Here is how the client implemented it. When the user logged in, a random session id was assigned to that session. The application created a list that contained the pages the user is authorized to access. It then associated a 10-digit random token to each of those pages. These secret tokens are unique and valid as long as the user is logged in. The tokens are different for different users, and for different sessions of the same user.
The client called these page tokens.
[We discussed page tokens in Palisade last year. In the true page token implementation, the tokens change each time the user moves to a new page. It has a shorter lifetime than the session. In the simpler implementation, the tokens remain the same during the lifetime of the session.]
The application further encrypted this token using crypt package present in the Java SDK before sending across to the user. Now whenever the user requests for a page, it contains the session id as well as page token. The application will check the page token against the list of token present for that particular user. If the token from the user is not present in that list, the application logs off the session.
The solution works fine for avoiding privilege escalation attacks like the one we used. But it could have been implemented in a simpler method as explained above. It adds an extra overhead in the traffic as well as session. Again it does not serve the purpose of page token. True page tokens are short lived, with the life time between two consecutive page requests.
The authentic page tokens minimize the time window available for session hijacking, in addition to preventing URL manipulation attacks.
But in this case the time frame of session hijacking is the time as long as the user is logged in. So this simpler page token doesn’t actually serve the purpose of reducing that time window. It does mitigate the risk of URL manipulation. But like we discussed earlier, that can be achieved by just maintaining an authorization table and checking against it.