security - PHP prevent CSRF attack
I'm raising the security levels of a software I'm working on.
The goal, as stated in the title, is to prevent CSRF attacks.
In a scenario that involves the use of the backend by a user who has to manage a control panel, let's take the example that the user must initialize a command that deletes a data from the database, obviously if it were used:
<a href="delete_post.php?post=003">Delete Post</a>
it would be an announced suicide.
By reading the PHP documentation (https://www.php.net/manual/en/function.random-bytes.php)
I found this that interested me a lot but it also made me ask questions.
If you implement the code in it:
function RandomToken($length = 32){
if(!isset($length) || intval($length) <= 8 ){
$length = 32;
}
if (function_exists('random_bytes')) {
return bin2hex(random_bytes($length));
}
if (function_exists('mcrypt_create_iv')) {
return bin2hex(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM));
}
if (function_exists('openssl_random_pseudo_bytes')) {
return bin2hex(openssl_random_pseudo_bytes($length));
}
}
function Salt(){
return substr(strtr(base64_encode(hex2bin(RandomToken(32))), '+', '.'), 0, 44);
}
$token = (RandomToken())."\n".Salt()."\n";
we will get such a thing that every time the page is refreshed it will change:
13356ac7fc5e058b61bbad693d84ca2e1d9ae584db356dfa928098800d46ed6d F0ToG948CsaUF2wGDSdt.DuyUMKY1VC/liEAyjTB6ME=
Which is good ...
but:
If you choose the way of storing codes in the db and check that the generated code is new and never used then I validate the query statements for the elimination, who guarantees me that a user with bad intentions cannot generate the same 108-character code that maybe it has never been used?
So a solution of a unique time code would be better?
How to solve this?
Answer
Solution:
Regarding your questions:
If you choose the way of storing codes in the db (...)
Why store the codes in the DB? Store them in the users session. You can have one anti-CSRF token for the whole session and it makes handling of the token easier.
who guarantees me that a user with bad intentions cannot generate the same 108-character code that maybe it has never been used?
Math. 32 byte random variable has an entropy of 256 bits. 128 bits would be sufficient to prevent a successful brute force attack and this is way above this.
So a solution of a unique time code would be better?
No. You already have all you need. And you don't need salt for the purpose of token creation too.
Source