#40990 [BC-Insight] Security best practices
Submitted on Mar 8th 2025 at 18:30:45 UTC by @jovi for IOP | Zano
Report ID: #40990
Report Type: Blockchain/DLT
Report severity: Insight
Target: https://github.com/immunefi-team/zano-iop/tree/main/src/p2p/net_node.inl
Impacts:
Security best practices
QA Report
Description
As spoken with the project at the discord channel, this submission contains findings that are not contained in the scope of impacts of this program and don't represent medium/high/critical severity vulnerabilities.
01
Summary
In the P2P node server’s peer management code (peerlist_manager
and node_server
), two related flaws allow attackers to abuse the peerlist trimming logic and manipulate peer IP classifications. Specifically:
The
trim_white_peerlist()
andtrim_gray_peerlist()
functions are implemented incorrectly, causing the wrong lists to be trimmed and possibly allowing untrusted or stale entries to remain in the white peerlist.When receiving peer information from an incoming connection, the code trusts the incoming IP/Port too readily (and does not cross-check it sufficiently), opening the door for peer IP spoofing or incorrect classification.
If exploited, these bugs can result in a peerlist that is improperly populated or trimmed, leading to disruptive network behavior (e.g., spurious connections, partial DoS, or peer partitioning).
Vulnerability Details
Location
peerlist_manager::trim_white_peerlist & trim_gray_peerlist
Located in
net_peerlist
.Code snippet reference (showing incorrect trimming):
Both methods call erase on the opposite list, which inverts the trimming logic.
node_server::set_peer_just_seen / handle_remote_peerlist
Located in
net_node
code (net_node.inl
).Code snippet reference (showing insufficient verification of incoming addresses):
{ ... if(!handle_remote_peerlist(rsp.local_peerlist, rsp.node_data.local_time, context)) { // merges peers without verifying correctness thoroughly // ... } ```
Description
Incorrect List Trimming The
trim_white_peerlist()
function actually trims the gray list, andtrim_gray_peerlist()
function actually trims the white list. This inverted logic can cause a scenario where:The white list grows without correct pruning, potentially filled with malicious or stale entries.
The gray list is pruned too aggressively (or not at all), impacting how new or less-trusted peers are recognized.
IP Spoofing / Insufficient Verification When new remote peer information arrives via an incoming connection, there is minimal cross-checking or confirmation that the provided IP addresses/ports are accurate. Attackers or misconfigured peers can inject bogus addresses into the white list, degrade the node's connectivity to honest peers, or trigger unwanted IP blocks.
Impact
Inaccurate Peer Reputation: The white list is supposed to represent more-trusted peers, but these issue lets unverified addresses end up in it.
Potential Node Resource Waste: Large or invalid peer entries in the white list or forced IP blocks can waste resources and degrade performance.
02
Summary
In handle_request_get_objects()
, the error message incorrectly cites the number of blocks (arg.blocks.size()
) even when the root cause is an excessive number of transactions (arg.txs.size()
). This leads to misleading logs and hinders accurate troubleshooting.
Vulnerability Details Location
File:
t_currency_protocol_handler<t_core>::handle_request_get_objects
Function:
handle_request_get_objects(...)
Description
When arg.blocks.size()
or arg.txs.size()
exceeds the respective maximum count, an error log is generated, and the connection is dropped. However, the log statement unconditionally prints arg.blocks.size()
regardless of whether arg.txs.size()
is responsible for the threshold breach. This creates confusion during debugging or monitoring because it obscures which specific parameter (blocks vs. transactions) caused the violation.
Code Snippet
The snippet demonstrates that only arg.blocks.size()
is reported, even if the arg.txs.size()
exceeded its limit.
Impact
Operational Misinterpretation: Automated systems or operators may be misled by the incorrect reference in the log, delaying corrective actions or misdirecting investigations.
03
Summary
The connections_maker()
routine within node_server<t_payload_net_handler>
conflates all outgoing connections as if they were white-listed (“white”) connections. This erroneous assumption leads to incorrect logic that can create either too few or too many white connections, undermining the intended networking and connection policies.
Vulnerability Details
Location
node_server<t_payload_net_handler>::connections_maker()
in the method snippet:
Description
The code tracks a total count of outgoing connections (conn_count
) and applies that figure as though all these connections are white connections. In reality, the method get_outgoing_connections_count()
can also return connections established from other categories (for example, “grey” connections), inflating the count.
Root cause: The logic fails to distinguish white connections from grey connections when deciding whether to create more white connections.
Deviation from intended behavior: The system tries to maintain a certain number of white connections but incorrectly uses the overall outgoing connection count, leaving the node with insufficient white connections.
Impact
Connection Policy Issues: The node may fail to achieve the desired count of genuine white connections, hurting network health or reliability.
Proof of Concept
01
Wrong Peerlist Trimming
Run a local node that restarts repeatedly when the white list is at or near capacity.
Notice that the white list does not get trimmed, but the gray list entries do—showing the mismatch in code and actual effect.
IP Spoofing
Create a malicious peer that, during handshake, sends a fake peer list with random or malicious IP addresses.
Observe that the node merges these without verifying if the addresses correspond to the IP of the handshake creator.
02
Create a peer request with
arg.blocks.size()
within limits butarg.txs.size()
exceedingCURRENCY_PROTOCOL_MAX_TXS_REQUEST_COUNT
.Observe in logs that the error message only mentions blocks, showing a misleading reference to
arg.blocks.size()
being “too big”.
03
Start a node configured to have a limited number of white connections (for example,
connections_count=10
, withP2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT=50
).Allow the node to discover other grey peers before any white peers are available.
Observe that
get_outgoing_connections_count()
grows to or aboveexpected_white_connections
with grey connections, preventing the node from opening any new white connections. Despite the code’s intention to ensure at least 50% white connections, the final state mostly has grey connections.
Was this helpful?