How to encrypt GET and copy the parameter

2

I have a feedback email that is sent to a user after the service is completed. This email has 5 links, where each one is the respective service grade (from 1 to 5).

I want to direct to the page to update the database, the evaluation of the service, using the id of the client, the provider, the request and the note.

For this I used link as .. /avaliacao.php?prestador=1&cliente=2&pedido=3&avaliacao=4

In PHP, I'm using $_GET['prestador'] to get the parameters and set the variable that will be inserted into a MySQL database, but I do not want the client to see this url so that it does not change the way it wants .

How can I do it? Encrypt? Is there another way?

    
asked by anonymous 03.10.2017 / 20:50

2 answers

1

You can use a simple HMAC to check that id remains unchanged, this will be safe until no one knows the key you use, of course it must be strong and securely generated, I will explain this as well.

In addition you should make sure that you can not get HMACs from other accounts, otherwise it would be the same as having the key.

  

/! \ Do not use the keys mentioned in the examples.

In general, something like:

$id = '1234'; 
// Este é o id do usuário, que deve estar associado de alguma forma segura.

$chave = pack('H*', '07e8796b87caa27d793dbe2ecfa7c85f753a9c920cb5d1394fbc36c20f1755b818c9afe37fb453ebf42724c8670d365ca9f0d12d49e31ea843023126f3174df9');
// Esta sua chave secreta e segura que foi gerada por você.

$hmac = hash_hmac('sha512', $id, $chave);
// Este é o resultado do HMAC de SHA-512.


<form action="avaliacao.php" method="post">

<input name="id" type="hidden" value="<?= $id ?>" />
<input name="hmac" type="hidden" value="<?= $hmac ?>" />


<input type="submit" name="avaliacao" value="1" />
<!-- ... Resto das outras opções  -->
</form>

Then check to see if there has been a change:

$chave = pack('H*', '07e8796b87caa27d793dbe2ecfa7c85f753a9c920cb5d1394fbc36c20f1755b818c9afe37fb453ebf42724c8670d365ca9f0d12d49e31ea843023126f3174df9');

if(!isset($_POST['hmac'], $_POST['id'])) {
    echo 'Erro: faltam dados';
    exit;
}

$isHMACValido = hash_equals(
    hash_hmac('sha512', $_POST['id'], $chave),
    $_POST['hmac']
);
// Comparamos de maneira segura e em tempo contante o HMAC enviado pelo usuário e o computado agora.

if(!$isHMACValido){
    echo 'Erro: Dados foram manipulados';
    exit;
}

// Chegou até aqui está tudo certo!
// ...

What protection does this bring?

  • Changing id by a user who does not know the key.

How is this protection achieved?

  • HMAC is an option of type H(K⊕opad||H((K⊕ipad)||m) , so two different messages ( m , in this case id ) different result in a different HMAC. A malicious user will be able to modify both (eg send: id=99&hmac=aaaa ), but this will be compared to the new HMAC (we will do the hmac, id, key), obviously it will be different from the hash sent by the user.

Is there no risk?

From the HMAC ...

    CPA attacks do not work, even if the attacker creates thousands of accounts (thus having several valid HMACs for each account) he will have no clue what the key is used for.

  • Exhaustive search attacks will always work, however they are 512 bits, this results in more than 2 ^ 512 possibilities, which makes the attack unfeasible, at least until this moment.

  • Exhaustive search attacks against the key also work. For this the key must be secure and generated from a secure CSPRNG and strong enough, otherwise brute force attacks will be fast, also use 512 key bits.

  • MiTM attacks are valid. If you do not use HTTPS one person monitoring the network can get the other user's HMAC, this would not only affect the HMAC, but the whole system.

From the application ...

  • It should not be possible for the user to have access to other HMACs. The id must be unique to it. Your application should not say what the HMAC of an X, being X sent by the user, allow this to override any security.

  • The key must be kept secret and should not be known by the client, if the key is exposed it will be possible to compute valid HMACs.

To generate a secure key use:

echo unpack('H*', random_bytes(32))[1];
    
04.10.2017 / 03:20
0

As Rafael Augusto spoke, I changed using the POST, it looked like this:

email:

<form action="avaliacao.php" method="post">
<input name="id" type="hidden" value="1" />
<input type="submit" name="avaliacao" value="1" />
<input type="submit" name="avaliacao" value="2" />
<input type="submit" name="avaliacao" value="3" />
<input type="submit" name="avaliacao" value="4" />
<input type="submit" name="avaliacao" value="5" />
</form>

evaluation.php

<?php

$id = $_POST['id'];
$avaliacao = $_POST['avaliacao'];
echo 'id: '.$id.' - Avaliação: '.$avaliacao.'<br/>';

$conn = new mysqli('localhost', 'user', 'password', 'db');
$sqlverifica = '
SELECT avaliacao
FROM prestadores_avaliacao
WHERE id = '.$id;
$result = $conn->query($sqlverifica);
while($row = $result->fetch_assoc()) {
    $avaliacaoatual = $row["avaliacao"];
    echo "Avaliação Original: ".$avaliacaoatual;
}

if($avaliacaoatual==''){
$sql = '
UPDATE prestadores_avaliacao
SET avaliacao = '.$avaliacao.'
WHERE id = '.$id;
$conn->query($sql);
}

?>
    
03.10.2017 / 21:38