1

I have a use case where I need a factory-reset tablet device to install and run a simple Progressive Web Application (PWA). The tablet will be mounted on a wall inside a company building that may host unaccompanied external visitors from time to time. The PWA needs to initiate a websocket connection with a single JSON Web Token (JWT) to authenticate/authorize the connection. The PWA then just listens for new information coming through the websocket connection and displays it on the tablet. The intention is to show the currently-displayed information "publicly" to anybody walking by (including external visitors), without them having to do any kind of interaction at all with the tablet (indeed, no interaction will be supported in the PWA interface). I believe this is often termed a "kiosk display".

Although the information in the feed isn't anything particularly sensitive by design, we would like to prevent the case where a malicious person "inspects" the device (perhaps using a laptop, a cable and relevant software tools) and manages to obtain the JWT. The attacker's aim would be to duplicate the connection on another device, allowing them to record data from the feed for an indefinite period of time after they've left the building.

A key requirement of the the PWA is that it should continue to function (i.e. continue to show the feed information) even if the device is restarted (e.g. after an Android/iOS update), the PWA "refreshed" (sliding finger down), or the PWA closed and re-opened.

Our current thinking for securing the setup is along the lines of:

  1. When the admin first installs the tablet, they go through a "pairing" process using a back-end system. They do this by opening a normal browser (e.g. Chrome) on the tablet and navigating to a certain HTTPS URL. The webpage will ask them for an identifier of the feed they want to connect to, as well as the current short-lived "pairing verification PIN" that the admin can only see when logged into the back-end dashboard (they'd be looking at this dashboard on another device).

  2. When the admin submits the information (regular form POST), the server validates it and, assuming success, redirects the browser to another page that contains a unique and unpredictable link to the dynamically-generated PWA manifest for that unique pairing operation. Specifically, the start_url property in the PWA manifest includes an encrypted query string containing JWT for initiating the websocket connection.

  3. From that page, the admin then just installs the PWA to the device and closes the browser they were using.

  4. The admin then starts the PWA, which makes the websocket connection (because it can get it from the query string of the start_url) and starts displaying the information. The PWA will continue to work after refresh/restarts because it will always just have the same start_url with the JWT in it.

Now even though the PWA will be in "standalone" mode and it won't be possible to easily see the "address bar", it seems to us that it's probably still possible for somebody to "inspect" the device and either manage to find the PWA manifest somehow, or manage to inspect the current URL of the running PWA, either of which would expose the JWT.

The second part of our idea, to help prevent the consequences of this, is to have the websocket server deny any attempt to make a second active connection with the same JWT. That is, when validating a connection request, the websocket server will check to see if there is already an existing connection open that was made with that JWT, and deny it if there is. The intuition here is that an attacker, even if they were able to get the JWT, would have to stop the PWA on the wall tablet in order to be able to establish a connection on their other device. After a short time, people in the building would soon realize there's something wrong with the tablet, and realize that they aren't able to start its PWA. They'd then go through a fresh pairing process (which involves the server killing all active connections, including the attacker's, thereby resolving the problem).

My question: Assuming that the core elements of a 1) "public tablet", 2) a PWA and 3) a websocket connection with JWT are non-negotiable, is there any other approach that might be more secure? Said otherwise, is there any mechanism that would allow us to store a JWT in such a way that the PWA could use it as required to make (and re-establish as required) websocket connections, but without it being "inspectable" by somebody who physically had control of the device?

If there's no better way, are there any practical security risks of the approach I've described that I may not have thought about?

Finally, am I right in stating that "native" mobile apps might have advantages over PWAs in this respect, because "native" apps are able to use more of the device's features and could potentially store "secrets" in a more advanced way than a PWA can?

sammy34
  • 113
  • 3

1 Answers1

2

The typical assumption to make with physical security is that if someone has physical access to a device and it is not off and encrypted, then they can access all of the unencrypted data and run arbitrary code on the device. You can try to make it more difficult to exploit, but a dedicated adversary will likely succeed nevertheless.

You also need to consider your threat model here. If this information is publicly visible to external visitors, it is probably going to be publicly known, and therefore spending a large amount of time securing it doesn't gain you much of anything. Even if those visitors are under NDA, you may determine that the information is not very valuable (for example, it shows public information, information which will likely become stale or irrelevant quickly, or information whose disclosure has negligible financial or personal value) and determine that a lower level of security may suffice for your needs.

However, if you still need to secure it, you can adopt the approach you mentioned. You could also try to use some sort of asymmetric key in a secure enclave to sign the Websocket requests, and send the public key during the initial pairing step. That would at least mean that an attacker probably would not be able to extract the key and use it elsewhere, and as a result they would have to exploit your kiosk device on an ongoing basis.

bk2204
  • 7,828
  • 16
  • 15
  • Thanks for the very helpful answer! Considering that the information being displayed in our case has negligible financial or personal value and does become stale quickly, we probably won't bother with spending the extra effort on an asymmetric cryptography approach. The extra work required to restrict the number of active connections to one for a given JWT (i.e. the approach I suggested) is however relatively low, so we'll probably go with that. – sammy34 Aug 15 '21 at 10:14