登录

以太坊随机数安全全面分析(二)

Pinging / 2019-07-13 09:50:00 / 浏览数 8415 安全技术 区块链安全 顶(0) 踩(0)

一、前言

本文继续前文的讲解。在前文中我们介绍了区块链中由公开变量做种子而引起的安全问题;有些合约使用区块哈希作为变量并将其放入合约函数中作为某种读博游戏的判定依旧。

由于这些随机数并非真正的“随机”,所以其安全隐患也是巨大的。本文我们继续介绍四种随机数漏洞类型。

二、基于区块哈希的随机数问题

block.blockhash(block.number-1)。

许多合约使用blockhash作为生产随机数的变量,并传入上一个区块编号。这种方法同样存在问题,攻击者可以调用相同的方法来生成该随机数。

例如下面一个合约:

/**
 *Submitted for verification at Etherscan.io on 2016-04-23
*/

contract LuckyDoubler {
//##########################################################
//#### LuckyDoubler: A doubler with random payout order ####
//#### Deposit 1 ETHER to participate                   ####
//##########################################################
//COPYRIGHT 2016 KATATSUKI ALL RIGHTS RESERVED
//No part of this source code may be reproduced, distributed,
//modified or transmitted in any form or by any means without
//the prior written permission of the creator.
    event log(uint256);
    address private owner;

    //Stored variables
    uint private balance = 0;
    uint private fee = 5;
    uint private multiplier = 125;

    mapping (address => User) private users;
    Entry[] private entries;
    uint[] private unpaidEntries;

    //Set owner on contract creation
    function LuckyDoubler() {
        owner = msg.sender;
    }

    modifier onlyowner { if (msg.sender == owner) _ }

    struct User {
        address id;
        uint deposits;
        uint payoutsReceived;
    }

    struct Entry {
        address entryAddress;
        uint deposit;
        uint payout;
        bool paid;
    }

    //Fallback function
    function() {
        init();
    }

    function init() private{

        if (msg.value < 1 ether) {
             msg.sender.send(msg.value);
            return;
        }

        join();
    }

    function join() private {

        //Limit deposits to 1ETH
        uint dValue = 1 ether;

        if (msg.value > 1 ether) {

            msg.sender.send(msg.value - 1 ether);   
            dValue = 1 ether;
        }

        //Add new users to the users array
        if (users[msg.sender].id == address(0))
        {
            users[msg.sender].id = msg.sender;
            users[msg.sender].deposits = 0;
            users[msg.sender].payoutsReceived = 0;
        }

        //Add new entry to the entries array
        entries.push(Entry(msg.sender, dValue, (dValue * (multiplier) / 100), false));
        users[msg.sender].deposits++;
        unpaidEntries.push(entries.length -1);

        //Collect fees and update contract balance
        balance += (dValue * (100 - fee)) / 100;

        uint index = unpaidEntries.length > 1 ? rand(unpaidEntries.length) : 0;
        Entry theEntry = entries[unpaidEntries[index]];

        //Pay pending entries if the new balance allows for it
        if (balance > theEntry.payout) {

            uint payout = theEntry.payout;

            theEntry.entryAddress.send(payout);
            theEntry.paid = true;
            users[theEntry.entryAddress].payoutsReceived++;

            balance -= payout;

            if (index < unpaidEntries.length - 1)
                unpaidEntries[index] = unpaidEntries[unpaidEntries.length - 1];

            unpaidEntries.length--;

        }

        //Collect money from fees and possible leftovers from errors (actual balance untouched)
        uint fees = this.balance - balance;
        if (fees > 0)
        {
                owner.send(fees);
        }      

    }
登录并阅读全文
点击收藏 | 0 关注 | 1
上一篇:利用PHP函数parse_str绕... 下一篇:从CTF学习软件逆向分析
  1. 1 条回复
  • 执念 2019-07-16 22:25:29

    0 回复Ta

登录 后跟帖

先知社区


现在登录

阿里云情报奖励X计划
社区小黑板
年度贡献榜
月度贡献榜
深信服千里目安全实验室 5
零时科技 3
arr0w1 2
0x2l 1
123qwer 1
深信服千里目安全实验室 5
零时科技 3
arr0w1 2
0x2l 1
123qwer 1

目录

RSS 关于社区 友情链接 社区小黑板