How IC prevents replay attacks during query requests?

Imagine I have a token canister, where each account is certified via the subnet signature and a Merkle-tree (the same scheme that asset canister uses to certify frontend chunks).

Imagine a user who queries for their balance and receives back the balance alongside with the Merkle proof and the whole delegation chain of keys up to the Chain Key.

When such a query request happens, from my understanding, the request first goes to some boundary node and then to some individual subnet node and then the response comes back the same way. Both of these intermediate parties could be malicious.

The attack is as follows:

  • when a user queries their balance for the first time, one of the intermediate parties remembers the valid response (balance + Merkle-proof + subnet signature + delegation chain);
  • the user validates the response and is now sure that everything is good;
  • then the user updates their balance via, for example, depositing more funds - so the real balance is now increased;
  • when the user queries for their balance again, a malicious intermediate party replays previously recorded response, instead of giving the actual one;
  • the user validates the response (since all the signatures are still valid), sees that their balance didn’t change despite the deposit they made and get very upset.

I know that this is a very synthetic example. But I thought it would be simpler to explain the idea that way. You can imagine another example, when I found a bug in my frontend, that, for example, leaks private user information, so I fixed it, but intermediate parties continue to serve the leaky version of it to users, because they somehow make money with this information.

Anyway. What measures does IC perform in order to prevent this kind of situation?

Your observation is correct.

One thing that helps is that the certificate contains a timestamp. Currently the service worker only checks if the timestamp is between ± 5min of the system time. See here and here, but I guess you could make that stricter for high value applications.

Maybe @frederikrothenberger has some more thoughts on this.


So, that means, that the certificate actually gets updated more frequently than set_certified_data() method is called?

This means, that these certificates are not well suited for any kind of non-interactive certification protocol, am I right? Since it is incorrect to issue a certificate to someone, sign it with a subnet signature and then expect this certificate to be valid after a couple of days.

UPD: thanks!

Have a look at the System State Tree and the Certification section of the Interface Specification.

set_certified_data() means that you set a value in the system state tree, and the (root of the) system state tree is signed every round.

I’m not sure if I understand. The certificate stays valid, but it certifies the state at a given point in time. If you have an old certificate you can verify it, but you obviously have not guarantee that the state hasn’t changed since then.


Thanks a lot, Dominic!

I understand now.

1 Like