"Now enter you or the forerunner, finally the Watcher enters is the leek." Mr. Cai, Chairman of the Board of Directors, predicted the prophecy in the Three O'Clock Group. On April 22, with the advent of the BEC Smart contract loophole, a line of code evaporated 6447277680 yuan. However, after a lapse of three days, the smart contract SMT, the price of SMT in the fire currency pro fell nearly 20%. For a time, no matter forerunner or quasi "leek", have been harvested miserably.
Blockchain as a product can interact with the value, it is inevitable that people are not deified. Rationally analyzing, the loopholes in the program are always unavoidable, it is difficult to ensure that the code hundred percent error, even if large companies can only release the test version to reduce the probability of vulnerability. Today, let's look at the founders of the smart contract--what is the "pit" of the Ethereum Smart contract, and how to write the code to get out of the hole.
Author | Consensys Diligence
Translator | Guoxi
April 25 morning, the fire currency Pro issued a notice, virtual currency SMT Project Party feedback early on 25th to find their transactions are abnormal problems, after preliminary troubleshooting,SMT of the Ethereum Smart contract there are loopholes. Fire Currency Pro also detected an anomaly of TXID as 0x0775e55c402281e8ff24cf37d6f2079bf2a768cf7254593287b5f8a0f621fb83 during the same period. By this effect, the fire currency Pro suspends all currencies of the coin-charging business. On that day, the price of SMT in the fire currency pro fell nearly 20% as of the closing of the transaction.
This type of vulnerability is not the first time, only three days from the last occurrence.
On April 22, Bec unusual transactions, according to analysis, the BEC Smart Contract Batchtransfer Bulk transfer function has a loophole, the attacker can pass in a large value value, so that CNT *value after the maximum value of unit256 so that its overflow causes amount to become 0.
In Short, a section of the BEC code forgot to use the Safemath method, causing the system to generate an integer overflow vulnerability, exploiting the vulnerability, the hacker can transfer to generate a large number of non-existent tokens in the original contract, and these "out of the box" tokens in the market to sell.
Since the number of tokens transferred by hackers far exceeds the 7 billion of the BEC issue, and the resulting panic sell-off, Bec's 6.4 billion market capitalisation has almost zeroed.
After these two incidents, the Peckshield team scanned the Ethereum smart contracts and analyzed them using an automated system. The results show that there are batchoverflow security risks in many ERC-20 intelligent contracts. If you do not do a strict code audit and security protection, billions of dollars of money loss only in a flash. So how can we avoid this happening? Here are the discovered smart contract attacks that you must know and avoid when writing smart contracts for asset security.
2 types of vulnerabilities caused by race conditions
A race condition (race condition) means that the device or system has an inappropriate execution timing and gets incorrect results.
It is risky to invoke an external contract when executing a smart contract because the external contract can take over the control flow of your current contract, and a malicious external contract may change the key data in your contract, which has a huge impact on the current contract. Two contracts around, it sounds a mouthful. To explain to you in layman's way.
Imagine that when you transfer money suddenly a person appears in front of you, interrupting your operation and while you are not paying attention to change your transfer information, when you find that the money has been transferred to the wrong person is too late. There are many forms of this vulnerability, and it is also the "culprit" in the history of the largest smart Contract vulnerability event--the DAO. The DAO incident resulted in the theft of $60 million in Ethereum, and the $60 million loss was estimated at the then $17.5 ethereum price, which led to the hard fork at Ethereum.
Vulnerability One: function reentrant
Reentrant (reentrancy) can generally be understood as a function in a number of simultaneous calls, such as the operating system during the process of scheduling, or the MCU, the processor, such as the interruption of the phenomenon of re-entry occurs.
The first possibility of this vulnerability is that the called function may be executed multiple times before the operation of other functions is completed. This may cause several functions in the smart contract to interact in a destructive manner.
Because the user's balance has not been placed 0 until the end of the function execution. The second (and later) call to other functions will still succeed and will cancel the 0 operation on the account balance once and again. The DAO event was stolen by Ethereum because the attacker performed the operation.
solution, in the given example, in order to avoid encountering this vulnerability, our solution is to use the function send () instead of the function Call.value (), which will prevent any external code execution.
But if you cannot avoid calling an external function, the next easy way to prevent such an attack is to make sure that you have completed all the internal actions you want to perform when you invoke the external function.
Note that if you have another function that also calls Withdrawbalance (), then it may also be subject to the same attack, so you have to treat the function that calls the non-trusted contract as a non-letter number, and then I'll discuss the potential solution further.
Vulnerability II: Race condition for cross-function
An attacker could also perform a similar attack on two different functions that share the same state.
In this case, the attacker could invoke the transfer () function when the code executes to call Withdrawbalance (), and since their balances are not yet set at 0, they will be able to transfer the pass even if they have received a refund, and the vulnerability is also used in the DAO event.
The same principle, the same considerations. Note that in this example, both functions are part of the same smart contract, and similarly, this vulnerability can occur between these contracts when multiple contracts share the same state.
Because race conditions can occur between multiple functions, or even between multiple smart contracts, a solution designed to prevent reentrant phenomena is clearly insufficient.
Solutions, Here are two solutions, one that we recommend doing all of the internal work before calling the external function, and the other is using a mutex.
1. First Solution, complete all the internal work before calling the external function. If you follow this rule carefully when writing a smart contract, you can avoid race conditions. However, you need to be careful not only to avoid calling external functions prematurely, but also to be aware of external functions called by external functions, for example, the following operations are unsafe.
Although the function Getfirstwithdrawalbonus () does not call the external contract directly, the call in the function withdraw () is sufficient to allow it to enter the race condition. Therefore, you need to treat the function withdraw () as a non-letter number.
In addition to fixing the vulnerability to make this reentrant phenomenon impossible, it is also possible to mark untrusted functions. This tag should be noted over and over again because the function Untrustedgetfirstwithdrawalbonus () calls the non-letter number Untrustedwithdraw (), which means that an external contract is called, Therefore you must also list the function Untrustedgetfirstwithdrawalbonus () as a non-letter number.
2. The second solution is to use mutual exclusion locks. that allows you to "lock down" certain states, which can only be changed by the owner of the lock at a later stage, as shown below, which is a simple example:
If the user tries to call the withdraw () function again before the end of the first call, the lock blocks the operation, leaving the result unaffected. This can be an effective solution, but it can also become tricky when you want to run multiple contracts at the same time, and here's an unsafe example:
In this case an attacker could call the function Getlock () to lock the contract, and then no longer call the function ReleaseLock () to unlock the contract. If they do, the contract will be permanently locked and no further changes can be made. If you use a mutex to prevent race conditions, you need to make sure that you do not have a situation where the lock is locked but never unlocked. There are many other potential risks to using mutexes when writing smart contracts, such as deadlocks or live locks. If you decide to use this approach, be sure to read a lot about mutexes and avoid "stepping on thunder".
Some people might object to the term race condition, because Ethereum does not really achieve parallelism. However, the underlying characteristics of logically different processes competing for resources still exist, so the same vulnerabilities and potential solutions apply.
Trade order dependencies and loopholes caused by illegal advance trading
Trade order Dependent (transaction-ordering Dependence,tod)
Illegal advance trading (Front Running) Illegal advance trading is an unethical way for brokers to profit from client transactions. Make a preemptive transaction for your account in the hands of a client transaction.
The following are the different types of race conditions inherent in the blockchain: inside the block, the order of the trades itself is easily manipulated by humans.
Since each transaction is spent in the memory pool while the miners are digging, you can imagine what happens before the transaction is packaged into the block. For a centralized market, a change in the order of trades can cause a lot of trouble. For example, the market is a common buy some tokens trading. It is difficult to prevent these 10 points because it involves specific implementation details in the contract. For example, in the de-centralized market, because it can prevent high-frequency trading, so the effect of batch auction is better. Another solution is to use the mechanism of pre-submission, so don't worry, I'll explain the details of the mechanism in detail later.
Vulnerability Three: Timestamp dependent
Note that chunk timestamps can be manipulated by miners, so be aware of all the direct and indirect uses of timestamps.
There are a lot of time stamp-related considerations, you must carefully study before programming.
Vulnerabilities caused by overflow and underflow of integers
Imagine a very simple scenario for transferring a pass:
If your account balance reaches the largest unsigned integer value in Ethereum (2^256), your balance will not increase again. Because it is usually possible to carry on this phenomenon, but here the unsigned integer value is only 256 bits, the NO. 257 bit of carry is not displayed, so you have not guessed wrong, when you carry the balance will return to 0. In computer science, this phenomenon is called the overflow of integers.
Of course, this is also less common, because it requires that you really have so many balances, and your smart contract doesn't take into account the overflow problem. Consider whether this unsigned integer value has the opportunity to reach such a large number, and then consider the unsigned integer value if it changes the current value and who has the right to make such a change. If any user in the smart contract can call a function to update the unsigned integer value, the smart contract will be vulnerable to attack. If only administrators can make changes, then it may be safe. If the contract stipulates that the user's account balance can only increase by 1 each time, then this contract may also be very safe, because there is no feasible way for you to reach this limit in a short time.
When the account balance reaches its maximum, it will be zeroed out, and you will instantly turn from the richest person to the poorest. I wonder if you think you can turn from the poorest to the richest man. Yes, Underflow is also the case, if the unsigned integer value is less than 0, then it needs to forward borrow, and the borrowed one does not show, so your balance will overflow to the maximum value.
See here, you must be careful to use unsigned integer values like 8-bit, 16-bit, and 24-bit, because the 8-bit unsigned integer values can represent only 255, so the overflow occurs when they are more likely to reach their maximum value.
Please be careful when dealing with spills, before a programmer has collated the overflow and underflow scenarios of 20 smart contracts.
Vulnerability IV: Deep underflow in storage operations
Doug Hoyte This loophole in the Ethereum hack game of 2017, which has earned him the honor of the game. The idea is interesting because it raises concerns about how the C-language underflow affects the solidity of the Ethereum programming language. This is a simplified version:
In general, if the keccak256 hash is not computed (which is unrealistic, of course), the storage location of the variable manipulateme will not be affected. But since dynamic arrays are stored sequentially, if an attacker wants to change the manipulateme variable, he only needs to do this:
Call the function Popbonuscode () to implement Underflow. (Note that the Ethereum programming language solidity does not have a built-in pop function.) )
Calculates the location where the variable manipulateme is stored.
Use the function Modifybonuscode () to modify and update the value of the variable manipulateme.
In fact, it is known that this array of vulnerabilities exists. But if such arrays are buried under a more complex framework of intelligent contracts, who can easily find them? This makes it possible to maliciously tamper with the variable.
Solutions, using a container-style data structure is a good choice when considering the use of dynamic arrays. This vulnerability is described in detail in the 1th and 2nd parts of the solidity crud.
Vulnerability due to accidental recovery
Vulnerability V: Use of transaction failure to facilitate accidental recovery
Consider a simple auction contract:
When the smart contract is ready to pay for the original owner of the product, if the payment fails, it will recover. This means that a malicious bidder can make sure that the payment of the original owner of the product is always unsuccessful while the product is being photographed. This way they can prevent others from calling the bid () function and become the new owner of the product. As mentioned earlier, in order to secure funds, it is recommended to establish a pre-authorized payment contract at auction.
Another example is when a smart contract uses an iteration of an array to make payments to a user, such as a refund to supporters of a crowdfunding contract. Usually make sure every payment is successful, and if any payment fails, it will be resumed and re-paid. The problem is that if a payment fails, then you have to restore the entire payment system. This means that if a payment is stuck, the iteration payment will never be completed because an address error will not be paid by everyone.
Solutions, Our advice here is to use a pre-authorized method of payment.
Vulnerability due to block fuel limits
Vulnerability VI: Using block fuel caps to trigger vulnerabilities
You may have noticed another problem in the previous example: if you want to pay to everyone at once, you may encounter a situation where the fuel cap in the block is reached. Each ethereum block can only handle a certain maximum amount of computation, and if you try to exceed this limit, your trading will fail.
This is a problem even if no hacker intentionally attacks you. If an attacker is able to manipulate the fuel you need, things will get worse. In the previous example, an attacker could add a heap of addresses, each of which would require a small refund. Therefore, the addition of fuel to the attacker's address refunds may result in exceeding the block fuel cap, thereby preventing a refund transaction from occurring.
solution,