Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ledger Nano: Metamask Address does not correspond to Ledger #6012

Closed
AusIV opened this issue Jan 11, 2019 · 96 comments · Fixed by MetaMask/eth-ledger-bridge-keyring#146 or #14799
Closed
Assignees
Labels
area-hardware hardware-ledger needs-reproduction Sev1-high High severity; partial loss of service with severe impact upon users, with no workaround. stability type-bug

Comments

@AusIV
Copy link

AusIV commented Jan 11, 2019

Describe the bug
Somehow a Metamask account was created in association with a Ledger Nano that did not correspond to any account supported by that ledger.

To Reproduce
We have not been able to reproduce this issue reliably, but here are the steps we took to encounter it in the first place:

  1. Connect a ledger nano, unlock it, and navigate to the Ethereum app on the Ledger
  2. In Metamask, select "Connect Hardware Wallet" from the accounts menu
  3. Select Ledger and Connect
  4. Select an account and click "Unlock"
  5. Click the copy button next to the address to copy the wallet address.
  6. Send ETH to that address.
  7. Reboot, disconnect the ledger, come back later.
  8. Reconnect the ledger nano, unlock it, etc.
  9. Attempt to send a transaction from the Metamask account.
  10. Get an error similar to the effects of Ledger Nano: Submitting Transactions from Wrong Address #6011 - Metamask is sending from a different address than the attached ledger.
  11. If you attempt to import another account from the ledger, the original address is not available.

Expected behavior
If I connect an account from a ledger nano, I expect that account / address to exist on the ledger nano.

Browser details (please complete the following information):

  • OS: Windows 10
  • Browser Chrome
  • MetaMask Version 5.3.0

Additional context
I'm not certain how this happened. My understanding is that when a ledger is connected, Metamask asks it for a list of addresses, and those addresses are provided by the nano without any proof that it can sign messages with it. I suspect that some kind of interference (static electricity, gamma rays, a butterfly flapping its wings in China, etc.) caused the initial transmission of the address to be sent incorrectly, but it's hard to say for sure.

Ledger Live does not allow a user to connect an account without first confirming the address by clicking a button on the ledger (I'm not sure how this works under the hood, but I have the impression it's signing a message). It strikes me that this could have been avoided if metamask had required the user to sign a message before considering the account connected. In our case we lost about $2 worth of ETH, but it could have been a lot worse.

@jennypollack
Copy link
Contributor

@dmdque
Copy link

dmdque commented Aug 2, 2020

I'm not sure if the fix addresses this exact issue.

From the tweet:

Ledger signing would be done using the first Ledger account (at index 0) rather than the users’ currently selected account.

From the description:

a Metamask account was created in association with a Ledger Nano that did not correspond to any account supported by that ledger

I suspect @AusIV checked that the address doesn't match the first Ledger account.

I'm dealing with an issue that sounds very similar to what @AusIV described. An address was created when a Ledger Nano S was plugged in, but it doesn't seem to be associated with it at all. (Tried deriving addresses with all sorts of derivation paths, none of them match).

MetaMask Version v8.0.5

@danfinlay
Copy link
Contributor

Reopening so we will further investigate the possibility of this happening. If this is an active issue, it’s high priority, and worthy of a bug bounty.

@danfinlay danfinlay reopened this Aug 3, 2020
@danfinlay
Copy link
Contributor

danfinlay commented Aug 3, 2020

Our eth-ledger-bridge-keyring module, which we wrote to connect to the ledger-bridge, uses hdkey to derive an address for a given account index.

Looking at the hdkey changelog I found a bug in their key generation that they fixed in April.

A Reproduction Opportunity

EDIT: I have an xpub from an affected user so if this is the cause I should be able to verify without users needing to do the following steps.

IF that were the cause of this issue, then it could be possible that people who were affected by this issue could be able to reproduce it by loading a version of MetaMask from before April 14th 2020, which would be Version 7.7.6 (which is coincidentally the release that fixed the issue that this one was originally closed for resembling).

From that version, affected users would need to try connecting their ledger in the same way they did the first time they saw the disappeared account. If anyone is able to reproduce in that way, we may have identified the issue.

You could then try sending from that account, but from the looks of it, if this was the issue, the address was incorrectly generated, and the ledger would have never held the private key for that address, but at least we could rule this out.

If we were not able to rule this out in this way, we could try other ways of testing it, or just continue looking for other explanations, as we will anyways.

@danfinlay
Copy link
Contributor

danfinlay commented Aug 3, 2020

Reviewed the ledger-bridge-keyring code again, took some extra notes.

on hdkey

  • We were pinned at version 0.8.0 all this time, and so we would have missed any fixes they published since then.
  • The issue I noted above is apparently extremely rare, so it is probably not the problem we're looking for.

We only ever use hdkey to derive the dkey value.

What's strange about this usage is that the derive function depends on a locally available private key to derive beyond any hardened path segments (segments ending in ' involve hashing, and cannot be derived from an xpub). That makes me want to look closer at times this function is called.

That method is only used in the getAddressFromIndex method, and that method is called in two places:

Both of these suggest the older, non-bip-44 derivation "Ledger Live" strategy, and this is reinforced by a comment in the getPathForIndex method.

Working with an affected user, they tried using our "Legacy derivation" strategy and it did not result in re-generating their reportedly missing accounts. While I don't understand that code yet (our team has today off, and we should have more recently-acquainted eyes on this starting tomorrow), since that code has been the same since the first commit, I think it's worth considering some other possible causes before digging deeper there.

on skipping "unused" accounts

This keyring controller enforces a portion of bip44 that none of our other keyrings do: It actually checks etherscan for any known transactions before considering an account to be valid.

I think we could probably remove that:

  • It slows down our derivation
  • It's a privacy leak of account data
  • It deprives users of the ability to generate many addresses and hand them out before using them.

For a second I was concerned maybe it only counted outgoing txs, but that's not the case, so it shouldn't be the cause here, but noting it as an idiosyncrasy we could probably do without.

@Gudahtt Gudahtt added the Sev1-high High severity; partial loss of service with severe impact upon users, with no workaround. label Aug 4, 2020
@Gudahtt Gudahtt added type-bug and removed P1-asap labels Jan 6, 2021
@mdaria510
Copy link

mdaria510 commented Feb 19, 2021

Edit: Turned out to be a really convoluted case of user error.

@loupiote
Copy link

loupiote commented Feb 19, 2021

The addresses are derived by the ledger from the derivation path that is sent to it (in this case, by MM). e.g. MM sends the ledger m/44'/60'/0'/0 , and the ledger will return the corresponding ETH address. So if the bug occurs in the chain of events leading to the ledger receiving that derivation path, then possibly a garbled derivation path is passed to the ledger, such as /76344'/892394'/73483892'/38349471 , and the ledger would return an ETH address that will be later inaccessible (unless the same garbled path could be passed to the ledger again).

The Ethereum app (nor any other app except the BTC app) on the ledger does not display a warning when asked to derive an address from a weird-looking derivation path. It does the "unusual derivation path" check for BTC.

@loupiote
Copy link

loupiote commented Feb 19, 2021

There have been similar issues reportedly seen using other ETH wallet apps like MyEtherWallet (connected to the ledger), and so far no good explanation. Could also have been caused by a garbled derivation path passed to the ledger, or by a rare / random bug happening on the ledger firmware or ledger Ethereum app itself.

@loupiote
Copy link

loupiote commented Feb 19, 2021

Another thing is that I am not sure if there is actually a good error correction/detection for all the transmission between the computer and the ledger on the USB line (HID procotol).

If there is no strong error detection, then an undetected transmission error could change some bits in the derivation path when it is sent to the ledger, I guess...?

@itboy79
Copy link

itboy79 commented Apr 12, 2021

the issue is still open. any way to regain access to token send to unexisting address?

@crypt012
Copy link

I encountered the same issue. This is a very worrying problem. How to regain access to my ETH?
I submitted a support ticket on metamask, I hope this will help solve this.

@itboy79
Copy link

itboy79 commented Apr 13, 2021

does your issue ws similar to this or the one I suffer? --> this is way worst #10857

I encountered the same issue. This is a very worrying problem. How to regain access to my ETH?
I submitted a support ticket on metamask, I hope this will help solve this.

@crypt012
Copy link

I will give more details tomorrow, but I ended up sending ETH to an address given by metamask after unlocking ledger, adding hardware wallet address. And when I want to do a tx from this wallet I get an error message telling me it does not belong to this ledger device...

does your issue ws similar to this or the one I suffer? --> this is way worst #10857

I encountered the same issue. This is a very worrying problem. How to regain access to my ETH?
I submitted a support ticket on metamask, I hope this will help solve this.

@crypt012
Copy link

crypt012 commented Apr 13, 2021

Here are some more details of what happened to me.
I wanted to use a new address from my ledger. I clicked on "connect a hardware wallet", choose an address from the list after unlocking my ledger. Then as usual Metamask added it to my account. I sent ETH to this wallet, I can now see it in my wallet but I am unable to move my funds. I get an error message telling me this wallet doesn't belong to my ledger device.

I tried to add this specific address on another computer, but it's not visible anymore. The only place where I can see the wallet where my funds are stuck is the metamask which encountered the bug.

This could eventually be a derivation path issue, I now have 2 wallets with the same number ("Ledger X (legacy)") : one legit and one impossible to access.

OS : Windows 10
Chrome : 88.0.4324.190
Metamask : 9.3.0
Ledger : 1.6.1

@MetaMask : I opened a support ticket with logs and all infos I could provide.

@Heineseeki
Copy link

I encountered the same issue. This is a very worrying problem. How to regain access to my ETH?
I submitted a support ticket on metamask, I hope this will help solve this.

What did metamask say? Did you get access to your funds again?

@loupiote
Copy link

loupiote commented May 31, 2021

I have had reports of very similar situations with the Binance Chain Wallet Chrome extension, which appears to have been derived from an earlier version of MetaMask.

I.e. people depositing to addresses supposed to be derived from the Ledger (often, those are on the BCS network, but BSC uses the same derivation path schemes as Ethereum, and on the ledger, it uses the Ethereum app).

Then people realize that they have no control on those addresses, and they appear to be neither derived from the ledger seed, nor from the internal 12-word seed of the Binance Chain Wallet Chrome extension, or at least not derived with any of the known derivation path schemes.

So, extremely similar situation as the one described by others in this thread. And pretty large funds have become stranded (tens of thousands of dollars value).

See some reports here: https://www.reddit.com/r/ledgerwallet/comments/mnj9vx/missing_address_for_binance_smart_chain_generated/

I think the only way to understand those types of derivation issues would be to have a log / trace file of all the interactions between MetaMask (and other similar extensions like Binance Chain Wallet), and the ledger device.

@crypt012
Copy link

crypt012 commented Jun 2, 2021

Thanks for this update @loupiote. I will have a look on reddit also.
This issue has been raised here more than 2 years ago, and I'm not sure Metamask is investigating it...
Very worrying issue. I'm now scared each time I use a new address with Metamask.

@loupiote
Copy link

loupiote commented Jun 2, 2021

Very worrying issue. I'm now scared each time I use a new address with Metamask.

no reason to be scared, but it's always a good idea to check that you are in control of any address you deposit large fund on. You can check that by using other ETH wallets like MyEtherWallet or MyCrypto.

@vlindersteen
Copy link

Hey guys!

I think i have the same problem.

Somehow one of addresses completely disappeared from my metamask and i was unsure if the address was connected to my Ledger.

Luckily i found this topic and it seems that after 2 days of non-stop searching i finally found at least a beginning to hopefully a solution.

I opened a topic on metamask support forum as well about my problem for anyone interested in what i experienced so far: https://community.metamask.io/t/metamask-account-suddenly-gone-can-i-still-recover-my-funds/24484

@vlindersteen
Copy link

I've released a tool that worked in my case to recover funds. It might give you an idea: https://github.com/ApacheSub/bsc_recoverfunds_extension

In my case as you can see on the tool, the wallet used derivation path address with index 4 to derive a child from that address. Same kind of principle might apply here too.

Is there something like this for Ethereum addresses as well?

@vlindersteen
Copy link

thanks for your reply. Could you give me more details on how to bruteforce this ? The bug seems very similar so I hope your solution will work :)

You can try the bsc_recoverfunds_extension, which will look at a single derivation path that may recover access to funds inaccessible due to the Binance Chain wallet extension bug. We don't know if the MM issue is similar, because it could never be reproduced.

We have developed custom tools that can bruteforce millions of derivation paths, so if you have a case of a MM address (supposedly derived from a Ledger seed) that became inaccessible, we could run our search on it, or you can make your own tools to do the bruteforce.

I have this problem now!

@vlindersteen
Copy link

Might be BIP44 or m/44'/60/0

I've added a new script recoverFunds_manypaths.js that will try to check more paths. Please confirm that you did indeed enter the mnemonic and also targetAddr to the script which is required for it to work.

I just wrote the script without much testing so incase you encounter errors, let me know and I will fix them to the best of my knowledge.

Does the same script also works for ethereum and metamask? (the one you made is for bsc right?)

@vlindersteen
Copy link

@ApacheSub I figured out the issue. For some reason the newly created public address was associated with an old ledger. This appears to be a bug in MetaMask. I was able to sign transactions with an old private key.

@ApacheSub thank you for your help. I'd like to make a donation. Could you please share a public address I could send you a donation to?

Please help me as well!

@ApacheSub
Copy link

@ApacheSub I figured out the issue. For some reason the newly created public address was associated with an old ledger. This appears to be a bug in MetaMask. I was able to sign transactions with an old private key.
@ApacheSub thank you for your help. I'd like to make a donation. Could you please share a public address I could send you a donation to?

Please help me as well!

Hi,

Just checked back on this now. Did you figure it out yet?

It should work for Ethereum. If not, might require some (small) changes but you should be able to try it safely.

Could you report back to me if you need some help?

@vlindersteen
Copy link

vlindersteen commented Mar 6, 2023

@ApacheSub I figured out the issue. For some reason the newly created public address was associated with an old ledger. This appears to be a bug in MetaMask. I was able to sign transactions with an old private key.
@ApacheSub thank you for your help. I'd like to make a donation. Could you please share a public address I could send you a donation to?

Please help me as well!

Hi,

Just checked back on this now. Did you figure it out yet?

It should work for Ethereum. If not, might require some (small) changes but you should be able to try it safely.

Could you report back to me if you need some help?

Hi Apache, thanks for your response!

I've been spending days and days to figure out the problem but still no result.

I've managed to tweak a few things and ran the programs but unfortunately it couldn't find my address.

At this point i'm so desperate that i even consider the possibility that a few years ago when i bought the ledger, i created the first seed phrase (which my outdated ledger live and firmware still used), and that i created a new seed phrase after that, causing chaos and problems.
But i have to say, i have no evidence and memory at all that i created a different seedphrase earlier, and used a new one after that.

I still want to figure out the problem, but i think i need to start all over again. If you have time to help me and if you want me to clear up and sketch the situation, please let me know!

@vlindersteen
Copy link

vlindersteen commented Mar 6, 2023

I have a list with the old ledger derivation path as well, not sure if it will help.

https://gist.github.com/miguelmota/034c81886bd23b25c64ec5eda9251641

Could i tweak your code and then change the derivation path to the old ledger derivation path?

@ApacheSub
Copy link

I have a list with the old ledger derivation paths as well, not sure if it will help.

https://gist.github.com/miguelmota/034c81886bd23b25c64ec5eda9251641

I can take a look soon and see if my program doesn't cover some of those derivation paths.

@ApacheSub
Copy link

So I've been working on this but it looks like the ethereum library I am using does not support derivation paths that do not start with 'm'. Right now I am improving my program to support more non-standard paths but I will need to figure out a way to derive an address that uses the old ledger derivation path to help you out.

I will reply in this thread when there's progress on that.

@loupiote
Copy link

loupiote commented Mar 8, 2023

@ApacheSub

"m/" is just a notation convention that indicate that the derivation path starts deriving from the "master seed" (m). If a software package or library uses derivation path such as "0'/0'/0/0", in fact that's the same as the derivation path usually written as "m/0'/0'/0/0". the "m/" is just a notation convention.

So I don't really understand what you are saying...

@ApacheSub
Copy link

@ApacheSub

"m/" is just a notation convention that indicate that the derivation path starts deriving from the "master seed" (m). If a software package or library uses derivation path such as "0'/0'/0/0", in fact that's the same as the derivation path usually written as "m/0'/0'/0/0". the "m/" is just a notation convention.

So I don't really understand what you are saying...

I had not dived much into details of derivation itself yet and just went based on this resource which, for some reason, specifies Ledger Legacy path without the 'm': https://gist.github.com/miguelmota/034c81886bd23b25c64ec5eda9251641

I was under the impression that it may have some deeper meaning and would actually be used in the derivation.

Good to know though, knowing that solves the problem.

@loupiote
Copy link

loupiote commented Mar 9, 2023

@ApacheSub

On page https://gist.github.com/miguelmota/034c81886bd23b25c64ec5eda9251641
On the first line, the "m/" is missing before "44'/...". This is just a typo.

@vlindersteen
Copy link

notation convention that indicate that the derivation path starts deriving from the "master seed" (m). If a software package or libr

Thanks a lot guys! If i can help you with anything just let me know.

@ApacheSub
Copy link

ApacheSub commented Mar 11, 2023

@vlindersteen

I've now updated the program. It will now cover dramatically more paths. It will first check the regular paths (i.e. ones that are here: https://gist.github.com/miguelmota/034c81886bd23b25c64ec5eda9251641).

If none of those is a match, it will recurse practically any path but it may be very slow at doing so. It can even support adding more depth to searched paths, however, be prepared to wait a long time for it to run.

I have not extensively tested the new functionality but as far as I could see, it works.

Please report any bugs though :)

https://github.com/ApacheSub/bsc_recoverfunds_extension

EDIT: Fixed some of the performance issues. Recursion turned out to be problematic.

@vlindersteen
Copy link

@vlindersteen

I've now updated the program. It will now cover dramatically more paths. It will first check the regular paths (i.e. ones that are here: https://gist.github.com/miguelmota/034c81886bd23b25c64ec5eda9251641).

If none of those is a match, it will recurse practically any path but it may be very slow at doing so. It can even support adding more depth to searched paths, however, be prepared to wait a long time for it to run.

I have not extensively tested the new functionality but as far as I could see, it works.

Please report any bugs though :)

https://github.com/ApacheSub/bsc_recoverfunds_extension

EDIT: Fixed some of the performance issues. Recursion turned out to be problematic.

Thank you! I will give it a shot tomorrow and see if it works.

@vlindersteen
Copy link

@vlindersteen

I've now updated the program. It will now cover dramatically more paths. It will first check the regular paths (i.e. ones that are here: https://gist.github.com/miguelmota/034c81886bd23b25c64ec5eda9251641).

If none of those is a match, it will recurse practically any path but it may be very slow at doing so. It can even support adding more depth to searched paths, however, be prepared to wait a long time for it to run.

I have not extensively tested the new functionality but as far as I could see, it works.

Please report any bugs though :)

https://github.com/ApacheSub/bsc_recoverfunds_extension

EDIT: Fixed some of the performance issues. Recursion turned out to be problematic.

image

I've tried scanning it a first time and get this message. Finally can spend some more time today so will cover more results..

@vlindersteen
Copy link

Tweaked a few things (re-installed npm install ethereum-cryptography) and ran it again.

It finished in about 40 minutes but didn't find anything. It seems to be running correctly though, previously i just got a message after 10 minutes saying "we didnt find your address" and not showing it's searching through all the different paths like in this screenshot.

Going to continue running some things.

image

@ApacheSub
Copy link

Tweaked a few things (re-installed npm install ethereum-cryptography) and ran it again.

It finished in about 40 minutes but didn't find anything. It seems to be running correctly though, previously i just got a message after 10 minutes saying "we didnt find your address" and not showing it's searching through all the different paths like in this screenshot.

Going to continue running some things.

image

Thanks for the update. I have tried running it on MacOS, Linux and Windows with a freshly cloned repository and could not reproduce your issue.

Keep in mind that npm install is all you should need to do while in the cloned folder to install all dependencies.

Anyway, looks like those paths did not find the address then. Do you think it's possible an address could have an index higher than 20? If so, you could try increasing the max indices.

You could also try it with any older mnemonic's that you may have used. Otherwise, if none of your known mnemonics were used, maybe the tool won't be helpful :(

@vlindersteen
Copy link

Tweaked a few things (re-installed npm install ethereum-cryptography) and ran it again.
It finished in about 40 minutes but didn't find anything. It seems to be running correctly though, previously i just got a message after 10 minutes saying "we didnt find your address" and not showing it's searching through all the different paths like in this screenshot.
Going to continue running some things.
image

Thanks for the update. I have tried running it on MacOS, Linux and Windows with a freshly cloned repository and could not reproduce your issue.

Keep in mind that npm install is all you should need to do while in the cloned folder to install all dependencies.

Anyway, looks like those paths did not find the address then. Do you think it's possible an address could have an index higher than 20? If so, you could try increasing the max indices.

You could also try it with any older mnemonic's that you may have used. Otherwise, if none of your known mnemonics were used, maybe the tool won't be helpful :(

Yup, i'm going to try max the index to 40, since there could be a small chance it's within that range. Should i edit max_path_index or max_child_index? Or both?

Do you think changing Max Depth of the path could be useful? If so, what would you advise to input as max depth number, since it can take so long?

@ApacheSub
Copy link

Tweaked a few things (re-installed npm install ethereum-cryptography) and ran it again.
It finished in about 40 minutes but didn't find anything. It seems to be running correctly though, previously i just got a message after 10 minutes saying "we didnt find your address" and not showing it's searching through all the different paths like in this screenshot.
Going to continue running some things.
image

Thanks for the update. I have tried running it on MacOS, Linux and Windows with a freshly cloned repository and could not reproduce your issue.
Keep in mind that npm install is all you should need to do while in the cloned folder to install all dependencies.
Anyway, looks like those paths did not find the address then. Do you think it's possible an address could have an index higher than 20? If so, you could try increasing the max indices.
You could also try it with any older mnemonic's that you may have used. Otherwise, if none of your known mnemonics were used, maybe the tool won't be helpful :(

Yup, i'm going to try max the index to 40, since there could be a small chance it's within that range. Should i edit max_path_index or max_child_index? Or both?

Do you think changing Max Depth of the path could be useful? If so, what would you advise to input as max depth number, since it can take so long?

I would probably change both. I think depth is less important and unlikely any wallet used different depth so at most increase it by one if nothing else works.

@vlindersteen
Copy link

vlindersteen commented Mar 18, 2023

I've let it run for 12 hours but no result (does it halt the searching if it finds the address btw?)

Until here is where i've let it run, thought it would be finished here..

These are the settings:

const MAX_DEPTH = 4;
const MAX_PATH_INDEX = 40;
const MAX_CHILD_INDEX = 40;

image

@ApacheSub
Copy link

ApacheSub commented Mar 18, 2023

I've let it run for 12 hours but no result (does it halt the searching if it finds the address btw?)

Until here is where i've let it run, thought it would be finished here..

These are the settings:

const MAX_DEPTH = 4; const MAX_PATH_INDEX = 40; const MAX_CHILD_INDEX = 40;

image

Yes, it does stop if it finds the address.

I think it's probably safe to say that the issue may be something other than a wrong derivation path in your case.

@peteralexon
Copy link

notation convention that indicate that the derivation path starts deriving from the "master seed" (m). If a software package or libr

Thanks a lot guys! If i can help you with anything just let me know.

Hey there, i saw your post on metamask, but couldnt reply you as its been past a month, i think you should try contacting Hacktasks Ltd, they might be able to help out... their email is [email protected]
if you need to reach me, my personal email is [email protected], thank me later

@RusseII
Copy link

RusseII commented Sep 19, 2024

I ran into this issue and was able to make a successful recovery.

I used some of the code @ApacheSub wrote for brute forcing the derivation paths, modifying it to use ledger-hw-app-eth instead of importing the private key.

Then, I couldn't find any apps that supported using a custom derivation path (m/44'/60'/0'/1/7) so I created the transaction manually, used ledger-hw-app-eth to sign, and submitted the signed transaction.

Happy to help provide assistance if anyone is in the same boat.

@Pegietix
Copy link

@RusseII Hi, would you be able to share your version pls? I don't want to expose my mnemonic. Can I contact you somehow?

@RusseII
Copy link

RusseII commented Dec 20, 2024

@Pegietix I sent you an email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment