SECURE YOUR WEB DEVELOPMENT AGAINST REPLAY ATTACKS

SECURE YOUR WEB DEVELOPMENT AGAINST REPLAY ATTACKS

Replay attacks are popular among cyber threats and Rank #8 according to A8:2017-Insecure Deserialization hence let us deep dive on risk mitigations in this week's article

What is Replay Attack?

A replay attack at the TLS level (and thus HTTPS) as you imagine would mean that some attacker could simply replay a captured TLS session or inject a previously captured packet into an existing TLS session.

Sniffing attempt resending traffic to server

Replay attacks are a form of network attack where an attacker intercepts and retransmits data that was previously exchanged between two parties. Fundamentally, a replay attack occurs when an attacker is able to capture data-in-transit in cleartext form. Replay attacks may capture various forms of authentication data, such as passwords, session tokens, or cryptographic authentication hashes.

The problem lies in technologies that lack signature based authentication.? To understand this problem, it's important to understand the difference between using secrets vs. signatures for authentication. Essentially, secrets rely on transmitting predictable information such as a password or authentication token which, if stolen, can be used again since they don't change.? However, signature based authentication always transmits different data to authenticate because it relies on public key cryptography.


How is a Replay Attack carried-out?

  1. User Alice wants to buy something from www.iBuy.com, but www.iBuy.com wants Alice to prove her identity.
  2. In order to prove her identity, Alice sends her Hashed [Credentials] to www.iBuy.com, it validates and accepts Alice to their website.
  3. Alice orders her required item and requests to ship to her residential address.
  4. Meanwhile, communication session between Alice and www.iBuy.com has been eavesdropped by malicious user Bob and he retrieved Alice's Hashed [Credentials] from the communication channel session.
  5. After Alice and www.iBuy.com communication session ended, Bob connects to www.iBuy.com and sends Alice's Hashed [Credentials] (which is retrieved from step 4) to prove Alice's identity and not Bob's identity to www.iBuy.com, which www.iBuy.com accepts and thus it allows Bob to enter www.iBuy.com as Alice.
  6. Then, Bob changes Alice's ordered item's shipping address to his address. Now item is going to ship to Bob's residential address, and not to Alice's address.

So,

  • Bob possessed Alice's Hashed [Credentials] (from step 4), REPLAYED the action and submits Alice's Hashed [Credentials] to www.iBuy.com, which it thinks Alice is the one who submits the Hashed [Credentials], but really Bob replayed Alice's Hashed [Credentials].

How to prevent the Replay Attack using nonce?

If www.iBuy.com requires Alice to send Hashed [Credentials + non-repetitive Nonce sent by www.iBuy.com to Alice], then even though Bob eavesdropped, retrieved and REPLAYED the hashed value, www.iBuy.com denies the request, because the nonce sent by www.iBuy.com to Alice is now different, subsequently the hashed value is also different now and certainly the hashed value is not the one expected by www.iBuy.com.

Risk Mitigation through Nonce

Nonce as a timestamp provides a reliable way to prevent replay attacks. Using a nonce as a timestamp ensures that a message is used only once, and if an attacker tries to replay the same message, it will be detected as invalid.

Nonces must be stored securely to prevent attackers from accessing or modifying them. Ideally, nonces should be stored in a tamper-evident way, such as in a secure hardware module.

Let us see how to implement it:

The Web Fundamentals Content Security Policy article’s If you absolutely must use it section has a good example of how to use the nonce attribute, which amounts to the following steps:

  1. For each request your web server gets for a particular document, have your backend make a random base64-encoded string of at least 128 bits from a cryptographically secure random number generator; e.g., EDNnf03nceIOfn39fn3e9h3sdfa. That’s your nonce.
  2. Take the nonce generated in step 1, and for any inline script/style you want to “whitelist”, make your backend code insert a nonce attribute into the document before it’s sent over the wire, with that nonce as the value:
  3. Take the nonce generated in step 1, prepend nonce-, and make your backend generate a CSP header with that among the values of the source list for script-src or style-src:

So the mechanism of using a nonce is an alternative to instead of having your backend generate a hash of the contents of the inline script or style you want to allow, and then specifying that hash in the appropriate source list in your CSP header.

Use of Rebouncing in Typescript

Let's understand this with an example. Suppose we have an input element that gets some data when we type something. For example, let's say we type any pin-code, and it returns some data.

But there is a catch here. Let's say our pin-code is 800001. If we type the first character, that is 8, we will send request to the backend server. Then we type 0, and we will send another request to the server, and so on. ?

This calls the API so many times, and in turn overuses the requests. So, to prevent this, we use something called a debounce function.

So to achieve this, we have a feature in JavaScript called Debouncing.

Debouncing in JavaScript – a Practical Example

In the below example, we are simply calling an API using the axios.get method when we type any numeric character in the input box.

The input character is getting passed to the function as an argument and we are passing the value as path parameters. We are also logging the response in the console.

import axios from "axios";
import React from "react";
import "./styles.css";

export default function App() {
  const setInput = (value) => {
    axios
      .get(`https://api.postalpincode.in/pincode/${value}`)
      .then((response) => {
        console.log(response.data[0]?.PostOffice[0]);
      });
  };
  return (
    <div className="app">
      <input
        placeholder="Search Input.."
        onChange={(e) => setInput(e.target.value)}
      />
    </div>
  );
}
        

But the catch here is, every time we write a character, our API will get triggered. So going back to our example above, let's say we want to type 800001. Again, as soon as we type 8, the API will be triggered and it will search the character 8. Then we will type 0 (zero), and the API will search for 80, and so on.

Now, let's change the whole flow in order to add debouncing. In the case of Debouncing, the API will trigger only once after 2 seconds, after we type our whole pin-code.

First of all, create a state using the useState hook in React.

const [pinCode, setPinCode] = React.useState("");        

Now, we need to set the data in the pinCode state when we type something, using the onChange event handler.

<input
      placeholder="Search Input.."
      onChange={(event) => setPinCode(event.target.value)}
 />        

Now, let's have a useEffect Hook that will run every time our pin-code changes, or when we type something in the search input.

React.useEffect(() => {

}, [pinCode])        

In this useEffect Hook, we will have a function called getData. This function getData will have a callback function called setTimeOut. And we will set the timer for 2 seconds.

React.useEffect(() => {
    const getData = setTimeout(() => {
      
    }, 2000)
}, [pinCode])        

And now in this getData function, let's call our API.

React.useEffect(() => {
    const getData = setTimeout(() => {
      axios
      .get(`https://api.postalpincode.in/pincode/${pinCode}`)
      .then((response) => {
        console.log(response.data[0]);
      });
    }, 2000)
}, [pinCode])        

We will also need to destroy the instance of the useEffect hook using return, followed by clearTimeout, every time it finishes.

React.useEffect(() => {
    const getData = setTimeout(() => {
      axios
      .get(`https://api.postalpincode.in/pincode/${pinCode}`)
      .then((response) => {
        console.log(response.data[0]);
      });
    }, 2000)

    return () => clearTimeout(getData)
  }, [pinCode])        

And we are done. Let's type something in the input, and after 2 seconds we will get our results.

On a summary, if we type any search query in the input, it will display after 2 seconds just when we stop changing the input. And we used debouncing to do this.

There are multiple applications of debouncing. We can use it to keep from hitting our API over and over. And we can use it to make sure the the form data gets submitted only once, even if we click the submit button multiple times.

Stopping a Replay Attack

Preventing such replay attack is all about having the right method of encryption. Encrypted messages carry "keys" within them, and when they're decoded at the end of the transmission, they open the message. In a replay attack, it doesn't matter if the attacker who intercepted the original message can read or decipher the key. All he or she has to do is capture and resend the entire thing — message and key — together.

To counter this possibility, both sender and receiver should establish a completely random session key, which is a type of code that is only valid for one transaction and can't be used again.

Summary

Signature-based authentication, data encryption, employing unique token identifiers and nonce values within the applications will control replay attacks of some types but not all the different (newly emerging) types hence having sold security detection mechanism such as CheckMarx Scans, BurpSuite Scans to the application interfaces are essential to bring additional measures to reduce the overall impact of different Replay Attack methods.



References:

https://security.stackexchange.com/questions/233603/preventing-https-replay-attacks

https://fastercapital.com/keyword/replay-attacks.html

https://networksimulationtools.com/replay-attack-network-projects/

https://www.freecodecamp.org/news/debouncing-explained/

https://www.kaspersky.com/resource-center/definitions/replay-attack

https://stackoverflow.com/questions/38257221/exactly-how-does-a-nonce-and-client-nonce-prevent-a-replay

https://stackoverflow.com/questions/42922784/what-s-the-purpose-of-the-html-nonce-attribute-for-script-and-style-elements

https://www.packetlabs.net/posts/a-guide-to-replay-attacks-and-how-to-defend-against-them/


Like this article? Subscribe to Engineering Leadership and Digital Payments Hub to enjoy reading useful articles.


Disclaimer: Contents, posts and media used in this account of the author do not represent any organisation of any sort. Under no circumstances will the author be held responsible or liable in any way for any claims, loss, expenses or liabilities whatsoever.


要查看或添加评论,请登录

社区洞察

其他会员也浏览了