BTC
ETH
HTX
SOL
BNB
View Market
简中
繁中
English
日本語
한국어
ภาษาไทย
Tiếng Việt

Hackers are returning to "first principles," the Curve crisis is not just a typical attack incident.

区块律动BlockBeats
特邀专栏作者
This article is about 4615 words, reading the full article takes about 7 minutes
The recent Curve crisis does not just mean a typical hacker exploit. Hackers who adhere to the "first principles" have found a perfect entry point in the deeper layers of the compiler.
AI Summary
The recent Curve crisis does not just mean a typical hacker exploit. Hackers who adhere to the "first principles" have found a perfect entry point in the deeper layers of the compiler.

Original author: Jaleel, BlockBeats

Original editor: Jack, BlockBeats

With the occurrence of a vulnerability exploit, the DeFi industry has plunged into chaos. Curve Finance, a giant in the DeFi industry, has become a prime target of severe "attacks", with multiple stablecoin pools such as alETH/msETH/pETH at risk. According to incomplete statistics, this vulnerability exploit event has caused a total loss of $52 million for Alchemix, JPEG'd, MetronomeDAO, deBridge, Ellipsis, and the CRV/ETH pool, severely shaking the confidence of the entire market.

Vyper versions 0.2.15, 0.2.16, and 0.3.0 had a reentrancy bug, and the recommended version on the Vyper official documentation was also incorrect. Other projects using the Vyper compiler promptly conducted self-audits in an attempt to ensure they wouldn't become the next victims. As the source of the vulnerability exploit event was gradually revealed, the market gradually realized that this crisis not only signifies a regular hacker vulnerability exploit event but also exposes the enormous potential risks of the entire DeFi industry's underlying stack.

Compared to the past, the number of hacker incidents in recent times has decreased, which is related to the degree of market prosperity. During the DeFi summer and NFT summer, new billion-dollar protocols were launched every week. In contrast, the current market is stagnant. Meanwhile, hackers are finding dwindling market opportunities for exploiting vulnerabilities or orchestrating large-scale attack events. This means that hackers need new, unexplored entry points to explore.

Returning to "first principles," hackers have found a perfect entry point in lower-level compilers to feast on the delicious "cake" in the DeFi market. Lower-level compilers have become a "smarter" choice for hackers. In regards to this event and the related issues it has exposed, BlockBeats interviewed smart contract developer Box (@BoxMrChen) and BTX researcher Derek (@begas_btxcap).

How did the Curve incident occur?

Aave and Lens founder Stani (@StaniKulechov) expressed his views on the incident on social media: "This is an unfortunate setback for Curve and DeFi. While DeFi is an open space that can contribute, it is difficult to be absolutely correct and the risks are high. In the case of Curve, they did it right at the protocol level."

The vulnerability exploit encountered by Curve is one of the oldest and perhaps most common forms of Ethereum smart contract attacks, known as reentrancy attacks. A reentrancy attack allows an attacker to repeatedly call a specific function of a smart contract without waiting for the previous call of that function to complete. This allows them to continuously exploit the vulnerability and withdraw funds from the affected contract until it is depleted.

Reentrancy Lock and CEI Principle

Let's illustrate a simple example to explain the reentrancy attack: A bank has a total of $100,000 in cash. However, this bank has a major vulnerability where the account balance is not immediately updated when people withdraw money. Instead, it is only checked and updated at the end of each day. Someone discovers this vulnerability and opens an account at the bank. They deposit $1,000 and then withdraw $1,000. After 5 minutes, they withdraw another $1,000. Because the bank does not update the balance in real-time, the system still thinks their account has $1,000 before the check and update process. By repeating this operation, the user eventually withdraws all $100,000 in cash from the bank. The bank only realizes the vulnerability has been exploited at the end of the day.

The complexity of a reentrancy attack lies in its exploitation of the inter-contract calling and the contract's own logical vulnerabilities, by deliberately triggering exceptions and fallback mechanisms for fraudulent activities. Attackers can repeatedly exploit the contract's logical loopholes to steal funds. The solutions to prevent reentrancy attacks are also widely known, such as setting up specific code content in advance for protection, which is known as a reentrancy lock to ensure fund security.

Solidity, the programming language for smart contracts, has established a principle called "Check Effects Interactions" (CEI) to protect functions from reentrancy attacks. The content of the CEI principle includes:

1. The calling order of function components should be: first check, then affect state variables, and finally interact with external entities.

2. Before interacting with external entities, all state variables should be updated. This is called "optimistic accounting" where the impact is recorded before the interaction actually occurs.

3. Checks should be performed at the beginning of a function to ensure that the calling entity has the permission to call that function.

4. State variables should be updated before any external calls to prevent reentrancy attacks.

5. Even trusted external entities should follow the CEI pattern, as they may transfer control flow to malicious third parties.

According to the document, the CEI principle helps to limit the attack surface of contracts, especially to prevent reentrancy attacks. The CEI principle can be easily applied by following the order of functional codes without changing any logic. The well-known exploit of The DAO vulnerability that caused the Ethereum fork also ignored the "CEI principle" and allowed the attacker to successfully execute a reentrancy attack, resulting in devastating consequences.

However, the attacked Curve pool did not adhere to this CEI principle because Curve used the Vyper compiler. A vulnerability in the Vyper code as the compiler resulted in the failure of the reentrancy lock, enabling the hacker to successfully carry out the reentrancy attack.

Most people are familiar with Solidity, but Solidity is not the only language for creating smart contracts. Currently, Vyper is the popular alternative to Solidity. Although Vyper may not have the same functionality and popularity as Solidity, it is an ideal choice for developers familiar with Python because Vyper can transpile Python-like code into Ethereum smart contract programming language.

According to information on GitHub, the top contributor to the Vyper GitHub code repository is also a developer for Curve. This easily explains why Curve chose Vyper instead of Solidity.

Why did the Vyper reentrancy lock fail?

So, what went wrong with Vyper in this attack? Why did the reentrancy lock fail? Was it due to lack of testing? BlockBeats interviewed smart contract developer Box 826.eth (@BoxMrChen) who revealed that there were indeed test cases for the Vyper reentrancy lock. However, the reason for the failure was that the test cases were result-oriented and, therefore, incorrect.

In short, the main reason for the failure of the Vyper reentrancy lock is that the person who wrote the test cases based them on the expected results without considering why the slot would mysteriously skip one.

In the Vyper code shared by Box, the problem is obvious. When the lock name appears for the second time, the number of storage_slot will be overwritten, which means that in the ret, the first time the lock is obtained, the slot is 0, but after another function uses the lock, the slot of the lock is incremented. Using the wrong slot after compilation makes the reentrant lock ineffective.

On the left is the code being attacked, and on the right is the code after being fixed.

"Expected errors in test results, of course, cannot verify errors. Let's take a simple example, now we are doing a math problem, 1 + 1 = 2, but the given correct answer is wrong, saying 1 + 1 = 3. At this time, the student who is doing the problem answers 1 + 1 = 3, but it coincides with the pre-determined correct answer, so the program naturally cannot determine that the test result is wrong." Box said in an interview with BlockBeats.

The "Sword of Damocles" has been hanging for two years

In the first recorded reentrancy attack in history, the attacker of the WETH Attack intentionally created the attack in order to make developers pay attention to the possibility of reentrancy attacks, and the purpose is to protect more projects from potential reentrancy attacks. In the context of smart contracts, developers should use different triggering mechanisms, such as calling a state-changing function to implement protection. This requires developers to fully consider possible attack scenarios and take appropriate preventive measures when designing contracts.

To gain a deeper understanding of the Vyper editor, BlockBeats interviewed BTX researcher Derek (@begas_btxcap), who stated that for developers familiar with Python, Vyper is a more ideal choice than Solidity with a more comfortable UI and faster learning curve. However, it is evident that some versions of the Vyper editor code have not undergone reliable third-party audits. Some audits may even have been carried out by the developers themselves. "This wouldn't happen in the traditional IT industry because when a new language is released, countless auditing companies would search for vulnerabilities," Derek said.

Not to mention, allowing an error to exist for two years without being addressed.

Vyper contributor  fubuloubu also expressed that the compiler has not been reviewed or audited as people may imagine. Most compilers undergo significant and frequent changes, which makes auditing challenging. Even with a complete codebase audit, it becomes outdated with each subsequent version added. Auditing the compiler is not a comprehensive approach since auditing the final product generated by end-users (i.e., original EVM code) is more meaningful.

All of this points to the last issue: incentives. No one has the motivation to find critical vulnerabilities in the compiler, especially in older versions. Fubuloubu previously proposed a plan to improve Vyper by adding a user-sponsored bounty program, but it was not approved.

Hackers are returning to "first principles."

For protocol and project developers, this serves as another vivid example of contract security development practices. But more importantly, the Curve incident warns us that safety issues in the underlying compiler have been significantly overlooked. Hackers returning to "first principles" have found a perfect entry point in the lower-level compiler.

After the fact, Stani, the founder of Aave and Lens, also shared his thoughts in a lengthy post on social media: The Curve attack incident signifies that DeFi risks involve the entire underlying stack, programming languages, EVM, etc. It warns us to be more cautious and sensitive, especially when using custom EVM and application chains in the future.

Attacks from the Lower Levels

For compiler vulnerabilities, it is difficult to detect them simply by auditing the contract source code logic. Merely studying the differences between versions is also a significant task. It requires a combined analysis of specific compiler versions and specific code patterns to determine if a smart contract is affected by compiler vulnerabilities.

"Currently, only two compilers are considered the best, Vyper's codebase is smaller, easier to read, and has fewer changes in its history, which may be why hackers target it. Solidity's codebase is larger."

"Fubuloubu even suspects that state-supported hackers may be involved in this Curve attack: 'Finding this vulnerability would take weeks to months, considering the resources invested, it may have been done by a small group or team.'"

"As the most widely used compiling language in the cryptocurrency industry, the security of Solidity is a significant concern for users. After all, if the reentrancy issue is caused by the Solidity compiler, the entire DeFi industry's history may be rewritten."

"According to the regular security alerts released by the Solidity development team, there have been security vulnerabilities in multiple versions of the Solidity compiler."

"The most recent compiler error was recorded on June 26th, in which an error was found in the old code generation pipeline of the Solidity compiler while investigating security reports related to the use of side-effecting ternary expressions with abi.decode as type arguments. The old code generator did not evaluate complex expressions, such as assignments, function calls, or conditions, where the .selector is being accessed. This caused side-effects of such expressions to not be executed, resulting in potentially incorrect behavior of contracts compiled using the old pipeline."

"We can also see in the Solidity Github repository that there is a file listing known security-related bugs in the Solidity compiler. This list goes back to version 0.3.0, and bugs that existed only before this version are not included. Additionally, there is another bugs_by_version.json file, which can be used to query which bugs affect specific compiler versions."

"Fortunately, due to the widespread use of the Solidity language and the support from the Ethereum Foundation, many existing problems have been identified by projects and protocols during their deployment processes. Therefore, Solidity has made modifications and improvements faster than Vyper. From this perspective, it is also one of the reasons why Solidity is more standard and secure."

In order to help Solidity developers to conduct better testing and prevent similar incidents, SunSec, co-founder of UnitasProtocol (@ 1 nf 0 s 3 cpt), released a DeFiVulnLabs Solidity security testing guide after the Curve attack. It supports 47 vulnerabilities, including vulnerability descriptions, scenarios, defenses, vulnerable code, mitigation measures, and how to test.

How to avoid underlying attacks as much as possible?

In this Curve incident, Box believes that the lesson all developers should learn is: do not be greedy to follow technological trends and choose immature solutions; do not accept your code without writing test cases (on several versions of Vyper that had problems, even the test cases were incorrect); never approve your code by yourself; some vulnerabilities may take years to be discovered; not being upgradable is arrogance towards oneself and disdain towards others.

Usually, developers may not realize what pitfalls are hidden here and casually choose a version to compile, which may overlook the risks brought by differences between versions. Even minor version upgrades can introduce significant changes, which is especially important when developing decentralized applications.

The warning the Curve incident gives to developers is: use newer versions of compiler languages. It is important to keep the codebase, applications, and operating systems up to date and build a comprehensive security defense mechanism. Although new versions may also introduce new security issues, known security issues are usually fewer than in older versions. Of course, it is also important to pay attention to community and official version update announcements. Understand the changes brought by each version and update your codebase and runtime environment as needed. Taking these measures may greatly reduce security incidents caused by compiler errors.

In addition, it is necessary to improve the unit test cases of the code. Most compiler-level errors will lead to inconsistent code execution results, which are difficult to discover through code review alone but can be exposed during testing. Increasing code coverage helps avoid such problems. Additionally, try to avoid using complex language features such as inline assembly and multidimensional array encoding and decoding, unless there is a specific requirement. Most historical Solidity language vulnerabilities have been related to these advanced features. Developers should avoid using experimental language features just to show off their skills unless there is a special need.

For protocol layers and security personnel, when conducting code audits, the risks that compiler versions may bring should not be ignored. It can be foreseen that hackers have already opened up new ideas, and in the future, there will be more incidents exploiting lower-level vulnerabilities. At the same time, as the underlying infrastructure at a lower level, the underlying stack, programming languages, EVM, and others need to be thoroughly audited. The market for auditing companies will become larger in the future, and the market for white-hat bounties will also grow. The Vyper team also plans to start a bug bounty program after the matter is officially concluded.

Of course, there is no need to panic excessively about the risks of underlying infrastructure. Currently, most compiler bugs are only triggered in specific code patterns, and the actual impact needs to be evaluated based on the project's specific circumstances. Regularly upgrading the compiler version and conducting sufficient unit testing can help prevent risks.

Reference:

1.https://www.quicknode.com/guides/ethereum-development/smart-contracts/a-broad-overview-of-reentrancy-attacks-in-Solidity-contracts

2.https://github.com/pcaversaccio/reentrancy-attacks/issues/1

3.https://nipunp.medium.com/5-8-21-rari-capital-exploit-timeline-analysis-8beda31cbc1a

4.https://docs.Soliditylang.org/en/v0.8.21/




Safety
DeFi
Curve
Welcome to Join Odaily Official Community