Enzyme Fiance is an on-chain asset management protocol. Users can create access rules, trading limits and other various rules. Within this, there are three main roles: asset manager, end users and the protocols being interacted with.
The manager handles the funds in order to create a secure yield generating platform, which the users will benefit from. However, who should have to pay for the gas on a rebalancing? To solve this problem, there is a gas station network relayer for handling exactly this case. This works by having the users pay the expected gas charges up front then executing the transaction via a network of relayers.
Within this architecture, there are a few different roles. First, the relay server is a web server that takes in a request for a transaction. The paymaster is the contract setup by the application using the GSN to pay for the gas prior to executing the call. The relayhub is the entrypoint for the relayer itself. Finally, the forwarder is the contract on the network for the GSN that is trusted to execute the call, where the application should implement a caller interface for this.
We have an anonymous user from the GSN network making calls to the contract on behalf of another user. So, access control is complicated to do with this setup. One job of the forwarder is to call the function preRelayedCall() to ensure that the recipient matches the forwarder in the relay request. When overriding the original implementation of this function from GSN, they removed this check.
For integration into the network, the relayer is trusted and must be allow listed by the network. Since the check was removed, an malicious forwarder can abuse this to profit from it. Remember, the forwarder is the entity actually performing the transaction and getting paid out in gas for their troubles. Since the forwarder isn't validated, an attacker can send a fake message then receive payment for it!
How much payment? According to the GSN docs, the gas information should be validated within the paymasters preRelayedCall() as well. But, there is no verification of the gas parameters for this. As a result, a malicious relayer can set very high gas values then get paid out a lot by the paymaster. To make matters worse, since the paymaster is replenished with 0.5ETH magically, this can be done on repeat to steal more and more ETH.
To fix this, there are two bugs that should be remediated. First, checking the forwarder address. Second, checking that the gas parameters are sane.
The author leaves us with a few takeaways. First, small features can still have big impacts. Second, more misconfigurations can lead to the amplification of impact, such as with the missing gas price check. Finally, design is key. GSN rewrote some of their code to do this verification themselves instead of putting the blame on the developers.
Overall, a very in depth read onto a GSN integration vulnerability. It's interesting how a small access control issue turned into the stealing of money from the protocol. Great find and write up!