Analysis of Replay Attack Prevention Scheme Based on timestamp and nonce Implementation of PHP

  • 2021-12-13 16:26:06
  • OfStack

In this paper, an example of PHP based on timestamp and nonce to prevent replay attacks. Share it for your reference, as follows:

Previously, timestamp was used to prevent replay attacks, but this does not guarantee that every request is once. Today, I saw an article introducing nonce (Number used once) to ensure one-time effectiveness. I feel that a very good effect can be achieved by combining the two.

Replay attack is one of the common attack methods in computer world. The so-called replay attack means that the attacker sends a packet received by the target host to deceive the system, which is mainly used in the identity authentication process.

First of all, we should make it clear that the replay attack is two requests. The hacker got the requested HTTP message by grabbing packets, and then the hacker wrote a similar HTTP request and sent it to the server. That is to say, the server handles two requests, first the normal HTTP request, and then the tampered HTTP request sent by the hacker.

Scheme based on timestamp

Every HTTP request, you need to add timestamp parameter, and then digitally sign timestamp and other parameters. Since a normal HTTP request will not exceed 60s from the time it is sent to the server 1, after receiving the HTTP request, the server first judges whether the timestamp parameter exceeds 60s compared with the current time, and if it exceeds, it is considered as an illegal request.

If hackers get our request by grabbing packets, url:
http://koastal.site/index/Info?uid=ZX07 & stime=1480862753 & sign=80b886d71449cb33355d017893720666

Among them


$sign=md5($uid.$token.$stime);
//  Server through uid Readable from the database token

1 Under normal circumstances, it takes a hacker much more than 60s to replay the request from the grab packet, so the stime parameter in the request has expired at this time.
If the hacker modifies the stime parameter to the current timestamp, the digital signature corresponding to the sign parameter will be invalid, because the hacker does not know the token value and has no way to generate a new digital signature.

However, the vulnerability of this method is also obvious. If the replay attack is carried out within 60s, there is no way, so this method cannot guarantee that the request is valid only once.

Scheme based on nonce

nonce means a valid random string only once. It is required that this parameter should be different every time it is requested. Therefore, this parameter 1 is generally related to time stamp. For convenience, we directly use the hexadecimal of time stamp. In actual use, we can add the information such as ip address and mac address of the client to make a hash and use it as nonce parameter.
We store the nonce parameters of each request in a "collection", which can be stored in the database or cache in json format.
Every time an HTTP request is processed, it is first judged whether the nonce parameter of the request is in the "set", and if it exists, it is considered as an illegal request.

If the hacker gets our request url by grabbing the packet:
http://koastal.site/index/Info?uid=ZX07 & nonce=58442c21 & sign=80b886d71449cb33355d017893720666

Among them


$sign=md5($uid.$token.$nonce);
//  Server through uid Readable from the database token

The nonce parameter is stored in a "collection" on the server when it is first requested, and a second request is recognized and rejected.
nonce parameter as a part of the digital signature, is not tampered with, because the hacker is not aware of token, so can not generate a new sign.

There is also a big problem with this approach, that is, the "set" for storing nonce parameters will become larger and larger, and it will take longer to verify whether nonce exists in the "set". We can't make the nonce "set" infinitely large, so we need to clean the "set" regularly, but once the "set" is cleaned, we can't verify the cleaned nonce parameters. That is to say, assuming that the "collection" is cleaned once a day on average, although the url we captured could not be replayed at that time, we could still replay every other day. Moreover, it is not a small overhead to store the "nonce" parameters of all requests within 24 hours.

Scheme based on timestamp and nonce

What if we use both timestamp and nonce parameters?
The first degree of nonce can solve the problem of timestamp parameter 60s, and timestamp can solve the problem that nonce parameter "set" is getting bigger and bigger.

We add nonce parameters to the timestamp scheme. Because timstamp parameters are considered illegal requests for requests exceeding 60s, we only need to store the "set" of nonce parameters of 60s.

If the hacker gets our request url by grabbing the packet:
http://koastal.site/index/Info?uid=ZX07 & stime=1480862753 & nonce=58442c21 & sign=80b886d71449cb33355d017893720666

Among them


$sign=md5($uid.$token.$stime.$nonce);
//  Server through uid Readable from the database token

If the HTTP request is replayed within 60s, it will be judged as an illegal request because the nonce parameter has been recorded in the server's nonce parameter "set" at the time of the first request. After 60s is exceeded, the stime parameter is invalidated, and the signature cannot be regenerated because the hacker does not know the value of token.

To sum up, we think that a normal HTTP request will not exceed 60s, and the replay attack within 60s can be guaranteed by nonce parameter, and the replay attack exceeding 60s can be guaranteed by stime parameter.

Because the nonce parameter will only work within 60s, you only need to save the nonce parameter within 60s.

We don't have to clean up the set of nonce parameters every 60s. We only need to judge the last modification time of nonce set when the new nonce arrives. If it exceeds 60s, we will empty the set and store the new nonce parameter set. In fact, the nonce parameter set can last a little longer, but at least 60s.
The random number set can be cleaned regularly or automatically according to the size according to the business scenario. For example, the maximum number of requests per second of this interface is 1000, and the maximum number of requests within 60s is 1500*60=9000. Then we check whether the set size exceeds 90,000 after each request, and empty it if it is too high.

Verification process


// Judge stime Is the parameter valid 
if( $now - $stime > 60){
  die(" Request timeout ");
}
// Judge nonce Parameter already exists in the Collection 
if( in_array($nonce,$nonceArray) ){
  die(" Request only 1 Sub-efficient ");
}
// Verify digital signature 
if ( $sign != md5($uid.$token.$stime.$nonce) ){
  die(" Digital signature verification failed ");
}
/*
if( $now - $nonceArray->lastModifyTime > 60 ){
  $nonceArray = null;
}
$nonceArray.push($nonce);
*/
// Handling random numbers 
$key = 'nonce'+$uid;
if($redis->sismember($key,$nonce) === true){
  die(' Reject replay attack request ');
}
if($redis->scard($key) > 90000){
  $redis->del($key);
}
$redis->sadd($key,$nonce);
// Replay attack check completed 

Reference article:

http://www.360doc.com/content/14/0116/16/834950_345740386.shtml

For more readers interested in PHP related content, please check the topics on this site: "php Programming Security Tutorial", "php Security Filtering Skills Summary", "PHP Operation and Operator Usage Summary", "PHP Basic Grammar Introduction Tutorial", "php Object-Oriented Programming Introduction Tutorial", "php String (string) Usage Summary", "php+mysql Database Operation Introduction Tutorial" and "php Common Database Operation Skills Summary"

I hope this article is helpful to everyone's PHP programming.


Related articles: