diff options
Diffstat (limited to 'docs/security-considerations.rst')
-rw-r--r-- | docs/security-considerations.rst | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index f1a5dc03..bae6e20b 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -138,6 +138,45 @@ Note that ``.send()`` does **not** throw an exception if the call stack is depleted but rather returns ``false`` in that case. The low-level functions ``.call()``, ``.callcode()`` and ``.delegatecall()`` behave in the same way. +tx.origin +========= + +Never use tx.origin for authorization. Let's say you have a wallet contract like this: + +:: + + contract TxUserWallet { + address owner; + + function TxUserWallet() { + owner = msg.sender; + } + + function transfer(address dest, uint amount) { + if (tx.origin != owner) { throw; } + if (!dest.call.value(amount)()) throw; + } + } + +Now someone tricks you into sending ether to the address of this attack wallet: + +:: + + contract TxAttackWallet { + address owner; + + function TxAttackWallet() { + owner = msg.sender; + } + + function() { + TxUserWallet(msg.sender).transfer(owner, msg.sender.balance); + } + } + +If your wallet had checked msg.sender for authorization, it would get the address of the attack wallet, instead of the owner address. But by checking tx.origin, it gets the original address that kicked off the transaction, which is still the owner address. The attack wallet instantly drains all your funds. + + Minor Details ============= @@ -146,7 +185,11 @@ Minor Details Furthermore, it is not enforced by the EVM, so a contract function that "claims" to be constant might still cause changes to the state. - Types that do not occupy the full 32 bytes might contain "dirty higher order bits". - This is especially important if you access ``msg.data`` - it poses a malleability risk. + This is especially important if you access ``msg.data`` - it poses a malleability risk: + You can craft transactions that call a function ``f(uint8 x)`` with a raw byte argument + of ``0xff000001`` and with ``0x00000001``. Both are fed to the contract and both will + look like the number ``1`` as far as ``x`` is concerned, but ``msg.data`` will + be different, so if you use ``sha3(msg.data)`` for anything, you will get different results. *************** Recommendations |