Author: Atiq Ahmed and Shafiul Nobe
In this article we describe how our team was able to retrieve some NFTs that were lost because of a compromised wallet.
In the blockchain, a wallet e.g., metamask is a digital tool or application that allows users to securely store, manage, and transact with their cryptocurrency assets. The wallet is usually secured with a private key or seed phrase, which is used to sign and validate transactions on the blockchain. If someone gets access to the private key, that person can essentially steal anything that is in that compromised wallet.
Our engineering team used a wallet for testing our web3 apps during development. That wallet we used for testing had a small amount of Ether and a few ERC-721 NFTs in the Etherium network. Somehow the private key of that testing wallet got stolen/hacked and the person who got access to that wallet was able to transfer all the Ether from our wallet to his wallet. But the attacker left the NFTs in our test wallet.
Only a small amount of Ether was lost from our test wallet. But, it was important for us to recover the NFTs from that wallet since our team used them for testing our Web3 apps. We attempted to use the ERC-721’s setApprovalForAll
method to allow a different (not compromised) wallet to recover those NFTs using a single batch transaction. However, our transfer attempts failed. To execute the batch transfer, we needed to have a small amount of Ether in the compromised wallet. But, whenever we transferred any Ether to the compromised wallet was immediately transferred to the attacker’s wallet before we could initiate and complete the batch transfer transaction.
We carefully inspected the transactions in the attacker’s wallet on Etherscan and found that it is transferring Ether from a number of compromised wallets in the same way. First, the attacker somehow gets hold of a wallet’s private or seed phrases. Then the attacker sets up some process or script that listens to the emitted Ether transfer event signal and transfers any Ether that is sent to the compromised wallets to another wallet. We noticed that the attacker’s process does not transfer the Ether from a compromised wallet if the balance is below the threshold value of $1
.
In blockchain technology, a nonce is a random number that is included in the input data of a cryptographic hashing function to produce a specific output, known as a hash. The nonce used in a blockchain wallet is a sequential number that starts at 0 and increments by 1 for each subsequent transaction. The nonce value is used in combination with the private key of the wallet to create a digital signature that is included in the transaction data. This signature is used to verify that the transaction was indeed initiated by the owner of the wallet, and not by a malicious actor attempting to gain unauthorized access to the wallet or its assets. The Nonce prevents the replay attack, i.e., when an attacker intercepts a transaction and re-broadcasts it for it to get executed again.
Notice that if there are multiple transactions pending in blockchain pool with the same nonce value for a wallet, then miners pick the transaction first which has the higher gas fee. And when that transaction gets completed, all other transactions with the same nonce get cancelled.
It is possible to replace a pending blockchain transaction with a new one with a higher gas fee or a higher nonce value using the following steps:
Caution: It is important to note that not all blockchain networks support transaction replacement, and some may have specific requirements or restrictions. Also, replacing a transaction with a higher gas fee can be costly, so it is important to carefully consider the gas price before initiating a replacement transaction.
Our goal was to somehow have enough Ether in our compromised wallet without the attacker stealing it and execute the setApprovalForAll
method to enable a secure wallet that could retrieve all NFTs out of the compromised wallet in a single transaction. We used the following steps:
$1
thresholdsetApprovalForAll
transaction with nonce 11
and lower gas fee 8
Gwei. And it was pending as the gas fee was too low$2.5
equivalent Ether to our compromised wallet$1
threshold), the attacker’s process initiated a transaction to steal the Ether and this transaction had the nonce value of 12
11
setApprovalForAll
transaction11
but with a higher gas fee of 26 Gwei
setApprovalForAll
submitted with 8 Gwei
was cancelled and the new/sped-up transaction was picked by the miners and got completed