Back in days, things were simple: with jQuery you typically operated on DOM nodes in HTML page that was generated and served by your backend. All your data belongs
to us to server-side, perfect! The modern reactive applications are based on the concept of state. The UI that you see in your browser is the representation of the current state. State is modified with actions that are triggered by the user. Basically, your interaction with the application is just a series of actions modifying current state, you can move backwards in history, commit new actions, reset the state, etc.
So, what’s the problem with this approach? Universal applications share the same state between client-side and server-side, and web developers fail to properly separate data. Usually, the code which should be run on the server and the client is separated with a special environment variable.
However, it is up to a web developer where to place that if condition. If you fail to use it properly, most likely you have got an information leakage. Here is an example of someone else’s data that I can view on some popular site:
Typically, universal applications are written with React and Redux. React is a view library and Redux is a library for managing state. There are several browser extensions that help developers to debug their React applications. With Redux Dev Tools extension you can view the whole state if it is exposed to the extension via a window property:
With the extension installed, you will see a green icon in your Chrome extension bar if the property is available.
You will be surprised to learn how many web sites use Redux Dev Tools without stripping this window property.
If the web app is good enough to not expose the property, you can still view the state with React Dev Tools extension. Just look at the tree and navigate to the Connect node which is a Redux function to pass the state to React components.
By manipulating state you can uncover the hidden components and better learn the internal structure of the web application. Things are even worse if the web app uses GraphQL, which is a modern query language for the APIs. The idea behind GraphQL is that client knows which data it needs so it can request basically the whole database from the server. See? Without proper authorization it will surely lead to information leakage. GraphQL docs have an awkward statement on it:
However, for a production codebase, delegate authorization logic to the business logic layer.
Again, framework does not provide any means for securing your data, it is the developer who is in charge. Let’s see what happens next!