The Antidote To On-Chain Poisoning
Things to know: |
– The growth of the EVM ecosystem makes it a prime target for crypto attacks. – There are many variations and techniques used by scammers under the Address Poisoning umbrella. – Ledger is always exploring innovative protective measures for EVM chain users. |
We have seen lately an increase in the number of attacks labeled as “Address Poisoning”, targeting EVM chains. This impacts our clients who may be losing funds as they end up trusting and copy/pasting bad addresses. This has been discussed quite a lot by the main actors, but the content online is both repetitive and yet technically incomplete, missing clear examples.
So let’s dig into the different types of Address Poisoning! Because yes, it’s actually a family of attacks, with variations in their implementation.
Vanity Poisoning: Brute-forcing your addresses
This first type of Address Poisoning is the simplest one, and it is covered by most articles online. To understand it, we first need to talk about Vanity addresses, and our own human limitations.
Vanity Addresses
On EVM chains, Addresses are obtained by hashing the public key of the Account, and only keeping the last (right-most) 20 bytes. These 20 bytes are then formatted as a 40-character hexadecimal string, and that’s what we all manipulate when sending/receiving ETH or tokens.
Now, people being people, they started looking for addresses following a certain hexadecimal pattern, because it had a slicker look. A well-known example is 1INCH’s token contract which has the address 0x111111111117dc0aa78b770fa6a738034120c302
, starting with many 1s 😍. That’s what we call a Vanity Address.
The 1inch team generated it by deriving and hashing lots of public keys, until they got one looking the way they wanted. They probably used a tool like Vanity ETH to do so, which is not difficult but rather time-consuming.
“But wait, does that mean that I can find the private key to any Ethereum address??” you might ask. To which I’d answer: Hopefully not, or I’ll need to quickly find a new job to cover my mortgage.
In reality, the difficulty of generating a Vanity Address increases non-linearly with the number of characters you fix. Using Vanity ETH, it will take you several months to get an address with 10 fixed characters. For 12 fixed characters, it bubbles up to several hundred years. I’ll let you extrapolate how long it would take for a complete address of 40 characters.
How cool my descendants will look with this address!
The key takeaway is that, with sufficient effort, it is possible to generate an address that follows a certain pattern on a few of its characters.
Humans Reviewing Bytes
As humans, we tend to only partially review addresses when reading them. The most common pattern is to only review a few of the first and last characters of addresses. While this is less secure than exactly comparing them, character by character, it is much easier on the eyes and is the path of least resistance.
It is also somewhat encouraged by the tools available to us since a lot of them hide most of the addresses away.
Metamask only shows the start and end of your address
The Attack
Given the above, some bad actors have realized that they could:
- Look for an active User Address that is flush with magic internet money.
- Generate a Vanity Address that matches the first and last few bytes of the User Address.
- Send a transaction with an amount of 0, or almost 0, from the Vanity Address to the User Address. That’s the actual poisoning: The user now sees the attacker’s Vanity Address in their own transaction history.
- The attacker now waits and hopes that the user will make a mistake and copy-paste their Vanity Address when trying to send funds to themselves.
Since handling random bytes is hard for humans, we have a tendency to copy any address that looks like ours when in a rush, which makes this attack pretty effective.
Generating Vanity Addresses is time-consuming, however, which makes this attack harder to scale. It is important to note though that the process can be reversed to make it cheaper:
- The attacker generates as many Vanity Addresses as possible, that they control.
- The attacker watches all the on-chain activity and all the active User Addresses.
- If any active User Address matches one of the Vanity Address, start the poisoning process.
In this way, the attacker gives up on targeting a specific account but widens the attack surface.
Zero-Value Token Transfer Attack: Tricking the chain
This second type of poisoning is even more insidious as it relies on creating ERC20s transactions on your behalf and without your consent!
To understand it, you need to be familiar with on-chain events, token allowance, and a little bit of Solidity.
On-chain events
On EVM chains, a transaction can affect the state of the chain in multiple ways. The most common one is by moving ETH between addresses, effectively changing the on-chain balance of the accounts involved.
Another change of state is the publication of Events. When looking at a transaction on Etherscan, you can see the events that is has generated. These events are how transfers of tokens (ERC20s, NFTs, …) are materialised on chain.
When looking at your ERC20 transaction history, you’re really looking at all the Transfer(address indexed _from, address indexed _to, uint256 _value) events that involve your address.
About token allowance
Many advanced uses of ERC20 tokens depend on third-party contracts being allowed to move funds on behalf of a user. This is handled through a map of allowances where the key is the allowed address, and the value is the max amount of funds that address can move.
In the standard ERC-20: Token Standard allowance can only be changed by the user, by calling the function approve(address _spender, uint256 _value).
Transfer in your name
The only way for an attacker to send X
amount of tokens on behalf of another user is to call the function transferFrom(address _from, address _to, uint256 _value). To be able to do that however, the target user must have already called approve({_spender: <attacker_address>, _value: X})
, giving them the required allowance.
At first sight, it seems like a hard limit to overcome.
However, given how mappings and default values work in Solidity, every address has an allowance of value 0
on every other address in the standard implementation of ERC20 contracts. So, in these implementations, anyone is allowed to execute the following transfer, regardless of whether the target user has actively given them allowance:
transferFrom({from: <user_address>, to: <attacker_address>, _value: 0})
Even better, the ERC20 standard states that:
Transfers of 0 values MUST be treated as normal transfers and fire the ‘Transfer’ event.
This guarantees that this empty transfer will always generate a valid Transfer
event that will end up being displayed in the user’s transaction history.
The Attack
Using the above newly found knowledge, we can perform the following attack:
- Call
transferFrom
with a value of0
on well-known ERC20 contracts like USDC, Matic, Uniswap… - Make it a transfer from the User Address to the Attacker Address.
- This will generate a legitimate Transfer event on chain from User Address to the Attacker Address.
- This event will then be synchronised by the user’s wallet, and displayed as a valid transfer.
The attacker has reached its goal: creating a legitimate ERC20 transaction from a target’s account to their own.
In any standard wallet, their address will now be displayed in the target’s transaction history as part of a valid trade. The user has been poisoned. With some luck (for the attacker) the target may mistakenly use the bad address in future trades.
Here are a few examples of such attacks on-chain:
- https://etherscan.io/tx/0xee4222942c77e530f7dedcebc999f7faa2c7c73106cc9876518d76b96f23f601
- https://etherscan.io/tx/0xd1905742a5e50d209619e44c94b7aa440cb4270bd3815c2426a87e2268452727
- https://etherscan.io/tx/0x7dab04354ad772e6852223c3c499c525862e43d514a36ddbf2dee280440ca485
Protecting Users
The attacks we have described have a real impact on crypto users out there. They are also only the tip of the iceberg. In their quest to get users to interact with malicious addresses, scammers will exploit any kind of technical or human flaw. They are also very quick to adapt their strategies to any countermeasures that wallet makers may deploy.
As maintainers of the Ledger Live, we have a responsibility to provide solutions that are secure and improve on the user experience. Given the nature of the attacks, it is very hard to prevent them from happening entirely. Instead, it is the role of wallets to handle the poisonous transactions differently to avoid any possible user mistake.
So what is the best way forward?
The easy answer for us is that you should never copy an address from your wallet, without first verifying it on the trusted screen of your hardware device. This countermeasure has been available since the first Nano S was commercialised and it has no known technical flaw.
But leaving it at that would be a mistake. People are not machines: we can be lazy, we can be in a rush, maybe we don’t have our Nano with us, and some people don’t even own a Ledger hardware wallet 😱. In everyday life, we always follow the path of least resistance. In this instance, that would be copying an address without thoroughly verifying it.
In this context, our teams on the Product, Developer, and Customer Support sides have been exploring multiple solutions. The simplest one, yet most efficient of them, was added to the latest Ledger Live release: Hiding transactions with absolute zero amounts.
Now, the most nefarious attack (Zero-Value Token Transfer Attack) is rendered toothless as the amount must be absolute zero to perform it. It is also a safe change as 99.9% of users never purposely use absolute zero transactions. For the remaining 0.1%, it is of course possible to keep showing the transactions by tweaking the advanced settings of Ledger Live.
Overall this change has a great impact, very few drawbacks, and a very short time to market. For other versions of the Address Poisoning attacks, we are exploring different solutions such as secure address books, detection of scam addresses, and many more!
Securing The Future
As the crypto world continues to evolve, bad actors relentlessly seek new ways to exploit vulnerabilities and target unsuspecting users. Address Poisoning is a prime example of such malicious attacks that prey on the limitations of both technology and human nature. By shining a light on the different types of Address Poisoning attacks and dissecting their underlying mechanisms, we aim to raise awareness and empower you to make informed decisions in your crypto journey.
To combat these ever-evolving threats, it is crucial for wallet providers, like Ledger Live, and the broader crypto community to stay vigilant, collaborate, and develop innovative solutions to protect users. As we continuously improve security measures and user experience, we encourage users to stay informed, practice caution, and adopt recommended best practices.
Just like attempts from scammers at defrauding you, the grouped effort of the Ledger teams to protect you is always ongoing. It will yield regular improvements to your day-to-day experience on Ledger Live, so look out for changes in future releases!