一句话版本
以太坊地址是 40 个十六进制字符,人眼通常只看开头几位和结尾几位。攻击者批量生成首尾和你常用地址一样的假地址,再给你转一笔 0 金额或极小金额的"交易",让它出现在你的转账历史里。下次你从历史记录里复制地址时,复制到的就是攻击者的地址。 这种攻击不需要偷任何东西,只利用人的习惯。防御靠的是:不从历史里复制地址、用地址簿、比对更多字符、钱包主动标记相似地址。
全文分三层:
- 通俗理解:攻击是怎么做的
- 实际用处:真实损失案例,钱包和交易所的应对
- 原理与工程要点:生成相似地址的成本、EIP-55 校验和能做什么不能做什么、检测规则
第一层:通俗理解
1.1 攻击步骤
钱包界面为了好看,地址常常被缩写成 0x7a3f...91c2。真地址和假地址在缩写后一模一样。
1.2 为什么有效
- 人对一长串随机字符的记忆,基本只有首尾几位;
- "从历史里复制"是很自然的操作,大家都这么做;
- 攻击成本极低:生成地址和发 0 金额转账都很便宜,可以对成千上万人广撒网。
第二层:实际用处
- 规模:链上安全公司的统计显示,地址投毒尝试每年数以亿次计,受害者损失累计达数千万美元以上。
- 典型大案(2024 年 5 月):一名用户因为复制了投毒地址,一次转出 1155 枚 WBTC(当时约 6800 万美元)。这起事件后来出现戏剧性转折:经过链上喊话和追踪,攻击者把大部分资金退还了。但绝大多数受害者没有这种运气。
- 行业应对:
- 钱包和区块浏览器默认隐藏 0 金额转账和未知代币;
- 转账时提示"这个地址和你的历史联系人很像";
- 交易所的提币地址白名单,从源头上避免从历史复制。
Caloogy Wallet 也采用了地址投毒检测。
第三层:原理与工程要点
3.1 生成相似地址有多难
以太坊地址由公钥的哈希截取而来,可以看作 40 个随机的十六进制字符。要让假地址和真地址前 位、后 位都相同,平均要试
个私钥。
| 匹配位数(首 + 尾) | 平均尝试次数 | 难度 |
|---|---|---|
| 4 + 4 | 一块显卡几秒到几分钟 | |
| 6 + 6 | 显卡集群,可行 | |
| 10 + 10 | 实际不可行 |
注意这是第二原像式的搜索(给定一个地址找相似的),不是生日攻击,所以不能开平方(见《生日悖论与哈希碰撞》)。结论是:只核对首尾 4 位远远不够,核对得越多越安全。
3.2 EIP-55 校验和:能防手误,防不了投毒
以太坊地址的大小写不是随便的。EIP-55 规定:对小写地址取 Keccak-256 哈希,哈希的第 个十六进制位 时,地址第 位的字母就写成大写。
EIP-55 标准里的测试地址
正确写法:0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed
如果最后一位抄错,...BeAed 变成 ...beaee,那么对应地址的正确大小写变为
0x5Aaeb6053f3e94c9B9a09F33669435e7EF1BeAee,几乎每个字母的大小写都变了。
钱包发现你输入的大小写模式和正确的不一致,就会报错。(已用 Python 验算。)
和弃九法与校验位里的身份证、银行卡校验位一样,EIP-55 能抓住随机的抄写错误。但投毒地址本身就是一个合法的地址,有它自己正确的校验和,所以 EIP-55 完全挡不住投毒。
3.3 检测规则
| 规则 | 说明 |
|---|---|
| 和历史交易对象的首尾相似度比较 | 前后若干位相同,但整体不同,就标记为可疑 |
| 对方是否给你发过 0 金额或假币转账 | 投毒的典型前奏 |
| 这是不是第一次转给这个地址 | 首次转账本身就应该加一道确认 |
| 代币是否在白名单里 | 投毒常伴随假代币(名字也叫 USDT,但合约地址不同) |
3.4 界面设计
- 不提供"从历史记录选择收款人"这个入口,改用需要主动添加的地址簿;
- 确认页完整显示地址,而不是缩写,并高亮更多位;
- 高风险时要求用户手动输入地址的若干位(打断"看一眼就点确认"的习惯,见《风控评分与摩擦设计》);
- 首次转账或大额转账前,建议先转一笔小额测试,或者通过另一个渠道向对方核对地址(见《带外核对》)。
总结
| 层次 | 要点 |
|---|---|
| 攻击 | 生成首尾相同的地址,用 0 金额转账混进你的历史 |
| 成本 | 首尾 8 位匹配只要几十亿次尝试,很便宜 |
| 校验和 | EIP-55 防手误,不防投毒(投毒地址本身合法) |
| 防御 | 不从历史复制;地址簿;完整显示;相似度检测;带外核对 |