How Snyk uncovers libuv CVE-2024-24806 SSRF vulnerabilities in the Node.js project
Node.js is a powerful and widely used runtime that allows developers to build scalable and high-performance applications using JavaScript. However, many developers might not realize that Node.js relies heavily on several third-party open-source components to function effectively. Key among these components are libuv, OpenSSL, and V8. Each of these libraries plays a crucial role in the Node.js ecosystem:
libuv: Provides the event-driven, non-blocking I/O model that Node.js is known for.
OpenSSL: Ensures secure communication by implementing cryptographic protocols.
V8: The JavaScript engine that compiles and executes JavaScript code.
While these third-party components enable Node.js to deliver its robust features, they also introduce potential vulnerabilities that malicious actors can exploit. For instance, a vulnerability in the libuv or OpenSSL libraries can compromise the entire Node.js runtime, leading to severe security breaches. This makes it imperative for developers to secure these components to protect their applications and data.
Snyk offers a powerful security platform to help developers identify and remediate project vulnerabilities, including those introduced by third-party components. One of the standout features is Snyk's ability to perform unmanaged open-source scanning. This feature is particularly useful for detecting vulnerabilities in components like libuv, OpenSSL, and V8 integrated into the Node.js runtime.
How does Snyk identify vulnerabilities in unmanaged dependencies?
Snyk converts files to hashes, matches them against a database of known vulnerabilities, and displays any detected issues.
Role of libuv in Node.js
The libuv open-source component is a multi-platform support library focusing on asynchronous I/O. It provides the event loop and is the underlying engine that provides asynchronous operations such as file system interactions, network communication, and timers in the Node.js runtime. Essentially, libuv is the backbone of Node.js's non-blocking I/O model, enabling it to handle multiple operations concurrently without blocking the main execution thread (unless you cause it, for example, by writing ineffective regular expressions).
Similarly, OpenSSL is another third-party open source component that provides a robust, full-featured toolkit for implementing the Secure Sockets Layer (SSL) and Transport Layer Security (TLS) protocols. In Node.js, OpenSSL provides cryptographic functionalities, ensuring secure communication over networks.
Like the risk of regular npm libraries introducing security vulnerabilities, the C and C++ libraries built into the Node.js runtime, such as libuv and OpenSSL, may also have security implications.
The libuv CVE-2024-24806 SSRF vulnerability
Server-side request Forgery (SSRF) vulnerabilities allow attackers to make requests from the server to unintended locations. The CVE-2024-24806 SSRF vulnerability in libuv is a critical issue that can be exploited to manipulate server requests, potentially leading to unauthorized access to internal systems and sensitive data. This vulnerability is introduced through the libuv library, specifically in version 1.47.0.
What is SSRF?
SSRF allows attackers to send crafted requests from the server, potentially accessing internal services and sensitive data.
The security risks associated with CVE-2024-24806 are significant. Exploiting this vulnerability can allow attackers to:
Access internal network resources that are not intended to be publicly accessible.
Steal sensitive information such as credentials, tokens, or internal API keys.
Perform attacks on internal services, potentially leading to a complete compromise of the server or network.
The Node.js project has encountered several vulnerabilities in its third-party components. For instance, libuv has had multiple vulnerabilities, including CVE-2024-24806. OpenSSL, another critical element, has also had its share of security issues, such as the infamous Heartbleed bug (CVE-2014-0160).
The directory tree structure for the Node.js project is as follows and shows how third-party open-source dependencies are included in the runtime:
node
|── doc
|── lib
|── src
|── test
|── deps
|── ada
|── uv
|── docs
|── include
|── m4
|── src
|── test
|── autogen.sh
|── common.gpyi
|── libuv.pc.in
|── Makefile.am
|── uv.gyp
|── v8
|── zlib
|── configure
|── configure.py
|── Makefile
Detecting the libuv CVE-2024-24806 vulnerability
To demonstrate how Snyk can uncover the CVE-2024-24806 SSRF vulnerability in the Node.js project, follow these steps:
Clone the Node.js repository:
git clone https://github.com/nodejs/node
Check out the specific version that includes the vulnerable libuv library:
git checkout v21.6.0
Run the Snyk unmanaged open-source scan:
snyk test --unmanaged
The scan results will detect the SSRF vulnerability in libuv:
Testing /Users/lirantal/projects/repos/node...
Issues:
[High] Server-Side Request Forgery (SSRF)
Introduced through: https://github.com|libuv/libuv@1.47.0
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-LIBUVLIBUV-6234013
Tested 9 dependencies for known issues, found 21 issues.
This output indicates that a high-severity SSRF vulnerability (CVE-2024-24806) is present in the libuv library, specifically in version 1.47.0. This vulnerability poses a significant security risk as it can allow an attacker to make unauthorized requests from the server.
The security researcher provided the following proof-of-concept code, which demonstrates how the vulnerable uv_getaddrinfo
function in the libuv library incorrectly handles hostnames:
1function attack() {
2 for (let i = 0; i < 128; i++) {
3 const payload = '0x' + '0'.repeat(246) + '7f000001'
4 fetch(`http://localhost?url=http://${payload}.example.com:3000/secret`)
5 .then((x) => x.text())
6 .then(console.log)
7 }
8}
9
Snyk's unmanaged open-source scanning is a powerful tool for identifying vulnerabilities in third-party components that package managers do not explicitly manage. This is particularly useful for projects like Node.js, which rely on open-source libraries such as libuv, OpenSSL, and V8.
The --unmanaged command
line flag is particularly useful for C and C++ projects that aren’t managed using a proper package manifest that defines the components, as it scans all files for known open-source dependencies.
When you run the snyk test --unmanaged
command, Snyk performs the following steps:
Scanning: Snyk scans all files in your current directory.
Hashing: It converts these files into a list of hashes.
Matching: These hashes are sent to the Snyk scan server, which computes the dependencies list by querying the database.
Linking: The server links the identified dependencies to known vulnerabilities.
Displaying: Finally, the results are displayed, highlighting any vulnerabilities found.
This scanning process helps developers and operations teams surface vulnerabilities early in development and CI, ensuring that any custom-built Node.js runtime versions are secure from known threats.
In fact, Node.js v21.6.0 has over a dozen other security vulnerabilities that are attributed to V8 and OpenSSL, as the Snyk scan shows:
snyk test --unmanaged
Testing /Users/lirantal/projects/repos/node...
Issues:
✗ [Low] Uncontrolled Resource Consumption ('Resource Exhaustion')
Introduced through: https://openssl.org|openssl@3.0.12
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-OPENSSL-6592764
✗ [Low] Uncontrolled Resource Consumption
Introduced through: https://openssl.org|openssl@3.0.12
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-OPENSSL-6913421
✗ [Medium] Uncontrolled Resource Consumption ('Resource Exhaustion')
Introduced through: https://github.com|nodejs/node@21.6.0
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-NODEJSNODE-6478265
✗ [Medium] Denial of Service (DoS)
Introduced through: https://openssl.org|openssl@3.0.12
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-OPENSSL-6050293
✗ [Medium] Use of a Broken or Risky Cryptographic Algorithm
Introduced through: https://openssl.org|openssl@3.0.12
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-OPENSSL-6149450
✗ [Medium] Resource Exhaustion
Introduced through: https://openssl.org|openssl@3.0.12
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-OPENSSL-6157247
✗ [Medium] NULL Pointer Dereference
Introduced through: https://openssl.org|openssl@3.0.12
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-OPENSSL-6210213
✗ [Medium] Observable Timing Discrepancy
Introduced through: https://openssl.org|openssl@3.0.12
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-OPENSSL-6277384
✗ [Medium] Improper Input Validation
Introduced through: https://github.com|v8/v8@11.8.172.17-pgo
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-V8V8-2365614
✗ [Medium] Improper Input Validation
Introduced through: https://github.com|v8/v8@11.8.172.17-pgo
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-V8V8-2365619
✗ [High] Server-Side Request Forgery (SSRF)
Introduced through: https://github.com|libuv/libuv@1.47.0
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-LIBUVLIBUV-6234013
✗ [High] Security Features
Introduced through: https://github.com|v8/v8@11.8.172.17-pgo
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-V8V8-2365596
✗ [High] Out-of-Bounds
Introduced through: https://github.com|v8/v8@11.8.172.17-pgo
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-V8V8-2365620
✗ [High] Out-of-Bounds
Introduced through: https://github.com|v8/v8@11.8.172.17-pgo
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-V8V8-6672126
✗ [High] Improper Restriction of Operations within the Bounds of a Memory Buffer
Introduced through: https://github.com|v8/v8@11.8.172.17-pgo
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-V8V8-6672127
✗ [High] NULL Pointer Dereference
Introduced through: https://github.com|v8/v8@11.8.172.17-pgo
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-V8V8-6672131
✗ [High] Denial of Service (DoS)
Introduced through: https://github.com|v8/v8@11.8.172.17-pgo
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-V8V8-6672137
✗ [High] Heap-based Buffer Overflow
Introduced through: https://github.com|v8/v8@11.8.172.17-pgo
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-V8V8-6672138
✗ [High] Type Confusion
Introduced through: https://github.com|v8/v8@11.8.172.17-pgo
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-V8V8-7015516
✗ [High] Access of Resource Using Incompatible Type ('Type Confusion')
Introduced through: https://github.com|v8/v8@11.8.172.17-pgo
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-V8V8-7086414
✗ [Critical] Type Confusion
Introduced through: https://github.com|v8/v8@11.8.172.17-pgo
URL: https://security.snyk.io/vuln/SNYK-UNMANAGED-V8V8-6672130
Tested 9 dependencies for known issues, found 21 issues.
Finding these unmanaged C and C++ libraries is a first step, followed by monitoring them, which Snyk also supports via the snyk monitor command or automatically when you import projects.
Using Snyk's unmanaged scanning provides several benefits:
Early detection: Surface vulnerabilities early in the development and CI process.
Comprehensive coverage: Identify vulnerabilities in third-party components that might not be explicitly managed by package managers.
Enhanced security: Help developers and operations teams who compile and build their own Node.js runtime version from source to secure their builds.
Securing Node.js and its dependencies is crucial for maintaining a robust and secure application environment. The discovery of the libuv CVE-2024-24806 SSRF vulnerability underscores the importance of scrutinizing third-party open-source components integrated into the Node.js runtime. These components, such as libuv, OpenSSL, and V8, represent a significant attack surface that malicious actors can exploit.
By integrating Snyk into your development workflow, you can proactively manage and mitigate security risks associated with third-party open-source components. To get started with Snyk, sign up here.