With this article, we begin a cycle dedicated to typical vulnerabilities, attacks and problem areas inherent in Solidity smart contracts, and the Ethereum platform as a whole. In the first part we will talk about this:
Disclaimer: We already talked about the front-running attack in the analysis of the competition for ZeroNights 2017. Therefore, those who read can immediately proceed to the next item.
The term front-running has appeared a long time ago, and means the possibility of manipulation in the market due to the possession of closed information about transactions in a pending state. If a fraudster knows that a big purchase is coming, he can quickly buy a bargaining item cheaply, thus ensuring his own profit.
In cryptocurrencies, and in Ethereum in particular, all transactions are first placed in the unconfirmed pool (pending pool or mempool or backlog), where they wait for the miner to take them from there and add them to the block. However, unlike the classic stock exchanges, where such information is available to a very narrow circle of people, all members of the network can see the pending pool in Ethereum. And, since the average time through which a new transaction falls into a block is ~ 14 seconds , the attacker has enough time to analyze the market behavior and send his own transaction that takes this behavior into account. Last, how can an attacker guarantee that his transaction will be processed first? The answer lies in the amount of commission per transaction - the larger it is, the faster the transaction will fall into the block. However, in Ethereum, the concept of commission is a little more complicated than usual, and is calculated as follows:
As a mitigation from this attack, a smart contract can analyze the transaction property tx.gasprice
. However, this will not be a complete solution to the problem, since the miner is actually not obliged to sort the transactions in descending order by gasPrice - this is only an economic incentive. If the option of a more significant stable gain appears, who knows what the miner will do :)
In order to somehow protect against this, you can use cryptography - for example, first send a hash from the desired action (purchase or sale) with the number of tokens. And in the next block already send the data itself. Although the scheme is also not without drawbacks, at a minimum, it is more complicated - it requires twice as many transactions.
Ethereum in its design is a deterministic mechanism, therefore it is very difficult to draw entropy anywhere inside it. However, not all Solidity developers are sophisticated in the internal structure, but see before them only a description of the syntax of the language, and try to apply it as they did in other programming languages.
So, from where it is impossible to take entropy:
An exception is the function block.blockhash(uint blockNumber)
, which returns the hash of a block by its number. However, you need to apply it, keeping in mind two things:
Examples of improper use of blockhash and exploits for them can be found here and here .
Another option is the commit-reveal scheme that RANDAO uses. In the first phase, over the course of M blocks, N participants guess a random number and send a hash from it with some deposit to the smart contract. In the second phase, participants send their hidden numbers to a smart contract, and he checks the number, taking the hash from it. After everyone has sent the numbers, the contract uses them as a seed for the PRNG. If the participant does not send his number at the specified time, he loses the deposit he made and the round is canceled (the rest receive their deposit back). The drawback of the scheme is obvious - it is subject to DOS, so if random numbers are needed constantly and immediately, such a scheme in its pure form is unlikely to work. It is worth looking at the additional rules for this scheme, as suggested by the RANDAO themselves or to invent one based on it, like Acne . And you can combine the idea with the block hash and the commit-reveal scheme.
Another option worth noting is Signidice . The scheme is good when there are few participants, so we will look at it using the example of a roulette game. So, there are two participants - a casino and a player, as well as a smart contract that implements the logic of the game. At the preparatory stage, the casino generates a private-public key pair and sends a public smart contract. At this training is over, you can play. Go:
The biggest drawback that stops us from taking and applying the scheme right now is that the Ethereum signature algorithm is ECDSA . And if you use it, then the casino will always have the opportunity to cheat. I will agree to the algorithm , at the third step random k is chosen. This parameter directly affects the final signature, and the same k cannot be used, otherwise, having two signatures, it will be possible to restore the casino private key (you cannot disclose k for the same reason). Therefore, the casino can change k until it receives a signature with which it will win. Here is an example of such a casino.
Besides (we will discard the previous problem), it is necessary to solve the problem with what to do if the participant makes the same number. Provided that the casino uses the same parameters for the signature (including, k), it will be identical to the previous one, and therefore not random. Therefore, we need a ban on the reuse of the guess number or the generation of a new key pair every round.
The “Light at the End of the Tunnel” for Signidice is EIP-198 about adding a modulo operation. This makes it possible to implement signature verification for RSA. When using RSA, casino cheating will fail.
In fact, there are a lot of approaches to solving the problem of obtaining random numbers, there are no options left for entropy off-chain ( Oraclize ) and experiments with whisper .
In this block we will not deal with smart contracts, however, we will consider one feature of the permissioned blockchain - validators are always known. As an example, a network with a Proof-of-Authority consensus. Proof-of-Authority is a special case of a network with a Proof-of-work consensus, only mining can be selected (validators). A striking example of such networks is test networks for Kovan and Rinkbey developers. This consensus was conceived mainly in order to avoid spam attacks . When a malicious miner, having an advantage in power (due to the use of a GPU), gets new blocks faster than the rest of the network, he consolidates a large amount of ether in his hands. While ordinary members of the network can no longer extract ether on their own - they drain the "taps" that were previously replenished with bona fide miners. All this leads to the fact that new developers cannot use the network due to the lack of ether. For those who still have air, normal work in such a network is also not possible. A miner is capable of littering the network with meaningless but expensive transactions, which, in turn, will make adding normal participants to the transaction block difficult and time consuming.
So, the Proof-of-Authority approach with selected validators can be used not only for test networks, but also for permissioned networks. For example, the PoA network is a publicly accessible network in which the validators are legally assigned members. Does PoA relieve these networks from the possibility of conducting DOS attacks? Yes and no.
At the Internet level, it is still possible to generate a large amount of traffic on port 30303, on which the miner listens. And thus make it unavailable to the rest of the network. Further, it is obvious - there is no validator, no one extracts blocks, transactions are accumulated, the network costs. But how to calculate the miner in the network? After all, he uses exactly the same client for the network as the rest.
The algorithm is actually simple:
curl --data '{"method":"parity_netPeers","params":[],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8545 -s | jq '.result.peers[]' | jq '.network.remoteAddress' | cut -d "\"" -f 2 | cut -d ":" -f 1
If there are more than 25 of them, then you will have to forcibly break connections to known IPs, for example, using iptables, and so assemble them all.
Further, all that is needed is to track from which IP the first new blocks come. These IP will be miners.
That's all for now. In the next part, we proceed directly to the problems that may occur in smart contracts.
Source: https://habr.com/ru/post/345196/
All Articles