Blogs & Stories

SpiderLabs Blog

Attracting more than a half-million annual readers, this is the security community's go-to destination for technical breakdowns of the latest threats, critical vulnerability disclosures and cutting-edge research.

When User Impersonation Features In Applications Go Bad

A user impersonation feature typically allows a privileged user, such as an administrator, but typically these days, support teams, to sign into an application as a specific user without needing to know the user’s password. This feature allows support teams to see the application as the user would see it, often in relation to following a user journey in the context of that user, in order to see the same error message a user is receiving with a view to resolving the issue. I’ve also seen this functionality over the years created solely by development teams so that they can quickly switch users (and roles) to assist with development of an application, without having to keep authenticating every second. In this instance, the feature is often kept in as a legacy thing, no longer used or referenced in the UI, but handlers exist in the code, and you’ll only find out about its existence by references in the JavaScript code or old CSS relating to UI elements.

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.

Ponder us logged in as the malicious user “venom”. We look through the JavaScript code and CSS and find references to “impersonate”. Now we (as venom) request the resource “/editprofile.aspx?impersonate=true&userid=spider”. The server will return the edit profile page in the context of the “spider” user, populating spider’s details such as name, e-mail address, etc. This is a magical route for account takeover because the attacker (venom) can simply update spider’s e-mail address to be one they own and can then utilize the forgotten password functionality and log into the application as them. Now imagine this spider user is an administrator of the application, so in doing so, the attacker gets access to the account with access to administrative functionality, previously blocked by the traditional black and white access control methods.

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!

What can pentesters do to make the problem appear? Search in HTML, JavaScript and CSS (search all the things!) for anything named “impersonate”. Also, a bit of a long shot, but blindly trying these parameters (and variations of them) when making requests might result in some success.

As always, thanks for reading!