ERC20 Short Address Attack
ERC20 Short Address Attack
什么是ERC20
代币大家应该都很熟悉了,代币也叫 token, 他不是像比特币,以太坊等虚拟币这样建立在大量技术人员的辛苦工作基础之上,用于维持公链运行的虚拟货币。代币一般是依赖于以太坊平台,就是一个以太坊平台上面的一个智能合约里面记录的数字。
所以说token没有任何价值,每个人都可以在1分钟之类创建出无限的token。那么为什么现在有这么多的token价格这么高,还有这么多人去交易呢? 一般来说,发行token的人会将整个token绑定一个很有前途的项目,什么纳米科技,卫星技术,新型动力,怎么牛逼怎么往上面靠,然后找几个币圈有名气的人站台,然后通过各种渠道发布这个token很了不起的舆论,接下来就是上交易所收割韭菜了,至于他们当时标榜的跨时代的项目就不知道是不是能够真的完成了,毕竟钱已经收到口袋里面了。
不可否认,有些token确实很有良心,也真的按照设想的去做了事情。这里不深究发行token的对与错,这里我们讲下ERC20。
大家都来发token,那么这么多的token没有一个统一的标准,不好在以太坊平台进行通用的转让呀,为了便于token的流通,于是出现了一个token的标准叫做ERC20,简单点说,ERC20规定了token智能合约必须要实现的9个方法和2个事件。
具体的方法和事件名请看 ERC-20标准说明
Application Binary Interface(ABI)
这篇文章其实是讲ERC20攻击的,要想攻击ERC20,我们首先要知道怎么去跟以太坊虚拟机进行交互。在以太坊Ethereum 生态系统中, 应用二进制接口Application Binary Interface(ABI) 是从区块链外部与合约进行交互以及合约与合约间进行交互的一种标准方式。 数据会根据其类型按照约定的方法进行编码。
简单点说,一个ABI包括一个函数选择器和函数的参数。
函数选择器是一个函数调用数据的前 4 字节,指定了要调用的函数。这4个字节是函数签名通过 Keccak(SHA-3)哈希之后的前 4 字节。
函数的参数会被编码成32字节,不足32字节的将会补全。ERC20 Short Address Attack 就是在这个函数补全上面出现的。
ERC20 Short Address Attack
我们先看一个简单的token合约,用来转账。
pragma solidity ^0.4.11;
contract MyToken {
mapping (address => uint) balances;
event Transfer(address indexed _from, address indexed _to, uint256 _value);
function MyToken() {
balances[tx.origin] = 10000;
}
function sendCoin(address to, uint amount) returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount;
balances[to] += amount;
Transfer(msg.sender, to, amount);
return true;
}
function getBalance(address addr) constant returns(uint) {
return balances[addr];
}
}
很简单的一个智能合约, 这里我们看下sendCoin的方法,他接收2个参数,一个是接收token的地址,一个是数目。
如果想进行调用,那么生成的ABI可能是这样的:
0x90b98a11
00000000000000000000000062bec9abe373123b9aabbcce608f94eb8644163e
0000000000000000000000000000000000000000000000000000000000000004
其中:
0x90b98a11 是Keccak (SHA-3) 运算之后的方法标记 sha3(sendCoin(address,uint))。
00000000000000000000000062bec9abe373123b9aabbcce608f94eb8644163e 是 20字节的目标地址,被补全到32字节。
0000000000000000000000000000000000000000000000000000000000000004 是 1个字节的4被补全到32字节。
开始攻击
如果攻击者不按常理出牌,并不将参数补全到32字节,那么总的ABI长度会比预料的要小,那么会出现什么问题呢?
还是上面的例子,我们要发送4个token到62bec9abe373123b9aabbcce608f94eb8644163e。
但是我们把地址的最后1个字节“3e”去掉,那么ABI如下所示:
0x90b98a11
00000000000000000000000062bec9abe373123b9aabbcce608f94eb8644163e00
00000000000000000000000000000000000000000000000000000000000004
^^
我们可以看到,最后的04后面其实是少了一个字节的。
那么如果我们把这个ABI传给以太坊虚拟机,会出现什么问题呢?
以太坊虚拟机会将ABI补全,就是在04后面加一个字节00。
参数如下:
_from: 0x58bad47711113aea5bc5de02bce6dd332211aabb
_to: 0x62bec9abe373123b9aabbcce608f94eb8644163e00
_value: 2048
我们看到两个变化,第一目标地址变了,第二转移的数值变了:4<<8 = 2048。
这个就是ERC20 Short Address Attack。
怎么利用?
- 攻击者构建一个最后一个字节为0的地址A。
- 攻击者找到一个发行token的智能合约,在这个智能合约里面,向A存入500token。
- 攻击者从智能合约转出500token到地址A,但是将地址A最后一个字节的0去掉。
- 地址A最后1个字节会被补全,而转账的500token就变成了500<<8。
攻击防范
防范起来其实很简单,做好必要的参数校验即可。
下面的代码加了一个modifier onlyPayloadSize 。 在这个modifier里面,我们做了参数长度的校验。
pragma solidity ^0.4.11;
contract MyToken {
mapping (address => uint) balances;
event Transfer(address indexed _from, address indexed _to, uint256 _value);
function MyToken() {
balances[tx.origin] = 10000;
}
modifier onlyPayloadSize(uint size) {
assert(msg.data.length == size + 4);
_;
}
function sendCoin(address to, uint amount) onlyPayloadSize(2 * 32) returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount;
balances[to] += amount;
Transfer(msg.sender, to, amount);
return true;
}
function getBalance(address addr) constant returns(uint) {
return balances[addr];
}
}
更多教程请参考flydean的博客
ERC20 Short Address Attack的更多相关文章
- Identifying a distributed denial of service (DDOS) attack within a network and defending against such an attack
The invention provides methods, apparatus and systems for detecting distributed denial of service (D ...
- 【转】zigbee终端无法重连的问题解决
zigbee终端无法重连的问题解决 1.zigbee重连的原因 (1)zigbee由于各种原因的干扰导致信号太差而掉线. (2)协调器重启. 2.zigbee终端重连的处理 (1)zigbee掉线后会 ...
- 【转】ZigBee终端入网方式深入分析
前述 继之前对终端Direct Join的分析,发现很多东西还很模糊,存在很多问题.终于找到时间继续深入挖下去,这次应该比较完整地搞清了终端的入网机制,并纠正之前的几个认识偏差. 由于Z-Stack网 ...
- Masonry使用注意事项
1 理解自身内容尺寸约束与抗压抗拉 自身内容尺寸约束:一般来说,要确定一个视图的精确位置,至少需要4个布局约束(以确定水平位置x.垂直位置y.宽度w和高度h).但是,某些用来展现内容的用户控件,例如文 ...
- 第1章 ZigBee协议栈初始化网络启动流程
作者:宋老师,华清远见嵌入式学院讲师. ZigBee的基本流程:由协调器的组网(创建PAN ID),终端设备和路由设备发现网络以及加入网络. 基本流程:main()->osal_init_sys ...
- Ztack学习笔记(4)-系统网络分析
协调器的组网,终端设备和路由设备发现网络以及加入网络 //第一步:Z-Stack 由 main()函数开始执行,main()函数共做了 2 件事:一是系统初始化,另外一件是开始执行轮转查询式操作系统 ...
- 关于NuDaqPci 数据采集
最近在做公司一个fct的测试及调试软件 设计到的比较多的通信问题 1,Gpib通信(调用ADL-GPIB) 2,串口通信 3,Usb通信(调用USBXpress) 4,Pci通信(调用PCIS-DAS ...
- CodeForces250B——Restoring IPv6(字符串处理)
Restoring IPv6 DescriptionAn IPv6-address is a 128-bit number. For convenience, this number is recor ...
- sockaddr_u详解
struct sockaddr { unsigned short sa_family; /* address family, AF_xxx */ char sa_data[14]; ...
随机推荐
- 测试Activity和Fragment的生命周期
Activity的生命周期有7个函数,Fragment的生命周期有11个函数. Activity生命周期除上述6个方法还有一个Restart()方法,该方法在该Activity从不可见(仍存在)到重新 ...
- TCP协议的安全性分析
有算法就有破解法,因为它们都遵循了一定的数据结构和数学知识.所以网络安全是一个相对的概念,不可能出现绝对的安全!作为当今最流行的网络协议--TCP也是如此.那么TCP的安全问题究竟是哪些因素引起的呢? ...
- Java第十三天,内部类
内部类 一.①成员内部类.②局部内部类(包含③匿名内部类) 1.内部类用外部类属性和方法的时候,可以随意进行访问. 2.外部类用内部类属性和方法的时候,需要通过内部类对象访问. 3.在编译成class ...
- 【python实现卷积神经网络】卷积层Conv2D实现(带stride、padding)
关于卷积操作是如何进行的就不必多说了,结合代码一步一步来看卷积层是怎么实现的. 代码来源:https://github.com/eriklindernoren/ML-From-Scratch 先看一下 ...
- matplotlib BboxBase类
2020-04-07 17:24:12 --Edit by yangray BboxBase 是 TransformNode 的子类, 同时它是所有 bounding box(平行四边形限位框) 的 ...
- hadoop(五)scp命令copy文件和配置(完全分布式准备二)|7
机器的克隆参考centos7克隆ip|机器名|映射关系|别名配置(hadoop完全分布式准备一) 那么问题来了,如果我们有30台机器,之间可以互相访问,那我们如何快速安装配置环境如jdk hadoop ...
- Powershell 输出信息过多,结尾显示省略号
有时候我们通过powershell指令去查询某些信息时,因为输出结果过多,导致一部分重要信息被省略号代替,如下图 面对这种情况无论是 |fl 还是 out-file 亦或是 export-csv都无 ...
- Win安装docker
Windows Docker 安装 win7.win8 系统 win7.win8 等需要利用 docker toolbox 来安装,国内可以使用阿里云的镜像来下载,下载地址:http://mirror ...
- Linux c++ vim环境搭建系列(5)——vim使用
5. 使用 5.1 快捷键及设置 5.1.1 光标移动 w : 正向移动到相邻单词的首字符 b : 逆向移动到相邻单词的首字符 e : 正向移动到相邻单词的尾字符 ge : 逆向移动到相邻单词的尾字符 ...
- Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(一)之Introduction
Learn Java I found out that I and other speakers tended to give the typical audience too many topics ...