Seguridad de Smart Contracts
Patricio Palladino
patricio@nomiclabs.io
Programa
- Historia
- Qué tienen de especial los smart contracts?
- Principales tipos de vulnerabilidades
- Principios para el desarrollo seguro
- Ejercicios
Lanzamiento de
Ethereum
- Primer plataforma de Smart Contracts
- Inmutable
- Imparable
- Transparente
- Trustless
- "Code is law"
The DAO
- Entidades autoreguladas
- Nuevos paradigmas de organización
- Fondo de inversiones descentralizado
- ICO: 14% del ETH
The DAO Hack

Otros hacks importantes
- 19/07/2017 - Parity MultiSig Wallet - 30M USD
- 03/11/2017 - Parity MultiSig Wallet - 150M USD
- 28/01/2018 - POWH Coin - 2.3M USD
- 27/07/2018 - Kick ICO - 7.7M USD
- Muchos más
¿Por qué?
I want you to write a program that has to run in a concurrent environment under Byzantine circumstances where any adversary can invoke your program with any arguments of their choosing. The environment in which your program executes (and hence any direct or indirect environmental dependencies) is also under adversary control. If you make a single exploitable mistake or oversight in the implementation, or even in the logical design of the program, then either you personally or perhaps the users of your program could lose a substantial amount of money. Where your program will run, there is no legal recourse if things go wrong. Oh, and once you release the first version of your program, you can never change it. It has be right first time.
¿Qué hacemos?
- Procesos de desarrollo enfocados en la seguridad
- Auditorías de seguridad
- Bug Bounties
Decentralized Application
Security Project
Reentrancy
mapping(address => uint256) balances;
function sendEtherTo(address to, uint256 amount) {
require(balances[msg.sender] >= amount);
to.call.value(amount)();
balances[msg.sender] -= amount;
}
contract Attacker {
function attack() {
target.sendEtherTo(this, 1 ether);
}
function() payable {
attack();
}
}Access Control
function createFunds(address beneficiary, uint256 value) public {
balances[beneficiary] += value;
}function createFunds(address beneficiary, uint256 value) public onlyOwner{
balances[beneficiary] += value;
}
address owner;
modifier onlyOwner() {
require(msg.sender == owner);
_;
}Arithmetic errors
function sendEtherTo(address to, uint256 amount) {
require(balances[msg.sender] - amount > 0);
balances[msg.sender] -= amount;
to.transfer(amount);
}Checkeos de calls
faltantes
function withdraw(uint256 _amount) public {
require(balances[msg.sender] >= _amount);
balances[msg.sender] -= _amount;
etherLeft -= _amount;
msg.sender.send(_amount);
}Denial of service
function becomePresident() payable {
require(msg.value >= price); // must pay the price to become president
president.transfer(price); // we pay the previous president
president = msg.sender; // we crown the new president
price = price * 2; // we double the price to become president
}On-chain/Bad randomness
function guess(uint8 n) public payable {
require(msg.value == 1 ether);
uint8 answer = uint8(keccak256(block.blockhash(block.number - 1), now));
if (n == answer) {
msg.sender.transfer(2 ether);
}
}function attack() public payable {
uint8 answer = uint8(keccak256(block.blockhash(block.number - 1), now));
victim.guess.value(1 ether)(answer);
}Front-running

Front-running

Time manipulation
function play() public {
require(now > 1521763200 && neverPlayed == true);
neverPlayed = false;
msg.sender.transfer(1500 ether);
}Short address
attack
- Muy debatido
- Problema off-chain?
- Responsabilidad de quien?
Unknown unknowns
Principios para el
desarrollo seguro
-
Seguridad primero
-
Código modular
-
Claridad y buenos nombres
-
Reutilización de código
-
Tests automatizados
-
Runtime assertions
-
Code reviews y auditorias
Seguridad primero
No es un feature que se puede agregar despues.
Tiene que tenerse en cuenta desde el diseño del sistema
Código modular
Modularización compartimentaliza
responsabilidades y fracciona la superficie de ataque
Claridad y buenos
nombres
El código simple facilita su desarrollo, comprensión y análisis
Reutilización de código
Reutilizar código auditado y battle-tested
disminuye la posibilidad de errores
Tests automatizados
100% de code coverage signífica
que apenas estas tocando cada statement/condición/etc
Runtime assertions
Fallar lo antes posible, de forma explicita
Code reviews y auditorias
- Reviews internos
- Auditorías externas
- Bug bounties
Más material
- http://bit.ly/slides-sec-sc
- http://bit.ly/consensys-best-practices
- Post-mortems de hacks
- Reportes de auditorías
Ejercicios
Seguridad en Smart Contracts
By Patricio Palladino
Seguridad en Smart Contracts
- 474