Refactor Ether Send Module (#696)

* Refactor ether_send -> ether_thief and update tests

* Commit file change missed previously

* Remove unused import and fix formatting

* Fix expected output in Truffle test
pull/699/head
Bernhard Mueller 6 years ago committed by JoranHonig
parent 86e1544090
commit 2fdc2878e8
  1. 43
      mythril/analysis/modules/ether_thief.py
  2. 2
      tests/cmd_line_test.py
  3. 6
      tests/testdata/outputs_expected/ether_send.sol.o.graph.html
  4. 2
      tests/testdata/outputs_expected/ether_send.sol.o.json
  5. 4
      tests/testdata/outputs_expected/ether_send.sol.o.markdown
  6. 4
      tests/testdata/outputs_expected/ether_send.sol.o.text
  7. 6
      tests/testdata/outputs_expected/multi_contracts.sol.o.graph.html
  8. 2
      tests/testdata/outputs_expected/multi_contracts.sol.o.json
  9. 4
      tests/testdata/outputs_expected/multi_contracts.sol.o.markdown
  10. 4
      tests/testdata/outputs_expected/multi_contracts.sol.o.text

@ -10,15 +10,21 @@ import logging
""" """
MODULE DESCRIPTION: MODULE DESCRIPTION:
Check for CALLs that send >0 Ether to either the transaction sender, or to an address provided as a function argument. Search for cases where Ether can be withdrawn to a user-specified address.
If msg.sender is checked against a value in storage, check whether that storage index is tainted (i.e. there's an unconstrained write
to that index). An issue is reported ONLY IF:
- The transaction sender does not match contract creator;
- The sender has not previously sent any ETH to the contract account.
This is somewhat coarse and needs to be refined in the future.
""" """
def execute(state_space): def execute(state_space):
logging.debug("Executing module: ETHER_SEND") logging.debug("Executing module: ETHER_THIEF")
issues = [] issues = []
@ -46,31 +52,42 @@ def _analyze_state(state, node):
return [] return []
try: try:
"""
FIXME: Instead of solving for call_value > 0, check whether call value can be greater than
the total value of all transactions received by the caller
"""
model = solver.get_model( model = solver.get_model(
node.constraints + not_creator_constraints + [call_value > 0] node.constraints + not_creator_constraints + [call_value > 0]
) )
debug = "Transaction Sequence: " + str( transaction_sequence = solver.get_transaction_sequence(
solver.get_transaction_sequence( state, node.constraints + not_creator_constraints + [call_value > 0]
state, node.constraints + not_creator_constraints + [call_value > 0]
)
) )
# For now we only report an issue if zero ETH has been sent to the contract account.
for key, value in transaction_sequence.items():
if int(value["call_value"], 16) > 0:
return []
debug = "Transaction Sequence: " + str(transaction_sequence)
issue = Issue( issue = Issue(
contract=node.contract_name, contract=node.contract_name,
function_name=node.function_name, function_name=node.function_name,
address=instruction["address"], address=instruction["address"],
swc_id=UNPROTECTED_ETHER_WITHDRAWAL, swc_id=UNPROTECTED_ETHER_WITHDRAWAL,
title="Ether send", title="Ether thief",
_type="Warning", _type="Warning",
bytecode=state.environment.code.bytecode, bytecode=state.environment.code.bytecode,
description="It seems that an attacker is able to execute an call instruction," description="Users other than the contract creator can withdraw ETH from the contract account"
" this can mean that the attacker is able to extract funds " + " without previously having sent any ETH to it. This is likely to be vulnerability.",
"out of the contract.".format(target),
debug=debug, debug=debug,
) )
issues.append(issue) issues.append(issue)
except UnsatError: except UnsatError:
logging.debug("[UNCHECKED_SUICIDE] no model found") logging.debug("[ETHER_THIEF] no model found")
return issues return issues

@ -29,7 +29,7 @@ class TruffleTestCase(BaseTestCase):
command = "cd {}; truffle compile; python3 {} --truffle --max-transaction-count 1".format( command = "cd {}; truffle compile; python3 {} --truffle --max-transaction-count 1".format(
truffle_project_root, MYTH truffle_project_root, MYTH
) )
self.assertIn("=== Ether send ====", output_of(command)) self.assertIn("=== Ether thief ====", output_of(command))
class InfuraTestCase(BaseTestCase): class InfuraTestCase(BaseTestCase):

File diff suppressed because one or more lines are too long

@ -1 +1 @@
{"error":null,"issues":[{"address":722,"contract":"Unknown","debug":"<DEBUG-DATA>","description":"It seems that an attacker is able to execute an call instruction, this can mean that the attacker is able to extract funds out of the contract.","function":"withdrawfunds()","swc-id":"105","title":"Ether send","type":"Warning"},{"address":883,"contract":"Unknown","debug":"<DEBUG-DATA>","description":"This binary add operation can result in integer overflow.\n","function":"invest()","swc-id":"101","title":"Integer Overflow","type":"Warning"}],"success":true} {"error": null, "issues": [{"address": 722, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "Users other than the contract creator can withdraw ETH from the contract account without previously having sent any ETH to it. This is likely to be vulnerability.", "function": "withdrawfunds()", "swc-id": "105", "title": "Ether thief", "type": "Warning"}, {"address": 883, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "This binary add operation can result in integer overflow.\n", "function": "invest()", "swc-id": "101", "title": "Integer Overflow", "type": "Warning"}], "success": true}

@ -1,6 +1,6 @@
# Analysis results for test-filename.sol # Analysis results for test-filename.sol
## Ether send ## Ether thief
- SWC ID: 105 - SWC ID: 105
- Type: Warning - Type: Warning
- Contract: Unknown - Contract: Unknown
@ -9,7 +9,7 @@
### Description ### Description
It seems that an attacker is able to execute an call instruction, this can mean that the attacker is able to extract funds out of the contract. Users other than the contract creator can withdraw ETH from the contract account without previously having sent any ETH to it. This is likely to be vulnerability.
## Integer Overflow ## Integer Overflow
- SWC ID: 101 - SWC ID: 101

@ -1,10 +1,10 @@
==== Ether send ==== ==== Ether thief ====
SWC ID: 105 SWC ID: 105
Type: Warning Type: Warning
Contract: Unknown Contract: Unknown
Function name: withdrawfunds() Function name: withdrawfunds()
PC address: 722 PC address: 722
It seems that an attacker is able to execute an call instruction, this can mean that the attacker is able to extract funds out of the contract. Users other than the contract creator can withdraw ETH from the contract account without previously having sent any ETH to it. This is likely to be vulnerability.
-------------------- --------------------
==== Integer Overflow ==== ==== Integer Overflow ====

File diff suppressed because one or more lines are too long

@ -1 +1 @@
{"error": null, "issues": [{"address": 142, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "It seems that an attacker is able to execute an call instruction, this can mean that the attacker is able to extract funds out of the contract.", "function": "_function_0x8a4068dd", "swc-id": "105", "title": "Ether send", "type": "Warning"}], "success": true} {"error": null, "issues": [{"address": 142, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "Users other than the contract creator can withdraw ETH from the contract account without previously having sent any ETH to it. This is likely to be vulnerability.", "function": "_function_0x8a4068dd", "swc-id": "105", "title": "Ether thief", "type": "Warning"}], "success": true}

@ -1,6 +1,6 @@
# Analysis results for test-filename.sol # Analysis results for test-filename.sol
## Ether send ## Ether thief
- SWC ID: 105 - SWC ID: 105
- Type: Warning - Type: Warning
- Contract: Unknown - Contract: Unknown
@ -9,4 +9,4 @@
### Description ### Description
It seems that an attacker is able to execute an call instruction, this can mean that the attacker is able to extract funds out of the contract. Users other than the contract creator can withdraw ETH from the contract account without previously having sent any ETH to it. This is likely to be vulnerability.

@ -1,9 +1,9 @@
==== Ether send ==== ==== Ether thief ====
SWC ID: 105 SWC ID: 105
Type: Warning Type: Warning
Contract: Unknown Contract: Unknown
Function name: _function_0x8a4068dd Function name: _function_0x8a4068dd
PC address: 142 PC address: 142
It seems that an attacker is able to execute an call instruction, this can mean that the attacker is able to extract funds out of the contract. Users other than the contract creator can withdraw ETH from the contract account without previously having sent any ETH to it. This is likely to be vulnerability.
-------------------- --------------------

Loading…
Cancel
Save