transferProxy() a.k.a Proxy Transfer is a newly proposed EIP where the users can pay transaction fees in tokens, as opposed to paying only in ether in tradition ERC20 contracts. Proxy Transfer aims to solve the problem where the users can’t freely transfer their tokens unless they hold enough ether to pay for the transaction fees. While the EIP is still being reviewed, many projects have jumped on the gun and incorporated Proxy Transfer into their own smart contracts. Not long after Proxy Transfer was implemented in actual DApps projects, an overflow bug in transferProxy() was exploited on SmartMesh (SMT) where an equivalent of over $5 octodecillion worth of SMT counterfeit tokens were generated. A technical breakdown of this incident can be found down below:

In this article, we will be focusing on a replay attack exploit recently discovered by the researchers at 360 Security Research Innovation Alliance. Before diving into the code, we need to first understand how such replay attacks work at a high level. For demonstration purposes, we will use the classic placeholder names, Alice and Bob for representing the sender and the recipient respectively.

Attack Workflow

① Alice (sender) initiates a transaction in which 100 Token 1s will be sent to Bob (recipient) and 3 Token 1s will be paid to Proxy as service fee. Alice then signs the transaction with her signature → sig(A,B,100,3).

② Transaction gets carried out by Proxy. Bob gets 100 Token 1s from Alice.

③ Bob replays Alice’s signature in a new transaction → transferProxy(A,B,100,3,sig) → sig(A,B,100,3).

④ New transaction gets carried out by Proxy. Bob gets 100 Token 2s from Alice without her authorization.

Note 1: many smart contracts on Ethereum share the same way of verifying signatures. Some even share the exact same signature contents.

Note 2: here we assume the starting nonce is 1.

Proxy Transfer Contract

Two functions worth noting here:

keccak256(): KECCAK-256 is a cryptographic hash function used in Ethereum. Being an alias to SHA-3, KECCAK-256 is often wrongly referred to as SHA-3. In reality, KECCAK-256 does not follow the SHA-3 Standard and was already used in the Ethereum project before the SHA-3 Standard was finalized in August 2015.

KECCAK-256 is a cryptographic hash function used in Ethereum. Being an alias to SHA-3, KECCAK-256 is often wrongly referred to as SHA-3. In reality, KECCAK-256 does not follow the SHA-3 Standard and was already used in the Ethereum project before the SHA-3 Standard was finalized in August 2015. ecrecover(): “a function to recover the address associated with the public key from elliptic curve signature or return zero on error” (Ethereum, 2018).

Signing and Signature Verification

Note that the sender and the recipient need to agree on nonce and _fee before transacting.

Attack in Action

Here we will demonstrate an attack verification experiment performed by the 360 Security Research Innovation Alliance.

Alice sends Bob 3 MTC tokens

Transaction input data

Function: transferProxy(address _from, address _to, uint256 _value, uint256 _fee, uint8 _v, bytes32 _r, bytes32 _s) MethodID: 0xeb502d45

[0]: 0000000000000000000000008e65d5349ab0833cd76d336d380144294417249e

[1]: 000000000000000000000000185ca9b6da95beba43f3763b8e4cf3a0252cc241

[2]: 00000000000000000000000000000000000000000000000029a2241af62c0000

[3]: 0000000000000000000000000000000000000000000000000000000000000000

[4]: 000000000000000000000000000000000000000000000000000000000000001c

[5]: c6074323c4606c141739966b594d451add5411400b936d2ab8fd2338fc1a6263

[6]: 0b139672753d1ce31ed68bf3d49b9502aab5b919fa6cba34f3c4ff37edaa63ff

2. Bob extracts data [0] — [6] from the input data shown above, and uses it to make another transaction in the MTC smart contracts.

3. Along with the 3 MCT tokens Alice sent, Bob also received 3 UGT tokens from Alice without her permission. In other words, Bob “stole” 3 UGT tokens from Alice.

How to Prevent Such Attacks

There certainly are many possible ways to prevent such replay attacks, here are some of my ideas: