Potential Hive API Client Chain ID Vulnerability

in HiveDevslast year

First of all, I am not aware of an active attack using this vulnerability. Second, even if there were, it'd be pretty easy to spot, once it happens.

The potential vulnerability has to do with any API client that may programmatically request the chain_id from an untrusted endpoint, followed by blindly signing with such an injected chain_id.

We may have clients that programmatically requested the chain_id due to the transition from HF23 to HF24. There was a situation where we went from the previous chain_id to the new one. But that is no longer the case. We should remove client code that may still check for the old chain_id.

Old chain_id:

0000000000000000000000000000000000000000000000000000000000000000

New chain_id:

beeab0de00000000000000000000000000000000000000000000000000000000

Scenario

Alice intends to sign a transaction containing a transfer of 100 HIVE to Bob. Alice uses an API client library that requests the chain_id from an untrusted endpoint being operated by Eve.

Normally Eve reports the expected chain_id.

But under a certain condition, Eve suddenly injects a chain_id for another chain and gets Alice to sign the transaction with this alternate chain_id, where the Bob account is under the control of Eve. The original 100 HIVE transfer is not broadcasted on the Hive blockchain, but instead, broadcasted on the alternate chain.

Testnet Senario

For the purpose of testing, the chain_id can be anything. In fact, the original design called for the chain_id to match the github commit SHA, which wasn't a bad idea, but a little bit overkill.

It would be tempting for an API client library to dynamically request the chain_id and use this reported value so that the person testing doesn't have to worry about it. But this is the main vulnerability.

I want to stress that perhaps the biggest vulnerability in having a programmatic chain_id is when working with a testnet. If Eve ran a testnet, she could momentarily report the mainnet chain_id and trick a tester into signing a mainnet transaction that was intended for the testnet.

This is actually the most worrisome scenario: Heavy testing on an untrusted testnet node. I guess it's lucky we don't do heavy testnet testing (/s).

Again, this assumes that the API client library will refresh the chain_id right before signing, which it should not do.

Mitigations

In order for all this to work, Eve must operate some kind of public node that Alice must trust. Therefore, Eve's node must work as expected until the attack. It must basically "lie in wait" until it sees a transaction Eve wants to redirect.

Even then, the API client library must cooperate with Eve and request the chain_id right before signing.

Transfers are likely protected because they still must use legacy serializations (i.e.: to this day, even amounts expressed as nai still need to use legacy strings in serializations). The upshot is that whatever alternative chain that intends to steal funds would have to have the same symbol on that alternative chain.

Therefore the only asset symbol that is likely vulnerable to this scenario would be VESTS on a testnet, where for example Alice intends to power up Bob on a testnet, but is tricked into powering up Bob on the mainnet instead. This would be more of an act of vandalism by Eve, because Bob would still likely have control of the funds unless Bob's mainnet account was compromised.

All these mitigations result in an unlikely scenario. Don't trust a random node. More importantly, don't constantly refresh the chain_id.

Better Mitigations

An even better way to avoid this entire problem is for clients to never request the chain_id for the purpose of signing. Requesting it to see if the node is up to something is fine. Requesting it for debugging is fine. But whatever chain_id comes over the wire should never be trusted or used for signing in any situation. And if it changes to something unexpected, the client should raise an exception.

Since we're done with the HF23-HF24 transition, there should be no need to dynamically apply the chain_id anymore.






CVE-2018-?????: It turns out Bruce Schneier is just two mischevious kids in a trenchcoat.

Sort:  

TaPoS will stop that.

True, now that certain chain head blocks are 142,698 apart. But the testnet scenario could skip blocks.

Excellent information, this is a contribution very significant and strengthens the power of open source over proprietary, since collaboration among many can generate more growth than the power of the few.

That's why I keep telling people that open source projects are the best. great observation. Thanks a lot

Weird, after last night's steemit post, my downvoting power went to zero over there! (I think I got blocked from curation) I guess was posting sort of fud posts, now it does not work at all! Sad day!!

This is why open source trumps closed source. Thanks for keeping an eye on this stuff for us!