Full Report
Rust is perfectly safe and we never have to worry again, right? In Rust, error handling is tedious and most be specifically handled. Because of this, many denial of service (DoS) vectors revolve around handling errors in Rust. In P2P networking, you are communicating with other computers which in turn communicate with other computers. So, this is a necessity of communicating in a blockchain network and must be externally exposed in some way. The author of this post found two locations where errors were not being handled correctly. First, when verifying a public key the from_slice() function requires that it must be 32 bytes in length. When processing this in the handshake code of P2P, expect(), a nice wrapper for unwrap() is called. If the public key isn't 32 bytes, then a panic is triggered. The second vulnerability has to do with signature parsing. The ECDSA code from_i32() converts the recovery ID value from a single byte to an i32. When doing this, the value is required to be between 0-3 but it can in reality be 0-255. Later on, unwrap() is called, causing a panic upon the error path being taken. Both of these vulnerabilities cause a panic that crashes the node. To me, it's weird that a small parsing issues crashes the node and there is no recovery that happens on the node, similarly to how Golang can. Between the two vulnerabilities, they got 150K in bug bounties, which is awesome! It's fascinating how such little functions in error handling can have catastrophic consequences on the uptime of the software.
Analysis Summary
# Vulnerability: NEAR Protocol "Ping of Death" Denial of Service
## CVE Details
- **CVE ID:** N/A (Identified via Bug Bounty)
- **CVSS Score:** 8.8 (High) / 10.0 (Critical - Researcher Original Rating)
- **CWE:** CWE-248: Uncaught Exception (Panic in Rust)
## Affected Systems
- **Products:** NEAR Protocol (`nearcore`)
- **Versions:** Versions prior to the fix implemented in January 2024.
- **Configurations:** All nodes participating in the P2P networking layer (Validator and RPC nodes).
## Vulnerability Description
The vulnerability stems from improper error handling in the Rust-based P2P networking layer of the NEAR Protocol. Specifically, the software used `unwrap()` and `expect()`—functions that trigger a process-wide "panic" (crash) upon encountering an error—instead of returning a Result that could be gracefully handled.
Two distinct flaws were identified:
1. **Public Key Parsing:** During the P2P handshake, the `from_slice()` function was called on a public key. The code used `expect()`, which triggered a panic if the provided key was not exactly 32 bytes in length.
2. **Signature Parsing:** In the ECDSA verification logic, the `from_i32()` function converted a recovery ID (v) from a single byte to an `i32`. While the protocol expects a value between 0–3, a malicious actor could send a value between 4–255. Subsequent calls to `unwrap()` on the error path caused the node to crash.
## Exploitation
- **Status:** PoC available (developed by researcher)
- **Complexity:** Low (Sending a single malformed P2P handshake message)
- **Attack Vector:** Network (Remote, unauthenticated)
## Impact
- **Confidentiality:** None
- **Integrity:** None
- **Availability:** High (Total crash of the node; if executed against enough peers, it causes a "chain-halting" event).
## Remediation
### Patches
- **NEAR Core PR 10385:** Fixed the issue by replacing panicking calls with proper error handling. The fix ensures that malformed signatures or keys result in a dropped connection rather than a process crash.
- Users should ensure they are running `nearcore` versions released after **January 9, 2024**.
### Workarounds
- No viable software workarounds existed other than patching the binary, as the flaw resides in the initial P2P handshake required for communication.
## Detection
- **Indicators of Compromise:** Node logs showing unexpected process termination with Rust panic messages related to `expect` in the `p2p` or `signature` modules.
- **Detection methods:** Monitoring for high rates of failed handshakes from specific IP addresses.
## References
- Zellic Research: [https://www.zellic.io/blog/near-protocol-bug/](https://www.zellic.io/blog/near-protocol-bug/)
- NEAR Core Repository: [https://github.com/near/nearcore/](https://github.com/near/nearcore/)
- Patch PR: [https://github.com/near/nearcore/pull/10385](https://github.com/near/nearcore/pull/10385)