Whenever I hear about an impersonation feature existing in an application, I get those spidey hacker senses tingling because more often than not, I am able to abuse these and use them as a direct path to vertical privilege escalation through arbitrary account takeover.
Ultimately this issue boils down to an access control issue and you would think it is an easy one to solve, but how these impersonate functions work is a little bit of a, how should I say it, Inception film plot? Let me explain.
Access controls aka authorization - either your name is on the list and you’re coming into the club or your name is not and you’ll have to move on (to the pub down the road). Take implementing access controls against administrative functionality around user management as an example. You’ll not want normal users to be able to add, edit and remove arbitrary users – so you implement a check to say if the user doesn’t have the admin role then don’t load this page. It is pretty black and white.
Now, when it comes to impersonate user functionality, the way I tend to always see this implemented (the bad way) is as follows. Each resource (typically a page) being called checks for additional parameter(s) sent by the user either in the POST body or GET request (URI). It then uses this to load the page in the context of that user, based on these parameters. The parameters are typically something like “?impersonate=true&userid=spider”. There is often the concept of starting and stopping impersonation, so the true/false toggle exists. It may be that a similar setup exists but instead of parameters it is occurring within cookies, e.g., “Cookie: impersonate=true; userid=spider;”.
Once you understand the above, you can obviously see (or hear!) the alarm bells right away, but also understand why it is hard to implement access controls in the more traditional sense. The problem (or challenge) for developers is that a normal user will (and should) be allowed to access a page like “editprofile.aspx” (as an example) because the user may want to change parts of their profile; their name, e-mail address, etc. The page itself isn’t privileged and you want the user to be able to access this page. You therefore can’t implement the same sort of access control like you would with a clear-cut case, like “/admin/” (to protect user management pages, etc.) - the old school way. This is what I think trips up developers – it is authorization, but not as we know it, Jim. The security problem comes when that same page has support for user impersonation – that page suddenly got supercharged from an attacker perspective.
Will the real slim spidey please stand up?
What can developers do about making this problem disappear? Ensure all impersonation features are locked down to only those users authorized to call them. For example, it may be better for a central page to make the calls, which is then able to (each time) do authorization checks of the caller (requesting user), e.g., “/impersonate.aspx?page=editprofile.aspx&userid=spider”. However, care needs to be taken implementing it in this way too. There is a tendency for developers to inadvertently create Server-Side Request Forgery (SSRF), Path Traversal and possibly Local & Remote File Inclusion (LFI/RFI) vulnerabilities with this approach – as always, validate all the things!
As always, thanks for reading!