Check if user changed POST request

Asked

Viewed 245 times

2

I have a javascript application that runs on the client side, in this application the user can trigger events that communicate with the server of my site through a POST request. However, I need to ensure that the user does not have wrought the data prepared by this application of mine. For example, the user can intercept the connection before it exits his machine and change the attributes of the variables I am going through POST.

In another example: we can assume that this variable is a punctuation and the actual information is credited 10 points in the account of a particular user, but it can intercept this communication, change it and send a false request for the server to credit 1,000 points. This is not a validation error, because both values are numerical and therefore will be accepted on the server, it is also not SSL, because the user himself is acting in bad faith, changing the data before they leave his machine. How can I validate this data to know if it was manipulated? I’ve seen some sites using hash for this, but I don’t quite understand how this can be done.

  • 1

    You can encrypt the client-side data and decrypt on the server-side.

  • @Alisson, exactly, I had thought of it using jCryption, because I can’t leave a symmetric key exposed in my client-side code.

  • 1

    You can leave the methods all on the server side, and do only "triggers" on the client side, with the encrypted parameters, any parameter that arrives in the method and gives conversion failure, you automatically do not perform the operation and back to the client

  • @Miguelneto, I’ve thought about this too, but I believe that the client can tamper with the data before it goes through the encryption, but of course this is still an extra barrier, a mere palliative. As for triggers, if the Urle client encrypts and discovers the triggers I send to the server, I will have big problems.

2 answers

5

Sensitive information should never depend on client-side¹ because Javascript encryption is useless.

The transparency offered by current browsers makes all your code and information readable and alterable in a few clicks. This does not mean that older browsers made the web safer. On the contrary, it was formerly easier for a developer to believe that his application was safe when using any kind of complication like Javascript encryption, compiled application (Flex/Actionscript), among others.

CSRF tokens can help you prevent someone from forging a call to your server from another source (Curl, CORS, etc.), but they will not guarantee that the other information being trafficked is intact as expected.

You can use a combination of CSRF and SSL/TLS to encrypt the connection between client and server, avoiding possible tampering with javascript files and ensuring that the response came from your application, but still doesn’t justify relying on the client-side provide sensitive information.

Updating

Responding to the comment, any security mechanism you can think of using Javascript in browsers has been thought of before, it is not a lack of idea, but rather the mechanics of how Javascript works in the browser. Even if you create a public key from the server for the client to use this key and you ensure that the information has been encrypted using a valid key, the end user still has the information before and afterward to encrypt it. The same facility to forge data that does not represent reality with and without such a mechanism is the same, as the customer will only tamper with the information before it is encrypted.

If you are depending on your secure information client, you need to rethink your application.

  • What action does the customer take that guarantees him the right to points?
  • Who has a financial obligation to create this score?
  • They are multiple actions, each with a different score value?
  • The same action may result in different scores?
  • A person is able to get points while offline and sync when online?

Every question you can think about your model will be able to better specify where your problem is. If your customer earns offline points, you need to think about coupon forms, such that a coupon has a generated code that makes it mathematically unlikely that anyone will be able to "find" it at random. If your customer earns points when making a purchase, it may be the responsibility of the establishment itself to guarantee the authenticity of the information. If a specific action is only able to generate a specific amount of points, that score can be stored on the server side.

  • 1

    I fully agree. The punctuation logic should be processed on the server side and not on the client side. The server must receive the basic data to set the score, calculate and.

  • 1

    very good observation, but could you talk a little more about the use and operation of CSRF Tokens? (concept)

  • @marcusagm, this example of my punctuation was based on actual observations and believe me, there are many applications recording punctuation on the client side and sending everything "chewed" to the server.

  • Client-side encryption is useless when we want to preserve the data against the client himself, after all he will have access to everything that happens, before and after the data is encrypted. The use of a public/private key solves the problem only superficially.

  • 1

    @Danover Yeah, unfortunately there is, but that doesn’t make this practice right. I already got a lot of system to fix because of this, either because the client wanted to improve security or even because javascript miscalculated in some cases... Do what some people can’t learn and hammer into the same mistake.

  • I have an idea that consists of the following: Points are accumulated on the server, the application only passes the new increments. Increments are immediately encrypted, not stored locally in a raw form, and their encryption is preferably done with a public key issued by the server. The encryption is done by an obfuscated algorithm. One can use data from a clock to ensure that the client will not replicate a call to the server. Although theoretically still a vulnerable system, a huge barrier has been created.

  • 1

    @Danover edited the reply to reflect his suggestion.

Show 2 more comments

0

Here’s a tip that might be useful:

The data you send to your form, save them in a session

You will fill in the values below with the data that will come from the bank, which will look like this:

$_SESSION['esperado'] = ['preco' => '1000', 'quantidade' => '1', 'desconto' => '10'];

And then when you receive the submission, make sure nothing important has changed

$dadosRecebidos = [
    'preco'      => $_POST['preco'],
    'quantidade' => $_POST['quantidade'],
    'desconto'   => $_POST['desconto']
];

$diferenca = array_diff($_SESSION['esperado'], $dadosRecebidos);

 if ( $diferenca) {
    throw new Exception("Os dados foram alterados");
}

Depending on the case, instead of saving the data in a session, you can also save in the database, and do the same check when the form is submitted

Browser other questions tagged

You are not signed in. Login or sign up in order to post.