# The Association NFT 合约漏洞分析 **Published by:** [analyse nfts](https://paragraph.com/@analyse-nfts/) **Published on:** 2022-04-24 **URL:** https://paragraph.com/@analyse-nfts/the-association-nft ## Content 漏洞描述 NBA发行的NFT项目The Association NFT,合约出现了白名单用户的签名数据被攻击者利用,可以无限制铸造NFT的重大漏洞,现在让我们看看这个合约的漏洞是怎么产生的. 漏洞位置 NBA这个发行的NFT项目有两个合约地址,一个是NFT本身的合约The_Association_Token,另一个是售卖合约The_Association_Sales,问题的根源出现在这个售卖合约上面。 售卖合约有个mint_approved方法,通过检验用户传送过来的签名数据,然后去调用The_Association_Token合约铸造NFT。 function mint_approved( vData memory info, uint256 number_of_items_requested, uint16 _batchNumber ) external { require(batchNumber == _batchNumber, "!batch"); address from = msg.sender; // info是包含用户签名的数据,通过调用verify方法去验证签名数据是否正确 require(verify(info), "Unauthorised access secret"); _discountedClaimedPerWallet[msg.sender] += 1; require( _discountedClaimedPerWallet[msg.sender] <= 1, "Number exceeds max discounted per address" ); presold[from] = 1; // 如果上面verify方法验证通过,这里调用会NFT合约铸造NFT _mintCards(number_of_items_requested, from); emit batchWhitelistMint(_batchNumber, msg.sender); } 再看看verify方法它是如何检验签名数据的 function verify(vData memory info) public view returns (bool) { require(info.from != address(0), "INVALID_SIGNER"); bytes memory cat = abi.encode( info.from, info.start, info.end, info.eth_price, info.dust_price, info.max_mint, info.mint_free ); // mint数据的hash值 bytes32 hash = keccak256(cat); require(info.signature.length == 65, "Invalid signature length"); bytes32 sigR; bytes32 sigS; uint8 sigV; bytes memory signature = info.signature; // 通过签名获取到R,S,V assembly { sigR := mload(add(signature, 0x20)) sigS := mload(add(signature, 0x40)) sigV := byte(0, mload(add(signature, 0x60))) } bytes32 data = keccak256( abi.encodePacked("\\x19Ethereum Signed Message:\ 32", hash) ); // 通过mint数据的hash值,签名R,S,V获取到签名的所属用户地址 address recovered = ecrecover(data, sigV, sigR, sigS); // 判断地址是合约配置的 return signer == recovered; } 从上面代码可以看到,这个签名校验方法是没有对发送者msg.sender进行校验的,只对签名所属者和合约配置白名单地址进匹对检验,那么攻击者完全可以使用正常白名单的用户签名数据,绕过这个身份验证方法去铸造NFT。 链上复现 现在我们在ethscan上面看看哪些铸造NFT交易是攻击者发起的。 首先我们在ethscan上面查看售卖合约The_Association_Sales 有漏洞的铸造合约方法的id是0x8df9da46 p1 根据方法id对交易进行筛选 p2 定位到早期发起的一些交易记录。 现在我们来看这笔交易记录铸造tokenid为2489的交易记录 p3 p4 通过对交易输入的数据解析可以知道,红框圈住的输入数据,是白名单发起者的地址。 p5 现在我们再来看铸造tokenid为9657的这笔交易记录 p6 p7 这里可以看到输入数据和上面的交易一模一样,但是发起者地址和输入数据的地址不符,说明这笔交易属于攻击者利用合约漏洞,使用正常用户的签名数据生成的。 另外对铸造方法分析,铸造NFT数量的参数number_of_items_requested不属于参数数据的一部分,那么修改这个参数值,可以实现一次性铸造多个。 预防措施 验证签名方法需要加入msg.sender校验 为了更节省存储gas费用,可以采用MerkleProof算法实现白名单功能 https://github.com/MetaplasiaTeam ## Publication Information - [analyse nfts](https://paragraph.com/@analyse-nfts/): Publication homepage - [All Posts](https://paragraph.com/@analyse-nfts/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@analyse-nfts): Subscribe to updates