SlowMist: “Blank Check” eth_sign Phishing Analysis

SlowMist
5 min readOct 17, 2022

--

We’ve recently witnessed a number of phishing incidents involving eth_sign signatures. In this article, we’ll show you how to recognize them so you don’t become a victim of one of these scams.

Phishing Site 1: https://moonbirds-exclusive.com/

When we connect our wallets and click Claim, MetaMask will display a signature request with red letters. This is a warning, since it’s almost impossible to determine what the signature request is for.

This is actually a very dangerous type of signature request. It’s basically like signing a “blank check” for Ethereum. Once you sign the transaction, scammers can use your private key to sign any transaction.

However it doesn’t stop there: After you reject the transaction above, it can create another request in MetaMask, this time asking you to confirm it. Let’s take a closer look at the content of this request. The SetApprovalForAll method is used, and the target of the Approved asset is displayed as All of your NFT. Once you confirm, the scammers will now have access to all your NFTs. As shown below:

Phishing Site 2: https://dooooodles.org/

We used MistTrack to analyze the scammer address (0xa594f48e80ffc8240f2f28d375fe4ca5379babc7) and here what we found:

According to our findings, the scammer used SetApprovalForAll numerous times to steal the victims’ NFTs. They stole 33 NFTs in total, and after selling some of them, they received more than 4 ETH.

Let’s take a closer look at the eth_sign request. Per MetaMask:

MetaMask currently has six types of signature requests. However, eth_sign is the only request where there are warnings in red. This is because eth_sign “is an open-ended signing method that allows signing an arbitrary hash, which means it can be used to sign transactions, or any other data, making it a dangerous phishing risk.”

According to MetaMask’s official documentation, the eth_sign method can sign any hash, and when you sign a transaction, it also signs a sequence of hashes, but MetaMask handles the entire encoding process for us. So let’s go over the process from encoding to transaction broadcasting:

Before the transaction is broadcast, MetaMask receives the object (To) we are transferring to, the amount (Value), and the attached data (Data). It also automatically collects the nonce, gasPrice, and gasLimit parameters to calculate for us, and encodes them in RLP to get the raw transaction content (RawTransaction). If it’s a contract call, then To is the contract address and data is the call data.

rlp = require('rlp');
// Use non-EIP115 standardconst transaction = { nonce: '', gasPrice: '', gasLimit: '', to: '0x', value: '', data: '0x'};

// RLP encodeconst rawTransaction = rlp.encode([transaction.nonce, transaction.gasPrice, transaction.gasLimit, transaction.to, transaction.value, transaction.data]);

Next, perform a keccak256 hash on this to get a string of bytes32. Which is the data we needed to sign.

// keccak256 encodeconst msgHex = rawTransaction.toString('hex');const msgHash = Web3.utils.keccak256('0x'+ msgHex);

After we use MetaMask to sign this string of data, we will get the r, s, v values, and use these three values to perform RLP encoding with nonce/gasPrice/gasLimit/to/value/data to get the original signed transaction content. Now, you can broadcast the transaction.

rlp = require('rlp');
const transaction = { nonce: '', gasPrice: '', gasLimit: '', to: '', value: '', data: '', v: '', r: '', s: ''};

// RLP encodeconst signedRawTransaction = rlp.encode([transaction.nonce, transaction.gasPrice, transaction.gasLimit, transaction.to, transaction.value, transaction.data, transaction.v, transaction.r, transaction.s]);

As mentioned above, the eth_sign method can sign any hash, so naturally the bytes32 data we signed can be used again. Therefore, the attacker only needs to obtain our address to analyze and query our account after we connect to the DApp and can construct arbitrary data (such as native token transfer or a contract call) and trick us into signing through eth_sign.

MetaMask will display red letters as a warning any time the eth_sign method is used. You’ll most likely not know what you’re signing for since the message will just be a string of bytes32 hashes. DO NOT SIGN anything unless you know what you’re signing.

Even if you cancel the transaction, scammers can attach another pop-up asking you to confirm the transactions. As you can see below, this wasn’t to confirm that you have canceled the eth_sign request, but to confirm the SetApprovalForAll function so they can steal all your NFTs. This is why it’s more important than ever to read what you’re signing.

This article primarily introduces how the eth_sign method can be used in a phishing attack. Although MetaMask will display a risk warning when signing, when combined with other phishing techniques, it can become difficult for users with no security experience to avoid these traps. Users should always be on the lookout, know the domain name, and check the signature data carefully. Security extensions like RevokeCash, ScamSniffer, wallet guard, etc. are a great way to help spot phishing sites and remove approvals to malicious addresses.

--

--

SlowMist
SlowMist

Written by SlowMist

SlowMist is a Blockchain security firm established in 2018, providing services such as security audits, security consultants, red teaming, and more.

Responses (1)