To correct marked response has some errors, in my opinion, that I decided to give another answer.
The mt_rand()
(and the str_shuffle()
) is predictable, a person with access to some answers may be able to get the used Seed, for example using the Untwister or the PHP_MT_SEED Cracker, out other several ways.
Your code is public, so something like (date('s') + date('i') * 10000)
is useless, after all the chances of our watches being different is despicable.
The strrev()
will not add any security, this is worse than the Cesar Cipher, because she at least had "some key".
When you run the SELECT
, as SELECT * FROM tabela WHERE token = $token
, you will be clearly vulnerable to timing-Attack, a user will be able to obtain information through the time consumed to run queries.
A solution would be to create two identifiers and search for them, one of them being compared securely with the hash_equals.
Create two identifiers:
$pesquisar = random_bytes(8);
$confirmar = random_bytes(24);
$confirmar_hashed = hash("sha256", $confirmar, true);
Then insert it into the database, like:
INSERT tabela (`pesquisar`, `confirmar`) VALUES ($pesquisar, $confirmar_hashed)
The user must receive the values of $pesquisar
and $confirmar
, whereas this is passed in URL, it would be like:
seusite.com/?pesquisar=$pesquisar&confirmar=$confirmar
Remembering that both should be unique, the $pesquisar
has the same capacity as an int64, or BIGINT in the case of Mysql.
Search for value:
To search, use the pesquisar
as the main parameter, such as:
SELECT * FROM tabela WHERE pesquisar = $pesquisar
Then compare the confirmar
using the hash_equals
, as:
$stmt = $mysqli->prepare('SELECT confirmar FROM tabela WHERE pesquisar = ?')
$stmt->bind_param("s", $_GET['pesquisar']);
$stmt->execute();
$stmt->bind_result($confirmar_hashed);
$stmt->fetch();
if(hash_equals($confirmar_hashed, hash("sha256", $_GET['confirmar'], true)) === false){
echo 'Valor de "confirmar" é incorreto';
}
For me this would be minimally safe. Of course, assuming you are using a secure operating system, the random_bytes
props on the /dev/urandom
.
EDIT (2020-08-22): After reviewing, I noticed that it was not assumed that there could be a "read-only" attack. I modified the answer to assume this possibility. Added use of the hash("sha256", ...)
to prevent a read-only attack, such as a "Read-Only SQL Injection". This assumes that the attacker has some read access to the databases, but not editing. In this scenario and with the use of hash
, the attacker will only have access to data that is the result of a hash (the $confirmar_hashed
), therefore it will not have the original value (the $confirmar
). In the previous version, and under these conditions, the attacker would have access to the codes, normally.
There are many ways, but probably all wrong. In a normal application no one should need this, Probably if someone can use the ID to do something wrong, it is lack of checking the user permissions . Maybe it would help to edit the question and explain the real problem you’re trying to solve, instead of the way you thought it would.
– Bacco
If there’s anything I can do to help with the question, thank you. As I said, I need some way to encrypt the ID displayed in the HTML and decrypt the ID in the back-end.
– ElvisP
The best help I think is to discourage wasting time with an outline that is probably not a real solution to the problem, for the reasons already mentioned. If the ID cannot be seen, it should not even be in HTML (either obfuscated or not). And probably not the case to hide, any basic application shows the Ids for deletion, editing, etc without any problem. But if it is, I’m really curious to know the application scenario, because the last questions that asked the same started from the wrong premise. If yours is different, it really must be an atypical scenario.
– Bacco
If you are using a secure connection (SSL) you are already encrypting. If it is something that no one can know should not be sent to a customer.
– Maniero
I improved the question, explained the scenario. Thank you!
– ElvisP
It really is what I had thought, there is no need to hide anything in this scenario. Basically what you need is to check the permissions of who is doing the deletion and change operation on that record.
– Bacco
I will continue to use Cipher, I had no pretension to make use of more classes in the code, because I am paranoid with security, if something goes wrong, other than through my code, which is for server failures or other levels, rs.
– ElvisP
I believe what you’re looking for is actually to use what they call UUID (Universal Unique Identifier), something similar to this token you decided to use. Take a look at the function UUID() in Mysql, you may find it more interesting to use it.
– Dudaskank
@Eliseub., what you want is to obfuscate the ID so as not to allow the user, for example, to derive information from your system, such as number of requests, etc. If that is so then, depending on the context, it is recommended: https://philsturgeon.uk/http/2015/09/03/auto-incrementing-to-destruction/
– cantoni
Gives a look here, can help you.
– Ivan Ferrer
Ivan Ferrer, I know the majority, but I believe that everything was misinterpreted in the way I explained my question, but it was already, security in several layers implemented and working. Thanks for everything. Namaste.
– ElvisP