Understanding frontend — security

Bartosz Szczeciński
4 min readSep 23, 2018

--

Source: http://www.itv.com/news/meridian/2016-04-25/simons-blog-funny-signs/

The topic of security on the frontend part can be separated into two purposes:

  • keeping your client and their data secure
  • keeping your clients away from things they should not have access to

The first part is a very vast topic that covers things like cross-site-scripting (XSS), cross-site-request-forgery (CSRF), CORS and other topics related to how browser keep your data from leaking out to attacker or preventing attacker from performing actions in your name.

The second part is more concerned with “how do I limit my users from accessing certain parts of my site” — things like members only section, admin panel etc.

Are variables in browser secure?

Your first idea might be “I’m going to create an isAdmin variable, set it to true whenever an admin authenticates and then check it in my application.

But once you implemented that solution — a question hits you — “What if the user just opens developer tools and changes it to true on his end? How can I prevent that? Should I use localStorage, sessionStorage or is there something more secure?”

We need to make one thing clear — everything you put in the client browser can be easily changed by the client. The browser — by default — gives an attacker all the tools he needs. He can open the devtools and change all the in-memory variables. He can manipulate localStorage, sessionStorage, cookies and with the correct extensions even React components state. He can also substitute the response of the auth endopint and just make it response with {isAdmin: true} every time.

You might think that you could use some form of encoding — either roll out your own, or use JWT which you can then verify in the browser for any modifications. This approach is also flawed, because you would need to make the browser aware of the mechanism (keys) used to generate the signature — else the attacker would just need to make up his own keys, change the isAdmin field in the JWT and sign it with his key — the signature is valid, the browser accepts the JWT as legit and trusts that the user is an admin.

How do I prevent the user from accessing non-public parts of my site?

You do it exactly as you though to do it — you create a variable, set it to true for admins only and once the check passes, show the admin only content.

“Ok, that’s not secure at all — everyone can then go to the admin page and delete everything!” you scream.

Fair — but only if you implement your application in a bad way. The frontend part should not be concerned with the validity or not of credentials provided. It should always accept the data as “true” and just render all the data it is passed.

It it’s the backend job to perform this validation!

Your UI can have a “Delete database” button. You might even try to hide it with some logic, but an attacker can download the JavaScript code and look for all endpoints — he will find http://example.com/api/database/delete URL (this is only for the sake of the example, you should always use CRUD notation anyway :)) and call it manually. If this operation ends up in deleting your database — you seriously need to add more security to your application.

In similar vein, your application can render members only content under /members/blogpost/read-up-on-all-the-new-things — the attacker can always navigate to it directly. If he were to see the content, that means your API (or other forms of content delivery) is not designed correctly — the attacker should be then redirected to /sign-up right away, or in the worst case he should see an blog post template without any content loaded.

Backend is the deciding factor

In both cases above, the attacker is able to get into gated-off content, but he is unable to perform the operation associated with the action. All of them should communicate with the backend and contain some form of authentication (am I who I say I am) and authorization (can I perform this action) mechanisms.

If the action is permitted, perform it and reply with a proper HTTP code (e.g. 200), if it’s not permitted, reply with an HTTP error code — e.g. 401 (not authenticated) or 403 (not authorized). Your frontend should respond to this and either let the user know he’s doing something he has no authorization to (show an error message, redirect to a login screen) or just fail gracefully (render an template with no content or *gasp!* — Published at: <date>undefined</date>).

--

--