From 3b0489f0d0c816e02167f25721eb78a96cca9ffb Mon Sep 17 00:00:00 2001 From: tenthirtyone Date: Wed, 7 Mar 2018 22:57:09 -0500 Subject: [PATCH] Read me --- README.md | 17 +++++++++ contracts/HoneyPot1/Log.sol | 35 ++++++++++++++++++ contracts/HoneyPot1/Migrations.sol | 23 ++++++++++++ contracts/HoneyPot1/TrustFund.sol | 56 +++++++++++++++++++++++++++++ contracts/HoneyPot2/FakeBank.sol | 31 ++++++++++++++++ test/DoSGas/DoSGas.js | 2 -- test/HoneyPot1/log.js | 28 +++++++++++++++ test/HoneyPot1/pot.js | 58 ++++++++++++++++++++++++++++++ test/HoneyPot2/FakeBank.js | 41 +++++++++++++++++++++ 9 files changed, 289 insertions(+), 2 deletions(-) create mode 100644 README.md create mode 100644 contracts/HoneyPot1/Log.sol create mode 100644 contracts/HoneyPot1/Migrations.sol create mode 100644 contracts/HoneyPot1/TrustFund.sol create mode 100644 contracts/HoneyPot2/FakeBank.sol create mode 100644 test/HoneyPot1/log.js create mode 100644 test/HoneyPot1/pot.js create mode 100644 test/HoneyPot2/FakeBank.js diff --git a/README.md b/README.md new file mode 100644 index 0000000..338bd73 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +## Solidity Security Exploits + +* Re-Entrancy +* Denial of Service - Gas +* Denial of Service - Revert +* Force Ether - selfdestruct +* Storage Allocation Exploit +* Underflow / Overflow +* Re-Entrancy Honey Pot +* Function Call Honey Pot + +To run all tests to see the attacks at work run: + +``` +$ npm install +$ bash scripts/test.sh +``` diff --git a/contracts/HoneyPot1/Log.sol b/contracts/HoneyPot1/Log.sol new file mode 100644 index 0000000..0f2b6f9 --- /dev/null +++ b/contracts/HoneyPot1/Log.sol @@ -0,0 +1,35 @@ +pragma solidity 0.4.19; + +contract Log { + address private owner; + address private ethAddress; + + struct Message { + address sender; + uint256 amount; + string note; + } + + Message[] History; + Message public LastLine; + + function Log() { + owner = msg.sender; + ethAddress = msg.sender; + } + + function changeEthAddress(address _addr) { + require(msg.sender == owner); + ethAddress = _addr; + } + + function LogTransfer(address _sender, uint256 _amount, string _note) { + if (keccak256(_note) == keccak256("withdraw")) { + require(_sender == ethAddress); + } + LastLine.sender = _sender; + LastLine.amount = _amount; + LastLine.note = _note; + History.push(LastLine); + } +} \ No newline at end of file diff --git a/contracts/HoneyPot1/Migrations.sol b/contracts/HoneyPot1/Migrations.sol new file mode 100644 index 0000000..f170cb4 --- /dev/null +++ b/contracts/HoneyPot1/Migrations.sol @@ -0,0 +1,23 @@ +pragma solidity ^0.4.17; + +contract Migrations { + address public owner; + uint public last_completed_migration; + + modifier restricted() { + if (msg.sender == owner) _; + } + + function Migrations() public { + owner = msg.sender; + } + + function setCompleted(uint completed) public restricted { + last_completed_migration = completed; + } + + function upgrade(address new_address) public restricted { + Migrations upgraded = Migrations(new_address); + upgraded.setCompleted(last_completed_migration); + } +} diff --git a/contracts/HoneyPot1/TrustFund.sol b/contracts/HoneyPot1/TrustFund.sol new file mode 100644 index 0000000..be236cd --- /dev/null +++ b/contracts/HoneyPot1/TrustFund.sol @@ -0,0 +1,56 @@ +pragma solidity 0.4.19; + +contract TrustFund { + address owner; + uint256 public minDeposit; + mapping (address => uint256) balances; + Logger public TrustLog; + + function TrustFund(uint256 _minDeposit, address _logger) public payable { + owner = msg.sender; + minDeposit = _minDeposit; + TrustLog = Logger(_logger); + } + + function deposit() public payable returns (bool) { + if (msg.value > minDeposit) { + balances[msg.sender]+=msg.value; + TrustLog.LogTransfer(msg.sender,msg.value,"deposit"); + } else { + TrustLog.LogTransfer(msg.sender,msg.value,"depositFailed"); + } + } + + function withdraw(uint256 _amount) public { + if(_amount <= balances[msg.sender]) { + if(msg.sender.call.value(_amount)()) { + balances[msg.sender] -= _amount; + TrustLog.LogTransfer(msg.sender, _amount, "withdraw"); + } else { + TrustLog.LogTransfer(msg.sender, _amount, "withdrawFailed"); + } + } + } + + function checkBalance(address _addr) public view returns (uint256) { + return balances[_addr]; + } +} + +contract Logger { + struct Message { + address sender; + uint256 amount; + string note; + } + + Message[] History; + Message public LastLine; + + function LogTransfer(address _sender, uint256 _amount, string _note) { + LastLine.sender = _sender; + LastLine.amount = _amount; + LastLine.note = _note; + History.push(LastLine); + } +} \ No newline at end of file diff --git a/contracts/HoneyPot2/FakeBank.sol b/contracts/HoneyPot2/FakeBank.sol new file mode 100644 index 0000000..154121e --- /dev/null +++ b/contracts/HoneyPot2/FakeBank.sol @@ -0,0 +1,31 @@ +pragma solidity ^0.4.19; + +contract FakeBank { + address owner; + mapping (address => uint256) balances; + + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + function FakeBank() { + owner = msg.sender; + } + + function () payable { + balances[msg.sender] += msg.value; + } + + function withdraw(address _addr) { + msg.sender.call.value(balances[_addr]); + } + + function balanceOf(address _addr) constant returns (uint256) { + return balances[_addr]; + } + + function selfDestruct() onlyOwner { + selfdestruct(owner); + } +} \ No newline at end of file diff --git a/test/DoSGas/DoSGas.js b/test/DoSGas/DoSGas.js index 3929652..d59fd89 100644 --- a/test/DoSGas/DoSGas.js +++ b/test/DoSGas/DoSGas.js @@ -23,8 +23,6 @@ contract('DoS Gas Test', accounts => { beforeEach(async () => { victim = await DoSGasVictim.new() attacker = await DoSGas.new() - - attacker.sendTransaction({ value: oneEther }); }) describe('Victim', () => { diff --git a/test/HoneyPot1/log.js b/test/HoneyPot1/log.js new file mode 100644 index 0000000..915cb0a --- /dev/null +++ b/test/HoneyPot1/log.js @@ -0,0 +1,28 @@ +const BigNumber = web3.BigNumber +const Log = artifacts.require('Log') + + +require('chai') + .use(require('chai-as-promised')) + .use(require('chai-bignumber')(BigNumber)) + .should() + +const expect = require('chai').expect + +contract('Log Test', accounts => { + const [creator, user, anotherUser, operator, mallory] = accounts + let logger = null + + beforeEach(async () => { + + logger = await Log.new(); + }) + + describe('Logger', () => { + it('Stuff', async () => { + // Does Stuff + }) + }) + +}) + diff --git a/test/HoneyPot1/pot.js b/test/HoneyPot1/pot.js new file mode 100644 index 0000000..fb60dec --- /dev/null +++ b/test/HoneyPot1/pot.js @@ -0,0 +1,58 @@ +const BigNumber = web3.BigNumber +const Log = artifacts.require('Log') +const TrustFund = artifacts.require('TrustFund') + + +require('chai') + .use(require('chai-as-promised')) + .use(require('chai-bignumber')(BigNumber)) + .should() + +const expect = require('chai').expect + +contract('Honey Pot Test', accounts => { + const [creator, user, anotherUser, operator, mallory] = accounts + let trust = null + let logger = null + let deposit = 1000000000000000000; + + beforeEach(async () => { + logger = await Log.new(); + trust = await TrustFund.new(100000000000000000, logger.address); + + }) + + describe('Logger', () => { + it('Makes a deposit', async () => { + await trust.deposit({ from: creator, value: deposit}); + const balance = await trust.checkBalance(creator); + balance.should.be.bignumber.equal(deposit); + }) + it('Makes a withdrawal', async () => { + await trust.deposit({ from: creator, value: deposit}); + await trust.withdraw(deposit); + const balance = await trust.checkBalance(creator); + balance.should.be.bignumber.equal(0); + }) + it('Makes a deposit from another account', async () => { + await trust.deposit({ from: mallory, value: deposit}); + const balance = await trust.checkBalance(mallory); + balance.should.be.bignumber.equal(deposit); + }) + it('Makes a withdrawal from another account and fails', async () => { + await trust.deposit({ from: mallory, value: deposit}); + try { + await trust.withdraw(deposit, { from: mallory }); + } catch (e) { + if (e.toString().indexOf('revert') >= 0) { + console.log('Withdraw Reverted. Ooooo it burns'); + } + } + + const balance = await trust.checkBalance(mallory); + balance.should.be.bignumber.equal(deposit); + }) + }) + +}) + diff --git a/test/HoneyPot2/FakeBank.js b/test/HoneyPot2/FakeBank.js new file mode 100644 index 0000000..be30e3c --- /dev/null +++ b/test/HoneyPot2/FakeBank.js @@ -0,0 +1,41 @@ +import assertRevert, { assertError } from '../helpers/assertRevert' +import { increaseTimeTo, duration } from '../helpers/increaseTime'; + +const BigNumber = web3.BigNumber + +const FakeBank = artifacts.require('FakeBank') + +require('chai') + .use(require('chai-as-promised')) + .use(require('chai-bignumber')(BigNumber)) + .should() + +const expect = require('chai').expect + +contract('Honey Pot 2 Test', accounts => { + const [creator, user, anotherUser, operator, mallory] = accounts + const oneEther = 10e18; + let bank = null + + beforeEach(async () => { + bank = await FakeBank.new() + + }) + + describe('Bank', () => { + it('Makes a deposit', async () => { + await bank.sendTransaction({ value: oneEther }); + const balance = await bank.balanceOf(creator); + + balance.should.be.bignumber.equal(oneEther); + }) + it('Fails to make a withdrawal', async () => { + await bank.sendTransaction({ value: oneEther }); + await bank.withdraw(creator); + const balance = await bank.balanceOf(creator); + + balance.should.be.bignumber.equal(oneEther); + }) + }) +}) +