目录
🦊原文:Can I Own Your NFTs? Understanding the New Attack Surface to NFTs
🦊写在前面:本文只会记录个人认为极有价值的部分。
Attack Demonstration
为了验证我们对 NFT 可能的新攻击面的分析,并确认这些攻击的可行性,同时确保不侵犯他人的数字资产。因此在本节中,我们将对自己的 NFT 进行攻击实验。
首先,我们在以太坊 Ropsten 测试网络上设置了两个地址。分别为:
- account1,地址 0x34eCf5A8C7673e6516a2cAc75599B6D58dAeb752
- account2,地址 0x784B13567287233CF796BEED63a4CB14fCFe935c
上述地址本质上就是钱包地址,用于识别和验证用户及其交易。
我们使用了一幅我们自己拍摄的照片作为数字资产,如下图所示:
我们将照片上传到了 Google Cloud:
- 指向数字资产的链接:https://bit.ly/3f8s2K1
我们还使用了 Pinata 作为 IPFS 来存储元数据。目前,Pinata 免费提供此类服务。
数字资产存储在云服务器上,元数据存储在分布式存储服务器 IPFS 上。
1 实验准备
我们创建了两个元数据文件,其中包含 image_url、name 和 description 在内的 NFT 属性。元数据文件被上传到 IPFS 中,Pinata 为每个元数据文件生成了一个链接,分别为:
- 指向 metadata1 的链接:https://bit.ly/3xCC24D
- 指向 metadata2 的链接:https://bit.ly/3eXf2qn
两个元数据文件都链接到了 Walden Pond 这张图片上。
点击链接即可查看相应的元数据文件。
如上图所示,它们的 image_url 是一样的,因此链接到的是同一个数字资产。话说,为什么第一个元数据文件比第二个长那么多?
2 攻击演示
本文没有对资产移除和元数据移除进行攻击演示,可能链接的失效由不得人吧😇
2.1 所有权复制攻击
元数据相同
我们使用了如下所示的智能合约,并将其部署在以太坊测试网络上:
// Contract based on https://docs.openzeppelin.com/contracts/3.x/erc721
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.3;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyNewNFT is ERC721, Ownable {
using Counters for Counters.Counter;
constructor() public ERC721("MyNFT", "NFT") {}
function mintMyNFT(
address recipient,
string memory tokenURI
)
public
onlyOwner
returns (uint256)
{
tokenIds.increment();
_tokenId = _tokenIds.current();
_mint(recipient, newTokenId);
setTokenURI(newTokenId, tokenURI);
}
}
对于 account1 和 account2,合约地址分别为:
- 0x11a6685d81F44C8cc894be0aD943446386893De2
- 0xB46a6fc74ACB7570d44979C2AEEDeD9237e1a6Fc
在我们创建并签署交易后,NFT 成功被铸造并得到确认。
说明:合约实例是合约代码的具体运行实体,account1 和 account2 分别部署相同的智能合约代码,得到两个不同的智能合约实例。上述合约地址指的是智能合约实例的地址。
对于 account1 和 account2,NFT 的交易哈希分别为:
- 0xbb4a9872d2c12db99a8fc73a99316796e0e36eada436a4a21f773815852088fb
- 0x0c5749e5d561016ca061a3bf031cbe6f6b763ef51c3cd4d5698d0c667ecb069b
这些交易可以在以太坊测试网上查询。我们的实验证实了不同的账户/地址可以铸造具有相同元数据的 NFT,即两个账户拥有相同的元数据所有权。
实验证明,不同的账户使用不同的智能合约实例,能够铸造出具有相同元数据的 NFT 。
2.2 代币复制攻击
元数据不同,但数字资产相同
为了实施代币复制攻击,我们使用了:
- account1,地址 0x34eCf5A8C7673e6516a2cAc75599B6D58dAeb752
- 智能合约,地址 0x11a6685d81F44C-8cc894be0aD943446386893De2
原文中 account1 和它的智能合约实例的地址居然是一样的,我怎么感觉是打错了😇
我们上传了一个略有不同的元数据文件,但其中的 image_url、name 和 description 保持不变。然后,我们使用稍加修改的元数据铸造了另一个 NFT 。交易成功,其交易哈希为:
- 0x23f9642d2c1eb58b61b7500d2cf08941b266f56be2fd23b920472cef927aa484
由于 image_url、name 和 description 保持不变,因此修改前后的元数据指向的是同一数字资产,即同一张瓦尔登池塘的照片。然而,我们作为 NFT 的创作者可以在区块链上铸造多个看起来完全不同的 NFT 。如果 NFT 创作者将这两个 NFT 出售给两个不同的买家,那么买家很难声称自己拥有一个数字资产的所有权。
个人理解:2.1 节是 account1 和 account2 分别把 metadata1 铸造了两遍,2.2 节是 account1 把 metadata1 和 metadata2 分别铸造了一遍。其中,metadata1 和 metadata2 的内容长得很不一样,但是 image_url 都指向的是同一张瓦尔登池塘的照片。
2.3 资产复制攻击
元数据不同,数字资产也不同
我们在原始照片的顶部添加了一个非常小的灰色块,人眼几乎看不见,并将其命名为:
- modifiedWaldenPond
然后我们将修改后的数字资产和形成的元数据上传到 Pinata 。
IPFS 只能检验出两个资产是否一模一样,而无法检验出一个资产是否是另一个的山寨品。
我们在以太坊 Ropsten 测试网上成功将其铸造为另一个 NFT,交易哈希为:
- 0x532f19cb29d22dbcfb1d6f1afd5cc25f977a7508a686c1a80477e9a7d6bc94f3
实验证明,目前的 NFT 系统缺乏对山寨品的检查机制。
3 讨论
我们的初步探索清楚地表明,链下 NFT 并不像链上 NFT 那样享有同等级别的保护,因为通常只有交易存储在区块链上,而其他关键数据(数字资产、元数据和不同实体之间的链接)并不存储在区块链上。
这种解耦虽然显著减少了区块链的存储开销,但也为整个基于 NFT 的虚拟经济和元宇宙带来了新的漏洞。接下来,我们将简要讨论未来需要的一些改进。
3.1 保护所有相关数据
相关数据不仅包括数字资产本身,还包括所有的元数据。由于这些数据都是公开的,因此加密是不切实际的。对于数字资产,需要一些数字版权保护机制,比如数字水印,以防止它们被轻易地复制或窃取。然而,数字水印可能不适用于文档或小型数字资产。在这种情况下,其他方案,如数字签名,或这些方案的组合可能更为合适。同样,所有相关的元数据也应该得到保护,如通过消息认证码。
消息认证码,message authentication code,MAC
3.2 保护链接
实体指针(链接)即 link 或 url,用于关联相应的数字资产、元数据和智能合约。这些链接很容易受到攻击。与数字资产和元数据文件类似,实体指针应该以一种方式受到保护,即一旦 NFT 被铸造,指针就不能再被操纵。一种直观的方法是,在部署合约的时候纳入它们或其相关信息,并将它们存储在区块链上,形成链式依赖。
即在区块链上存储指向数字资产的链接,指向元数据的链接本来就会被存储在区块链上。不过这样只能防止链接被替换,很难防止链接失效吧?
3.3 复制品检查
在铸造任何新的 NFT 之前,有必要进行彻底的检查,以确保数字资产、元数据、链接等的唯一性。直观地说,这需要一个全球数据库,能够提供搜索和查询功能。
为此,需要一个「基于云的集中式服务器」或「基于 P2P 的分布式存储」,例如基于分布式哈希表的存储。检查也应该在线进行,要求延迟最小。实际上,构建这样的集中式服务器是具有挑战性的,P2P 方法可能更有前景。
例如,如果一个宣传的 NFT 能在一定时间窗口内被许多其他验证者证实,那么该 NFT 就可能被认为是真实的,用户也更可能购买带有这种验证戳的 NFT 。验证者负责进行奖励或惩罚,并记录在交易中。
另一个挑战是要有一种机制,以防止攻击者铸造非常相似的数字资产,例如照片只有一像素被改变。通过机器学习辅助的图像搜索/匹配技术,可能会从这一角度提供一些启示。
由于上述方法可能需要更多的研究和时间,因此我们建议一个快速的解决方案,即将有关数字资产和链接的所有关键信息包含在区块链上。例如,在铸造过程中,不仅仅包含元数据的链接信息,还要包含在交易中所有涉及组件的链式哈希或哈希拼接,包括数字资产、元数据以及它们对应的 URL,并将其存储在区块链上。