# Treasure DAO 攻击事件分析 **Published by:** [xyyme.eth](https://paragraph.com/@xyyme/) **Published on:** 2022-03-25 **URL:** https://paragraph.com/@xyyme/treasure-dao ## Content 前段时间,Treasure DAO 被攻击,造成市场上一部分的 NFT 可以被以 0 的价格买到。究其原因,其实是由于合约代码中一个很简单的 bug 造成的,这篇文章我们就来看看。 TreasureDAO 是一个 NFT 市场,其相关合约主要有两个(对应的地址均为当时攻击发生时的地址):TreasureMarketplaceBuyer (1)TreasureMarketplace (2)代码分析先来看看 2 合约都有些什么方法:createListing(NFT 上架)updateListing(更新 NFT 相关商品信息)cancelListing(下架)buyItem(购买商品)一些 set 函数设置一些参数再来看看主要的 buyItem 方法:可以看到,购买 ERC1155 和 ERC721 是被放在一个方法中处理的。问题在于对于 1155 来说,tokenId 下的数量是有意义的,对于 721 来说,不存在数量这个字段(不熟悉 1155 的同学可以看看我之前写的这篇文章)。这里放在一起处理,对于 1155 来说没有问题,但是对于 721 来说,如果正常传 1,那么也没有问题,但是如果传大于 1 的值,就可能会造成用户多付几倍的钱,却只买到了一个 NFT。如果传 0,那么就会造成零元购(我猜测项目方在开发时可能就内部约定,在 721 的情况下,前端默认传 1,没有考虑传 0 的情况)。 这里还有一个问题,攻击者是通过调用 1 合约的 buyItem 方法再进入到 2 合约中的,而 2 合约没有对 msg.sender 进行校验。不过,不能确定这是一个漏洞,还是项目方有意为之。由于我没有对项目整体合约架构进行阅读,因此对这里不做评价。 我们可以顺便来看看 1 合约的 buyItem 方法,同样没有对数量参数进行非零校验:我们再来看看 createListing (NFT 上架)方法:可以看到,_quantity 参数仅仅对于 ERC1155 起作用,但是在最后的商品信息赋值时,却用到了这个参数。这里如果在上架 ERC721 的时候,数量传 1,没有问题,如果数量传大于 1 的值,就会造成数据紊乱。如果用户在购买的时候也传了大于 1 的值,就可能会多花冤枉钱,这就是我前面说的情况。总结造成这次攻击的原因主要在于没有对输入参数作完整的校验,这也是我们在日常开发中经常容易忽视的一点,不能仅仅考虑项目前端调用,还要考虑到有科学家会直接调用合约的情况。 还有就是代码中将 ERC721 和 ERC1155 放在一起处理,会造成一些逻辑混乱,这样就容易出现 bug,这种情况还是要避免。参考 PeckShield Inc. @peckshield 2/ To illustrate, we use the above hack tx and show the key steps below: 1. Call buyItem() with valid NFT token and NFT ID, but w/ invalid ZERO quantity 2. Treasure Marketplace sells the NFT but charges ZERO MAGIC (due to ZERO quantity) 15 11:12 PM • Mar 2, 2022 https://www.tuoluo.cn/article/detail-10095262.htmlTreasureDAO攻击事件分析-安全KER - 安全资讯平台安全KER - 安全资讯平台https://www.anquanke.com ## Publication Information - [xyyme.eth](https://paragraph.com/@xyyme/): Publication homepage - [All Posts](https://paragraph.com/@xyyme/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@xyyme): Subscribe to updates - [Twitter](https://twitter.com/xyymeeth): Follow on Twitter