Level 1 - Donation
GoldenRush is a set of challenges based on the Ethereum Blockchain technology where you will have to exploit vulnerable Smart Contracts. Your goal is to steal the money that I sent on it ! https://goldenrush.santhacklaus.xyz
Chaque challenge “Golden rush” est un smart contract à déployer sur la blockchain de test “Ropsten network”.
Mise en place de l’environnement
Pour faire les challenges de blockchain ou même ceux sur rootme, il faut ajouter l’extension “MetaMask” dans son navigateur:
Lorsque l’extension est correctement installée, il faut créer un compte en suivant les étapes de “Create a wallet”;
Quand le wallet est créé, il faut passer sur la blockchain “Ropsten Test Network”, une blockchain de test, où les ETH n’ont aucunes valeurs.
Pour résoudre les différents challenges, il faudra au minimum 1 ETH dans le wallet. Pour récupérer des ETH:
L’extension va apparaitre et il faudra accepter la transaction. Maintenant qu’il y a au moins 1 ETH dans le wallet, il est temps de valider le challenge.
Etat des lieux
On commence donc sur la première étape, l’objectif est plutot simple: Voler l’argent du smartcontract.
Pour cela, le code Solidity du contrat est donné:
|
|
En lançant l’instance, il y deux informations importantes:
- L’adresse du contrat ;
- L’Application Binary Interface (ABI) du contrat, cette ABI sert à décrire le contrat.
La fonction du contrat getDonationsFromOwner(address _contractOwner)
attend donc une adresse en entrée, va vérifier qu’il s’agit bien de son adresse, et transférer les fonds.
Transférer les ETH
Pour dialoguer avec les smartcontract, il existe le site:
Qui s’interface vraiment bien avec l’extension MetaMask. Pour commencer à intéragir avec le smart contract du challenge, il faut lui donner l’adresse et son ABI:
C’est à ce moment là que myetherwallet sera en mesure de fournir une interface à l’utilisateur pour dialoguer avec le contrat.
Pour valider l’épreuve, il suffit de fournir à la fonction getDonationsFromOwner()
l’adresse du contrat:
0x87f028059df3638b7184045682978Ed477637D72
Et cliquer sur “Write” pour écrire sur la blockchain. A ce moment, une popup MetaMask va apparaitre pour valider la transaction:
Lorsque la transaction est validée et terminée (il est possible de suivre la progression via l’add on MetaMask), il est temps de récupérer le flag:
Flag
SANTA{!!S0Lidi7y_BaSiCs!!}
Level 2 - Piggybank
Event | Auteur | Challenge | Category | Points | Solves |
---|---|---|---|---|---|
Santhacklaus | ch3n4p4n | Golden rush 2 | Blockchain | 200 | 29 |
Steal the money stored in the contract.
Etat des lieux
Comme pour le premier, on a accès au code Solidity du SmartContract:
|
|
La fonction withdrawPiggyBank()
est donc la fonction qui va transférer les fonds. Cependant, il faut que la variable isOwner
soit à “True”. Pour passer cette variable à “True” il faut exécuter la fonction unlockPiggyBank(uint256 pin)
avec un pin correspondant au hash keccak256 de “PinHash”.
Méthode 1: Bruteforce all the things (Python mode)
Il faut savoir que keccak256 est un SHA3 256, sauf que le SHA3 de hashlib n’est pas du tout le même algo. Pour avoir la bonne fonction de hashage, il faut utiliser la lib python pysha3
.
|
|
Méthode 2: Bruteforce all the things (JS mode)
Au lieu d’éviter de se casser la tête en python pour savoir SHA3 de hashlib est le même que celui utilisé dans les smart contracts, on va prendre les librairies natives utilisé par Solidity.
Pour cela, on va télécharger web3-utils
en faisant nmp i web3-utils
contenant la fonction qui nous intéresse ici qui est soliditySha3
.
|
|
Flag
213
Le pin secret est donc 213
, il ne reste plus qu’à vérifier l’état de la variable et transférer les fonds.
SANTA{N0_M0R3_B4D_R4ND0MN3SS_PL3AZ}
Level 3 - Gringotts
Event | Auteur | Challenge | Category | Points | Solves |
---|---|---|---|---|---|
Santhacklaus | ch3n4p4n | Golden rush 3 | Blockchain | 300 | 18 |
Steal the money stored in the contract.
Etat des lieux
Voici le code du Smart Contract:
|
|
On remarque que la vulnérabilité va sûrement se retrouver dans la fonction withdrawAllowance()
. En effet, les fonctions donateToSorcery
et queryCreditOfSorcery
ne font rien de très foufou. En regardant le constructeur, on remarque l’allowance par an est de msg.value/10
.
L’objectif ici va tout simplement être de s’octroyer le maximum d’allowance que le contrat a. C’est à dire availableAllowance = msg.value;
décrit dans le constructeur, en évitant bien sûr d’attendre 10 ans avant de tout récupérer.
Pour cela, on va effectuer une attaque de type Reentrancy. Ci-dessous un peu de documentation pour savoir comment ça marche:
- https://hackernoon.com/smart-contract-security-part-1-reentrancy-attacks-ddb3b2429302
- https://medium.com/@gus_tavo_guim/reentrancy-attack-on-smart-contracts-how-to-identify-the-exploitable-and-an-example-of-an-attack-4470a2d8dfe4
Exploitation de la Reentrancy
Cette attaque de type reentrancy consiste donc à exécuter la commande msg.sender.call.value(allowancePerYear)()
en boucle jusqu’à mettre à 0 la variable availableAllowance
. La commande étant un appel externe, la variable alreadyWithdrawn
n’aura pas le temps de se mettre à true
, nous permettant ainsi de vider le contrat.
Pour réaliser cette attaque, on va utiliser le contrat suivant:
|
|
Ce contrat va nous permettre d’appeler une première fois la fonction vulnérable. Lorsque nous arrivons à l’instruction msg.sender.call.value(allowancePerYear)()
, la fonction de fallback (fonction sans nom dans notre contrat Exploiter) va entrer en jeu.
En effet, l’instruction msg.sender.call.value(allowancePerYear)()
va envoyer de l’ether du contrat vulnérable à notre contrat malicieux. Il faut savoir que la fonction de fallback est exécutée à chaque fois que le contrat reçoit de l’ether. Donc à chaque fois que msg.sender.call.value(allowancePerYear)()
sera exécuté, la fonction de fallback sera exécuté, créant une boucle infini jusqu’au vidage du contrat.
Une fois la fonction Exploit() exécutée, il nous suffit just de récupérer le flag via l’interface.
Le flag
Well done ! SANTA{R3eN7r4ncY_f0r_Th3_WiN}