月亮链 月亮链
Ctrl+D收藏月亮链
首页 > 莱特币 > 正文

ALL:二十三种 DeFi 安全事故汇总:智能合约风险与防范_ACK

作者:

时间:1900/1/1 0:00:00

撰文:AustinZhang,JonLi,AsymmetriesTechnologies

智能合约的安全性问题一直是业界的一个重点话题,由于程序员的某些疏忽造成了思维和逻辑上的漏洞,从而导致黑客有了可乘之机。我们搜集了目前在DeFi领域已经发生了安全事故的智能合约,并根据我们编写的示例代码来实证分析其中的原因,希望能给到同事和同行们一些启示。

重入攻击

主要攻击方式之一:合约调用恶意外部合约结束之前,恶意外部合约函数反向调用原合约函数利用相关漏洞。

示例代码

案例1:2021年12月22日UniswapV3流动性管理协议Visor被盗120ETH

事故原因:deposit函数没有防重入锁也没有验证from地址是否是合法的Visor合约地址。攻击者传入攻击合约地址,重复调用deposit函数绕过取款金额检查多次取款。

案例2:2021年6月5日BurgerSwap被盗700万美金

事故原因:类似Uniswap的原创dex,分为Platform和Pool两个合约。Platform类似Uniswap的Router,Pair类似Uniswap的Pool,开发者错误的将K值校验放在Platform计算,攻击者在Platform中进行重入攻击,多次以旧的K值换取代币,造成流动性提供者损失。

解决方案:调用外部合约前确保所有中间状态变量已更新并使用再入锁。

未检查函数返回值

调用外部合约函数时,有些函数调用失败不会抛出错误回滚交易而是返回false,如果忘记检查函数返回值会导致误以为调用成功。

示例代码

案例:2021年4月4日ForceDao到被攻击损失183ETH

Asproex阿波罗生态通证MOON完成第二十二期回购销毁:据官方消息,1月19日,Asproex(阿波罗)生态通证MOON完成第二十二期回购销毁,销毁数量为1,913,096枚MOON,区块高度为11684826,销毁交易哈希值为

0x8f49e0652a7b94199ace361cd93d48ead1e02836983824f08aeb5b1bf9592df6。据悉,此次销毁价值总金额高达554798美金,MOON最新价格为0.2911U(实时数据),截止当前时间,Asproex(阿波罗)二十二期回购累计销毁25,855,844枚MOON。

Asproex(阿波罗)作为一家离岸银行控股持牌交易平台,涵盖CTO(Corporate Token Offering)企业通证上市、合约跟单、ETT指数通证、数字矿业、Digital Bank板块并持有5国合法牌照,致力于为中小微企业提供数字化上市一站式服务[2021/1/19 16:31:48]

事故原因:Force代币的transferFrom余额不足时返回false而不是直接回滚交易,合约中未做判断导致转账失败时也被认为成功,可以换取到对应代币。

解决方案:使用call函数调用外部合约时必须检查调用是否成功。注:call调用外部合约未匹配到函数时,会调用外部合约fallback或者receive函数,如果外部合约有定义receive函数且call函数未携带calldata则会调用外部合约receive函数,其他情况调用fallback函数。

未正确设置函数可见性

Solidity中函数默认为public,可以被外部调用,一旦未将关键函数设置为Private,就会导致安全风险。

示例代码

案例1:2022年1月22日DexCrosswise被攻击损失80万美金

Asproex(阿波罗)生态通证MOON完成第二十一期回购销毁:官方消息,1月12日,Asproex(阿波罗)生态通证MOON完成第二十一期回购销毁,销毁数量为?1,805,620?枚MOON,区块高度为?11639597??,销毁交易哈希值为

0xa0d79657c8d7f445e882443a60c0808ec6c0756a2ed73d2b0076a16ae557480c。据悉,此次销毁价值总金额高达523630美金,MOON当前价格为0.2926U(实时数据),到目前为止,Asproex(阿波罗)二十一期回购销毁计划累计销毁23,942,748枚MOON。

Asproex(阿波罗)作为一家离岸银行控股持牌交易平台,涵盖CTO(Corporate Token Offering)企业通证上市、合约跟单、ETT指数通证、数字矿业、Digital Bank板块并持有5国合法牌照,致力于为全球中小微企业提供数字化上市一站式服务。[2021/1/12 15:59:57]

事故原因:Crosswise虽然实现了权限验证函数onlyOwner,但忘记设置setTrustedForwarder为private,导致被攻击者利用,将自己设置为池子的Owner将代币全部转走。

案例2:2020年6月18日跨链桥BancorNetwork被攻击损失14万美金

事故原因:合约用于转账的函数默认为public,攻击者可以直接调用转走合约中的代币。

解决方案:提款函数事关合约资产的转移,需谨慎设置权限控制,确保初始化函数只能运行一次。

未验证Map中Key不存在的情况

Solidity中的Mapping在获取对应Key的Value时,如果Key不存在,会返回对应类型的默认值,而不是报错。例如Mapping(int→int),如果对应int的Key不存在,会返回默认值0。

BKEX Global 第二十期定期宝即将开启:据BKEX Global公告,BKEX Global将于2020年10月1日20:00(UTC+8)开启第二十期定期宝抢购,币种有:HT、TRX。周期分别为5日、11日。

BKEX定期宝是BKEX推出的数字金融衍生品之一,为加密数字资产持有用户提供稳定、安全、可靠的理财产品购买和赎回服务。除定期宝外,BKEX目前还开通了多个币种的活期宝理财业务。[2020/10/1]

示例代码

案例:2021年7月11日跨链桥ChainSwap被攻击损失400万美金

事故原因:ChainSwap依赖其网络中的validator进行转账。为了限制validator一次转走超过其质押的代币,设置了配额。结果合约中存在漏洞可以绕过配额限制,当地址变量signatory不存在时,authQuotes和lasttimeUpdateQuoteOf会返回0,导致配额计算错误返回预期外的大量配额。

解决方案:使用map时必须检查key是否存在。

在状态变更前进行转账

转账时有可能被重入,利用未变更的状态进行攻击。

案例:2021年8月17日XSURGE被攻击损失500万美金

事故原因:在转账后才修改totalSupply,转账时被重入另外一个未加重入锁的函数损失500万美金。

解决方案:使用了再入锁也要在所有状态变更之后在转账。

初始化函数未做调用和权限限制

很多合约需要初始化子合约,例如Uniswap需要通过Factory合约初始化Pool合约,这时候如果忘记对子合约的初始化函数做权限和重复初始化限制,可能被攻击者进行恶意初始化。

案例:2021年8月11日PunkProtocol被攻击损失400万美金

行情 | XLM领涨市值前二十币种:据coinmarketcap数据,目前XLM领涨市值前十币种,涨幅为9.26%,现全球均价为1.37元。此外,前二十币种中仅BTC、BCH、 XLM及ADA仍上涨。 其中ADA涨幅8.84%,仅次于XLM,而BTC和BCH涨幅不足1%。[2018/7/15]

事故原因:池子的initialize函数未做权限和重复调用限制,攻击者调用该函数将自己设置为Forge管理员权限,并调用withdrawToForge将池子所有资金都发送到攻击者地址。

解决方案:初始化函数必须设置成只能初始化一次。

未正确检查对应合约函数实现

通常智能合约被调用的函数不存在时会报错,但如果合约实现了fallback函数,则会自动调用fallback函数。有时fallback函数并不会报错,导致调用方误以为调用成功。

案例:2022年1月18日跨链桥Multichain被攻击损失450ETH

事故原因:通常ERC20的合约会实现permit函数,用于签名检查与授权操作。但WETH、PERI、OMT、WBNB、MATIC、AVAX六种代币的合约没有实现permit却实现了fallback,Multichain在检查这些代币的权限时误以为用户已经授权转账给攻击者,导致代币被盗。

解决方案:不同代币的实现方式不同,引入新代币之前应仔细检查其具体实现。

未正确处理带转账费的代币

有些代币在转账时会销毁一部分转账费用,导致实际收到的代币余额偏少,如果开发者没考虑到这一点,以转账值计算,会导致出现偏差。

案例:2021年8月19日Pinecone被盗20万美金

事故原因:Pinecone使用其代币PCT作为资金池的质押代币,PCT转账会有手续费的损耗。合约并没有考虑相关损耗导致用户份额和质押的PCT总额出现偏差,被攻击者利用领取多余的奖励。

二十国集团财长和央行行长会议开幕:就加密货币等展开讨论:新华社布宜诺斯艾利斯3月19日消息,二十国集团(G20)财政部长和中央银行行长会议19日在阿根廷首都布宜诺斯艾利斯开幕,与会代表将就基础设施投资、未来就业形势、加密货币等议题展开讨论与磋商。[2018/3/20]

解决方案:谨记不是所有的代币转账费都为nativetoken。

签名验证漏洞

签名被重复使用,或者利用椭圆曲线签名算法的对称性,根据已有签名构造合法签名。

案例:2021年7月12日AnySwap被盗800万美金

事故原因:对交易签名除了私钥外需要一个随机数R,但是Anyswap部署新合约失误,导致在BSC上的V3路由器MPC帐户下有两个交易具有相同的R值签名,攻击者反推到这个MPC账户的私钥转走了被盗资金。

解决方案:使用EIP-712标准验证签名,参考OpenZeppelin的实现:https://docs.openzeppelin.com/contracts/3.x/api/drafts。

未考虑合约余额可能产生的变化

矿工挖出块时或者智能合约调用selfdestruct函数销毁自己时可以向任意地址强行打币改变其原生代币的余额。当使用余额函数返回值作为判断条件时,余额有可能被强行改变导致风险,极端情况下甚至导致合约拒绝服务。

示例代码

即使捐赠合约不能接受代币转账,合约余额也可能在部署后被改变,严格检查已空投总量与合约余额之和等于总供应量可能导致捐赠合约拒绝服务。

解决方案:在合约中避免对合约余额做严格相等的检查。

使用delegatecall调用外部合约

delegatecall可以将对应合约的函数代码内嵌到当前上下文中执行,就像调用内置函数一般。如果不小心调用了恶意合约极易导致攻击。

示例代码

当攻击者调用forward函数并传入Attack合约地址以及函数setOwner()作为参数时,Proxy合约owner将被修改为攻击者地址。

解决方案:不推荐使用delegatecall调用外部合约。

授权tx.origin

tx.origin是交易的发起者地址,合约如果使用tx.origin做权限检查,当合约的授权用户与恶意合约交互时,恶意合约调用合约即可通过合约权限检查。

示例代码

当MyWallet合约owner使用transferTo函数向Attack合约转账时,Attack合约会重入MyWallet合约,并调用transferTo函数,此时tx.origin仍然为MyWalletowner,require条件满足,MyWallet余额将被全部转移至Attack合约。

解决方案:不使用tx.origin做权限检查。

交易排序竞争

全节点运行者可以在交易被确认之前获取交易信息,进而根据获取的交易信息,构造高手续费交易,让矿工优先打包自己的交易以执行对自己有利的策略。例如,谜语合约奖励最快找出谜底的用户,恶意用户可以在获悉诚实用户提交的谜底后,构造高手续费交易优先诚实用户提交谜底,从而获取奖励;又如当用户更新授权额度时,被授权用户可以在更新授权额度交易被确认之前转移旧的授权额度,如此,被授权人实际获得的授权额度为两次授权额度之和。

解决方案:针对谜语合约,获得谜底的用户先提交「随机数+自身地址+谜底」的哈希值,谜语合约存储该哈希值后,用户再提交随机信息与答案,合约检查哈希值匹配后再发放奖励;更新授权额度时先置零授权额度。

使用block.timestamp或者block.number作为合约时间参考

block.timestamp与block.number都不能获得精确都时间,用作智能合约的时间参考会引入潜在的风险。

解决方案:使用oracle获取时间信息。

Denial-of-Service(DoS)拒绝服务

调用外部合约可能永久失败导致本合约不能接受新的指令,例如当合约主动对另外一个合约转账,而被转账合约没有接受转账的函数时,转账失败,此时合约可能进入拒绝服务状态。

示例代码

当合约向其中一个账号转账失败会导致所有转账全部失败。

解决方案:合约调用外部合约时可能出现的失败,合约需包含处理调用失败情况的代码,防止合约进入拒绝服务状态。

使用链属性作为随机源

链属性如block.timestamp,blockhash,bock.difficulty以及其他属性可被矿工操控,存在风险。

解决方案:考虑使用RANDAO,oracle或比特币区块hash作为随机源。

继承顺序错误

多个被继承合约都定义了同一个函数时,继承合约调用该函数的优先级由继承顺序决定,错误的继承顺序将导致函数调用错误。

解决方案:继承顺序说明请参考官方实例:https://solidity-by-example.org/inheritance/。

Gas不足攻击

多签情况下或者需要其他人帮自己代付Gas时,用户准备好签名交易并交给代执行人,代执行人再将用户交易提交给执行合约,代执行人可以提前审查用户代交易,恶意的代执行人或当交易内容不利于代执行人时,可以通过限制Gas的供给,使交易的执行失败,从而阻止交易的执行。

示例代码

当Relayer调用者通过限制Gas使用导致某个交易失败,那么失败的交易将永远不能再被提交。

解决方案:选择信任的代执行人,或者在执行合约中检查代理人提供的Gas费是否足够。

函数类型变量跳转

solidity支持函数类型变量,当函数类型变量使用汇编指令赋值时,函数类型变量有可能被指向恶意构造当函数。

解决方案:如无必要,尽量避免在智能合约中使用汇编指令。

GasLimit服务拒绝攻击

区块设置有Gas使用上限,如果合约当执行超过了区块Gas使用上限,则合约永远不能被执行成功。

示例代码

当操作的循环次数过大时,执行合约所需Gas将超过区块上限,导致合约执行失败。

解决方案:在智能合约中谨慎操作大数组,或循环。

abi.encodePacked()哈希碰撞

abi.encodePacked()采用非填充序列化,当序列化参数包含多个变长数组时,攻击者可以在保持所有元素顺序不变的前提下,改变两个变长数组的元素,如此序列化的结果相同。

示例代码

通过构造addUser的输入,攻击者可以将regularUsers的成员加入admins成员,但是构造的输入和原输入的签名相同。

解决方案:使用定长数组,或者不让调用者传入abi.encodePacked()的参数,或者使用abi.encode()。

transfer()和send()函数Gas不足

transfer()和send()函数使用2300gas以防止重入攻击,公链升级后可能导致gas不足。

解决方案:推荐使用call()函数,但需做好重入攻击防护。

链上未加密隐私数据

链上数据完全透明,合约的private关键字不能阻止合约的隐私数据泄漏。

示例代码

虽然players为private,但攻击者仍然可以通过解析链上数据读取players。

解决方案:隐私数据需要加密放在链上。

以上是我们分析和总结的二十三种安全事故类型汇总,希望能够给到您些许参考和启示。

标签:ALLACKGASMOOMETAALLBI价格Cardstackbnb局gas费MoonieNFT

莱特币热门资讯
DOG:加密捐赠平台 QuestBook 完成 830 万美元 A 轮融资,Lemniscap 领投_bookchain

链捕手消息,加密捐赠平台QuestBook完成830万美元A轮融资,由Lemniscap领投,CoinbaseVentures、AlamedaResearch、Dragonfly、Hashed、.

1900/1/1 0:00:00
BANK:纽约时报特稿 | 加密大亨SBF的愿望:不穿长裤,书写规则_Mankind

作者:DavidYaffe-Bellany,纽约时报原标题:《ACryptoEmperor’sVision:NoPants,HisRules》编译:郭倩雯.

1900/1/1 0:00:00
BIN:Binance Labs完成募集五亿美元投资基金,用以推动区块链及Web3等新技术_ANC

链捕手消息,币安旗下的风险投资与创新孵化机构BinanceLabs宣布完成一笔五亿美元的投资基金,出资者均为全球领先的机构级投资者.

1900/1/1 0:00:00
COIN:你的个人经济体:社交通证利与害_NFTN

作者:MarioGabriele翻译:malatang.eth,?麻辣烫的Web3执行概要如果您只有几分钟的时间.

1900/1/1 0:00:00
比特币:美联储加息50个基点,比特币与美股齐涨_PPL

作者:茉莉,?蜂巢Tech北京时间今日凌晨,美国联邦储备委员会发布5月决议,联邦基金利率目标区间上调了50个基点,达0.75%至1%。这是美联储22年以来最大幅度的加息.

1900/1/1 0:00:00
区块链:每周要闻精选 | Terra 新链主网上线;a16z 推出 45 亿美元加密基金_ENT

整理:Hsilung,链捕手重要资讯1、Terra创始人DoKwon宣布Terra新链主网上线5月28日消息,Terra创始人DoKwon宣布,Terra新链phoenix-1主网上线.

1900/1/1 0:00:00