90360 bc medium unauthenticated 28 byte noise negotiation forces ml kem and ml dsa work before peer authentication
Submitted on Aug 24th 2026 at 17:06:04 UTC by @crypt0n1337 for Audit Comp | Quantus
Report ID: #90360
Report Type: Blockchain/DLT
Report severity: Medium
Target: https://github.com/immunefi-team/audit-comp-quantus-chain
Impacts:
Increasing network processing node resource consumption by at least 30% without brute force actions, compared to the preceding 24 hours
Description
Severity and impact
Medium - M9: increasing network processing node resource consumption by at least 30% without brute force actions.
An unauthenticated client can select the /noise protocol and close before sending pqXX message 1. The Quantus listener performs expensive post-quantum cryptography before it reads that message or authenticates the peer.
On the exact frozen full-node binary, a local E2E test at only 5 connections per second increased victim CPU by 187.87% over an equal-rate TCP control. After subtracting TCP connection cost, the Quantus-specific excess was 316.02% of the preceding quiet CPU baseline. This is above the 30% Medium threshold.
The attacker sent about 140 bytes per second, performed no post-quantum cryptography, and maintained approximately 0.5 concurrent sockets. This is deterministic protocol use, not key guessing, identity enumeration, Sybil activity, or high-volume brute force.
Affected target
Frozen commit:
3b243b870a5442a6e5f443056f67bbba87d472f5Reported node version:
0.8.0-exodus-3b243b870a5Exact locally built node SHA-256:
509C2FF68AC6D637B7305258AF0B1F470BB591BC49CDF6863E8A9BC2EB4BCBC0Affected component:
client/litep2p
No public node, mainnet node, or public testnet node was tested. All traffic stayed on 127.0.0.1.
Root cause
After multistream selects /noise, the TCP listener enters handshake():
Therefore, the remote peer can force one ML-KEM-768 key generation, two ML-DSA-87 key derivations, and one ML-DSA signature without providing a peer identity or any pqXX payload.
The exact unauthenticated input is 28 application bytes:
The client does not need to read the response. It can close the socket after 100 ms.
Why this is not the public litep2p pending-connection issue
Upstream litep2p issue #282 describes accumulation of pending sockets, file-descriptor exhaustion, and listener fairness. This report does not claim those effects.
The final E2E closes every socket after 100 ms, holds approximately 0.5 sockets on average, and shows stable file descriptors and threads. The measured impact remains after subtracting an equal-rate and equal-lifetime TCP control. The additional cost also matches the direct Quantus PQ context differential of approximately 1.47 ms per connection.
The distinct root is the Quantus modification introduced with Quantus PR #574, which replaced classical handshake cryptography with ML-KEM and ML-DSA but performs that work before pqXX message 1. The public PR security review discusses identity binding and key handling, but it does not disclose this remote CPU amplification. I found no public issue, PR, or audit finding that discloses the exact root reported here.
Security impact
Any unauthenticated remote host that can reach the P2P port can impose repeated post-quantum key-generation and signing work at negligible bandwidth and without performing equivalent cryptography. The measured relative CPU increase exceeds the program's 30% Medium M9 threshold even after generic TCP cost is removed.
The local PoC uses a short matched quiet window rather than a literal preceding 24-hour production trace because the competition prohibits testing project nodes. This comparator limitation is disclosed. It does not alter the deterministic source-level cost or the repeated exact-frozen E2E differential.
Recommended remediation
Move expensive post-quantum context creation behind a cheap pre-authentication admission step. Possible controls include:
a per-IP and global rate limit for pre-authentication handshakes;
a bounded pending-handshake CPU budget;
a stateless reachability cookie before ML-KEM key generation and ML-DSA signing;
metrics for pending handshakes and pre-authentication CPU rejection.
Do not reuse long-lived KEM session material without a separate cryptographic design review.
Proof of Concept
E2E proof of concept
Save the inline patch at the end of this section as poc-submit.patch.
SHA-256:
63BF6E9F13FE5E3B8E0AEE39BCC3CF4F8D583438008F07DE6587F0DC41405BC2Scope of patch: one test-only change in
client/litep2p/src/lib.rsgit apply --check --whitespace=error-all: PASSClean-worktree release build: PASS
Compare the results
The same node, rate, duration, socket lifetime, and number of successful connections were used in both cases.
The PoC sends 8,428 bytes in approximately 60 seconds, or about 140 bytes per second. At 5 connections per second with a 100 ms socket lifetime, it holds about 0.5 sockets on average. Threads and file descriptors remain stable.
Reproducibility
Two earlier exact-frozen runs with the same 5 connections per second and 100 ms lifetime produced consistent results:
1
0.44819%
1.14560%
155.61%
261.84%
2
0.44819%
1.17861%
163.00%
274.23%
The fresh clean-worktree E2E above produced an even stronger 187.87% increase over TCP and 316.02% adjusted excess over quiet.
Inline PoC patch
The following is the complete poc-submit.patch (SHA-256 63BF6E9F13FE5E3B8E0AEE39BCC3CF4F8D583438008F07DE6587F0DC41405BC2).
Was this helpful?