Let's say that I have a single-page web app written in JavaScript and a server-side API, both changeable by me. The app calculates some values based on user input and POSTs these to the API. The values are based on user input but do not contain user input. For instance it might ask the user to pick A or B based on radio buttons, then send their choice to the server. There is no session, and the user is anonymous.
Rule #1 is Never Trust User Input. A malicious user could modify the payload, and change "A" to "C" (not one of the choices). I don't want that to happen.
For simple cases there is an obvious solution: validate the input server-side. If it's not "A" or "B", reject it. In a complex app, though, the number of possible permutations could make validation very difficult.
The app could digitally sign the calculated payload before sending it, but as the JavaScript is available to the client, a user could obtain both the key and the algorithm. Obfuscation isn't sufficient here.
Has anyone come up with any way to prevent this sort of tampering? Time-based keys provided by the server? Web3? Or is there a formal proof that it is impossible (aside from server-side validation against a set of input constraints)?
TL,DR: It's impossible to do so client side.
Client side validation is just a client convenience, not useful to really validate anything. You don't want the client to mistype his email, putting an invalid char somewhere, and have to wait the form being submitted, the server parsing it, and sending back an error 5 seconds later, you want the error to show instantly. You validate on the client, but you ignore the client validation entirely and validate again on the server.
If the validation is made client-side, the client may submit the request by hand, bypassing all validation. Even if you use hashing, signing, obfuscating or anything else, the result is an HTTP request and the client can intercept it and tamper it.
If your use case is what you asked, server validation it's not difficult at all. Have a table with all questions and all valid answers, and check every client answer with the table. On the first invalid answer you stop the processing and send back an empty page.
the number of possible permutations could make validation very difficult.
You have to choose between server-side (from trivial to very difficult) and client side (not possible at all). I believe the choice is easy.
cURL
is effectively a client, where the user can submit anything — Mar 07, 2022 at 08:40