7 May 2019. Attackers withdrew 7,000 BTC, worth about $40M, from Binance's hot wallet in a single transaction.
The exchange stated that the attackers had obtained a large number of user API keys, two-factor authentication codes and potentially other information, assembled through phishing, malware and other techniques, and had structured the withdrawal so that it passed the venue's existing checks.
Read what those users had. They had two-factor authentication enabled. It did not help.
A one-time code is a phishable secret: you can be talked into reading it out or typing it into a convincing page, and it is valid for the attacker for the next thirty seconds. An API key is worse, because it is a separate credential that bypasses the login entirely, and F109-02 is a whole lesson on that.
Binance covered the loss in full from its SAFU insurance fund. No user balances were reduced. Deposits and withdrawals were suspended for about a week.
Which is the part to sit with. What made this survivable for those users was not a control any of them had configured. It was a discretionary decision by the venue to absorb the loss, and F104-06's sort puts that firmly in the policy bin.
F106-03 hardened your identity: the recovery chain, the phone number, the email. This lesson hardens the account itself, and the two are not the same job.
The four controls, in order
Most guidance lists these alphabetically or in the order the settings page presents them. That is the wrong order, and the right one has a clear first place.
1. A withdrawal allow-list, with a delay
This is the control that matters most and the one people configure last, if at all.
You register the addresses you are willing to withdraw to. Withdrawals to anything else are refused. Adding a new address triggers a waiting period, usually 24 to 48 hours, and a notification.
Why it beats everything else: two-factor authentication defends the session. An allow-list constrains the outcome. An attacker who has fully compromised your account, with your password, your codes and your email, still cannot send funds to an address you did not pre-approve, and the moment they try to add one you are notified with a day to respond.
That is a structural control in F104-06's sense. It does not depend on you being right in the moment, which is the property F106-02 says every good defence needs.
2. A hardware security key
F106-03 ranked the factors and the ranking holds here. A hardware key checks the domain itself and will not respond to a lookalike, which is exactly the failure that harvested codes in the autopsy.
An authenticator app is the acceptable second choice. It is still phishable, which is the whole point of the first row.
3. No SMS anywhere in the chain
Remove SMS as a recovery method wherever the venue permits it. F106-03's argument in full: when the same channel authenticates and recovers, it is not a second factor, it is a bypass.
4. A dedicated email
An address used for nothing else, not published anywhere, itself protected at level 2. This removes you from the automated target lists in F106-05 before any of the rest matters.
Adding an allow-list to an account that already holds value has a gap: the delay protects future changes and does nothing about the state you are in right now.
Configure it first, on an empty account, then fund it. The order costs you nothing and closes the window.
And add the addresses you will actually use, including your own self-custody address from F104-02, so that the routine path is the pre-approved one and the delay never becomes an obstacle you are tempted to work around.
What the venue enforces and what you do
Worth separating, because a control you assume is enforced and is not is worse than no control.
The venue enforces: the allow-list, the withdrawal delay, session controls, device management, and any anti-phishing code it prints in its own emails.
You are responsible for: everything in your recovery chain. F106-03's exercise applies unchanged, because an exchange account that resets by email sits behind an email that resets by phone.
Nobody enforces: that the venue remains solvent, that it does not freeze you, and that its staff are not bribed. That is F107-04, and no setting on the page touches it.
Anti-phishing codes and API keys
Two specifics that repay a minute each.
Set an anti-phishing code if the venue offers one. It is a phrase you choose that appears in every genuine email from them. A message without it is fake, and this converts a judgment call into a check, which is the F106-02 property again.
Audit your API keys. If you have never created one, confirm there are none, because their presence on an account you did not intend is a finding. If you have, they are the credential class that bypassed everything in the autopsy, and F109-02 covers them properly.
The insurance fund
Several venues maintain a fund and describe it as protecting users. Assess it honestly, in both directions.
It is real. Binance paid $40M from one in 2019 and users lost nothing.
It is not a claim you hold. It is a pool the venue may choose to apply, at its discretion, in circumstances it defines. There is no policy document naming you, no regulator adjudicating, and no process to appeal a refusal.
It has a size, and the size is not usually published in a way that lets you compare it against total customer balances.
So: a venue with a fund is better than one without, the fund is a policy rather than a guarantee, and it does not change the amount you should leave on the venue. That number comes from F103-03's custody line.
I have two-factor authentication on, so my exchange account is secure.
Two-factor authentication is worth having and it defends against exactly one thing: somebody who has your password and nothing else. That is a real category and it is no longer the common one.
It does not defend against a one-time code being phished, which is what the autopsy describes at scale, because a code you can be persuaded to type is a code the attacker can use. It does not defend against an API key, which does not go through the login at all. It does not defend against a session token being stolen, which is how F104-01's Connect Kit attacker got into an npm account despite 2FA. And it does not defend against your recovery chain, which is what took the SEC's account in F106-03 without any password ever being learned.
The pattern connecting all four is that authentication controls fail to phishing, and structural controls do not. A code, a password and a session are all things a sufficiently convincing conversation can obtain. An allow-list is not, because it does not care who is asking.
Which is why the four controls are in that order, and why the one everybody configures is third.
Configure the withdrawal allow-list with a delay first, because it is the only control that survives a full account compromise: two-factor authentication defends the session and an allow-list constrains the outcome. Then a hardware security key, then remove SMS from the chain entirely, then a dedicated email. The 2019 Binance users had two-factor authentication and lost nothing only because the venue chose to absorb $40M, which is a policy rather than a claim you hold. Set the allow-list before you fund the account, and remember that authentication controls fail to phishing while structural ones do not.