GHSA-4HWQ-4CPM-8VMX
Vulnerability from github – Published: 2024-02-26 20:11 – Updated: 2025-01-21 17:54Summary
When using the built-in extract32(b, start), if the start index provided has for side effect to update b, the byte array to extract 32 bytes from, it could be that some dirty memory is read and returned by extract32.
As of v0.4.0 (specifically, commit https://github.com/vyperlang/vyper/commit/3d9c537142fb99b2672f21e2057f5f202cde194f), the compiler will panic instead of generating bytecode.
Details
Before evaluating start, the function Extract32.build_IR caches only:
- The pointer in memory/storage to
b: https://github.com/vyperlang/vyper/blob/10564dcc37756f3d3684b7a91fd8f4325a38c4d8/vyper/builtins/functions.py#L916-L918 - The length of
b: https://github.com/vyperlang/vyper/blob/10564dcc37756f3d3684b7a91fd8f4325a38c4d8/vyper/builtins/functions.py#L920-L922
but do not cache the actual content of b. This means that if the evaluation of start changes b's content and length, an outdated length will be used with the new content when extracting 32 bytes from b.
PoC
Calling the function foo of the following contract returns b'uuuuuuuuuuuuuuuuuuuuuuuuuuu\x00\x00789' meaning that extract32 accessed some dirty memory.
var:Bytes[96]
@internal
def bar() -> uint256:
self.var = b'uuuuuuuuuuuuuuuuuuuuuuuuuuuuuu'
self.var = b''
return 3
@external
def foo() -> bytes32:
self.var = b'abcdefghijklmnopqrstuvwxyz123456789'
return extract32(self.var, self.bar(), output_type=bytes32)
# returns b'uuuuuuuuuuuuuuuuuuuuuuuuuuu\x00\x00789'
Impact
For contracts that are affected, it means that calling extract32 returns dirty memory bytes instead of some expected output.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 0.3.10"
},
"package": {
"ecosystem": "PyPI",
"name": "vyper"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.4.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2024-24564"
],
"database_specific": {
"cwe_ids": [
"CWE-125"
],
"github_reviewed": true,
"github_reviewed_at": "2024-02-26T20:11:35Z",
"nvd_published_at": "2024-02-26T20:19:05Z",
"severity": "LOW"
},
"details": "### Summary\n\nWhen using the built-in `extract32(b, start)`, if the `start` index provided has for side effect to update `b`, the byte array to extract `32` bytes from, it could be that some dirty memory is read and returned by `extract32`.\n\nAs of v0.4.0 (specifically, commit https://github.com/vyperlang/vyper/commit/3d9c537142fb99b2672f21e2057f5f202cde194f), the compiler will panic instead of generating bytecode.\n\n### Details\n\nBefore evaluating `start`, the function `Extract32.build_IR` caches only:\n\n- The pointer in memory/storage to `b`: https://github.com/vyperlang/vyper/blob/10564dcc37756f3d3684b7a91fd8f4325a38c4d8/vyper/builtins/functions.py#L916-L918\n- The length of `b`: https://github.com/vyperlang/vyper/blob/10564dcc37756f3d3684b7a91fd8f4325a38c4d8/vyper/builtins/functions.py#L920-L922\n\nbut do not cache the actual content of `b`. This means that if the evaluation of `start` changes `b`\u0027s content and length, an outdated length will be used with the new content when extracting 32 bytes from `b`.\n\n### PoC\n\nCalling the function `foo` of the following contract returns `b\u0027uuuuuuuuuuuuuuuuuuuuuuuuuuu\\x00\\x00789\u0027` meaning that `extract32` accessed some dirty memory.\n\n```Vyper\nvar:Bytes[96]\n\n@internal\ndef bar() -\u003e uint256:\n self.var = b\u0027uuuuuuuuuuuuuuuuuuuuuuuuuuuuuu\u0027\n self.var = b\u0027\u0027\n return 3\n\n@external\ndef foo() -\u003e bytes32:\n self.var = b\u0027abcdefghijklmnopqrstuvwxyz123456789\u0027\n return extract32(self.var, self.bar(), output_type=bytes32)\n # returns b\u0027uuuuuuuuuuuuuuuuuuuuuuuuuuu\\x00\\x00789\u0027\n```\n\n### Impact\n\nFor contracts that are affected, it means that calling `extract32` returns dirty memory bytes instead of some expected output.",
"id": "GHSA-4hwq-4cpm-8vmx",
"modified": "2025-01-21T17:54:09Z",
"published": "2024-02-26T20:11:35Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/vyperlang/vyper/security/advisories/GHSA-4hwq-4cpm-8vmx"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-24564"
},
{
"type": "WEB",
"url": "https://github.com/vyperlang/vyper/commit/3d9c537142fb99b2672f21e2057f5f202cde194f"
},
{
"type": "WEB",
"url": "https://github.com/pypa/advisory-database/tree/main/vulns/vyper/PYSEC-2024-205.yaml"
},
{
"type": "PACKAGE",
"url": "https://github.com/vyperlang/vyper"
},
{
"type": "WEB",
"url": "https://github.com/vyperlang/vyper/blob/10564dcc37756f3d3684b7a91fd8f4325a38c4d8/vyper/builtins/functions.py#L916-L918"
},
{
"type": "WEB",
"url": "https://github.com/vyperlang/vyper/blob/10564dcc37756f3d3684b7a91fd8f4325a38c4d8/vyper/builtins/functions.py#L920-L922"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Vyper\u0027s `extract32` can ready dirty memory"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.