Toward Active and Passive Confidentiality Attacks On Cryptocurrency Off-Chain Networks

06.03.2025
Toward Active and Passive Confidentiality Attacks On Cryptocurrency Off-Chain Networks

Cryptocurrency off-chain networks such as Lightning (e.g., Bitcoin) or Raiden (e.g., Ethereum) aim to increase the scalability of traditional on-chain transactions. To support nodes in learning about possible paths to route their transactions, these networks need to provide gossip and probing mechanisms. This paper explores whether these mechanisms may be exploited to infer sensitive information about the flow of transactions, and eventually harm privacy. In particular, we identify two threats, related to an active and a passive adversary. The first is a \textit{probing attack}: here the adversary aims to detect the maximum amount which is transferable in a given direction over a target channel by actively probing it and differentiating the response messages it receives. The second is a \textit{timing attack}: the adversary discovers how close the destination of a routed payment actually is, by acting as a passive man-in-the-middle and analyzing the time deltas between sent messages and their corresponding responses. We then analyze the limitations of these attacks and propose remediations for scenarios in which they are able to produce accurate results.

1 Introduction

Blockchains, the technology underlying cryptocurrencies such as Bitcoin or Ethereum, herald an era in which mistrusting entities can cooperate in the absence of a trusted third party. However, current blockchain technology faces a scalability challenge, supporting merely tens of transactions per second, compared to custodian payment systems which easily support thousands of transactions per second. This is the result of the underlying global consensus algorithms, which tread on the side of correctness rather than performance.

Off-chain networks \cite{9}, a.k.a. payment channel networks (PCNs) or second-layer blockchain networks, have emerged as a promising solution to mitigate the blockchain scalability problem: by allowing participants to make payments directly through a network of peer-to-peer payment channels, the overhead of global consensus protocols and committing transactions on-chain can be avoided. Off-chain networks such as Bitcoin Lightning [18], Ethereum Raiden [23], and XRP Ripple [8], to just name a few, promise to primarily reduce load on the underlying blockchain, as well as drastically increasing transaction throughput, and thus, being able to settle transactions in the matter of (sub-) seconds rather than in minutes or in hours – along with substantially reducing transaction fees, since now only one counterparty is responsible for validating a payment initially, rather than the whole network.

In all of these networks, each node typically represents a user and each weighted edge represents funds escrowed on a blockchain; these funds can be transacted only between the endpoints of the edge. Many payment channel networks use source routing, in which the source of a payment specifies the complete route for the payment. If the global view of all nodes is accurate, source routing is highly effective because it finds all paths between pairs of nodes. Naturally, nodes are likely to prefer paths with lower per-hop fees, and are only interested in paths which support their transaction, i.e. which have a sufficient channel capacity.

However, the fact that nodes need to be able to find routes also requires mechanisms for nodes to learn about the payment channel network’s state. The two typical mechanisms which enable nodes to find and create such paths are gossip and probing. The gossip protocol defines messages which are to be broadcast in order for participants to be able to discover new nodes and channels and keep track of currently known nodes and channels [15]. Probing is the mechanism which is used to construct an actual payment route based on a local network view delivered by gossip, and ultimately perform the payment. In the context of §4, we are going to exploit probing to discover whether a payment has occurred over a target channel. The gossip store is queried for viable routes to the destination, based on the desired route properties [25]. Because the gossip store contains global channel information, it is possible to query payment routes originating from any node on the network. Due to privacy concerns, gossip messages only include the total balance for any given channel rather than the balance each node is holding.

This paper explores the question whether the inherent need for nodes to discover routes in general, and the gossip and probing mechanisms in particular, can be exploited to infer sensitive information about the off-chain network and its transactions.

1.1 Our Contributions

This paper identifies two novel threats for the confidentiality of off-chain networks. In particular, we consider the Lightning Network as a case study and present two attacks, an active one and a passive one. The active one is a probing attack in which the adversary wants to determine the maximum amount which can be transferred over a target channel it is directly or indirectly connected to, by active probing. The passive one is a timing attack in which the adversary discovers how close the destination of a routed payment actually is, by acting as a man-in-the-middle and listening for / analyzing certain well-defined messages. We then analyze these attacks, identify limitations and also propose remediations for scenarios in which they are able to produce accurate results.

1.2 Organization

Our paper is organized as follows. We introduce some preliminaries in §2, and then first describe the probing attack in §4 followed by the timing attack in §5. We review related work in §3 and conclude in §6.

2 Preliminaries

While our contribution is applicable to the concept of off-chain networks in general, to be concrete, we will consider the Bitcoin Lightning Network (LN) as a case study in this paper. In the following, we will provide some specific preliminaries which are necessary to understand the remainder of this paper.

The messages which are passed from one Lightning node to another are specified in the Basics of Lightning Technology (BOLTs) [17]. Each message is divided into a subcategory, called a layer. This provides superior separation of concerns, as each layer has a specific task and, similarly to the layers found in the Internet Protocol Suite, is agnostic to the other layers.

For example in Lightning, the channel_announce and channel_update messages are especially crucial for correct payment routing by other nodes on the network. channel_announce signals the creation of a new channel between two LN nodes and is broadcast exactly once. channel_update is propagated at least once by each endpoint, since even initially each of them may have a different fee schedule and thus, routing capacity may differ depending on the direction the payment is taking (i.e., when ( c ) is the newly created channel between A and B, whether ( c ) is used in direction AB or BA). Once a viable route has been determined, the sending node needs to construct a message (a transaction “request”) which needs to be sent to the first hop along the route. Each payment request is accompanied by an onion routing packet containing route information. Upon receiving a payment request each node strips one layer of encryption, extracting its routing information, and ultimately preparing the onion routing packet for the next node in the route. For the sake of simplicity, cryptographic aspects are going to be omitted for the…

Two BOLT Layer 2 messages are essential in order to establish a payment chain:

  • update_add_htlc: This message signals to the receiver, that the sender would like to establish a new HTLC (Hash Time Locked Contract), containing a certain amount of millisatoshis, over a given channel. The message also contains an onion Routing field, which contains information to be forwarded to the next hop along the route. In Figure 1, the sender initially sets up an HTLC with Hop 1. The onion Routing field contains another update_add_htlc (set up between Hop 1 and Hop 2), which in turn contains the ultimate update_add_htlc (set up between Hop 2 and Destination) in the onion Routing field.
  • update_fulfill_htlc: Once the payment message has reached the destination node, it needs to release the payment hash preimage in order to claim the funds which have been locked in the HTLCs along the route by the forwarded update_add_htlc messages. For further information on why this is necessary and how HTLCs ensure trustless payment chains, see [4]. To achieve this, the preimage is passed along the route backwards, thereby resolving the HTLCs and committing the transfer of funds (see Steps 4, 5, 6 in Figure 1).

The gossip messages mentioned earlier are sent to every adjacent node and eventually propagate through the entire network. update_add_htlc and update_fulfill_htlc however, are only sent/forwarded to the node on the other end of the HTLC.

In order to test the attacks proposed in §4 and §5, we have set up a testing network consisting of four c-lightning [2] nodes, with two local network computers running two local nodes each (Figure 2). Nodes 1 and 2 are connected via a local network link and can form hops for payment routes between Nodes

3 and 4. In order to interact with the nodes, we have made use of c-lightning’s RPC interface and built our software tool set in Python [19]. The tests and their corresponding results in 5 have also been verified with LND [3], another BOLT-conform Lightning Network implementation, written in Go.

3 Related Work

Off-chain networks in general and the Lightning network in particular have recently received much attention, and we refer the reader to the excellent survey by Gudgeon et al. [9]. The Lightning Network as an second-layer network alternative to pure on-chain transactions was first proposed by [22], with the technical specifications laid out in [18]. Despite being theoretically currency-agnostic, current implementations such as c-lightning [2] and LND [3] support BTC exclusively. A popular alternative for ERC-20 based tokens is the Raiden Network [23].

Several papers have already analyzed security and privacy concerns in off-chain networks. Rohrer et al. [24] focus on channel-based attacks and proposes methods to exhaust a victim’s channels via malicious routing (up to potentially total isolation from the victim’s neighbors) and to deny service to a victim via malicious HTLC construction. Tochner et al. [27] propose a denial of service attack by creating low-fee channels to other nodes, which are then naturally used to route payments for fee-minimizing network participants and then dropping the payment packets, therefore forcing the sender to await the expiration of the already set-up HTLCs.

[10] provides a closer look into the privacy-performance trade-off inherent in LN routing. The authors also propose an attack to discover channel balances within the network. Wang et al. [28] examine the LN routing process in more detail and proposes a split routing approach, dividing payments into large size and small size transactions. The authors show that by routing large payments dynamically to avoid superfluous fees and by routing small payments via a lookup mechanism to reduce excessive probing, the overall success rate can be maintained while significantly reducing performance overhead. Beres et al. [6] make a case for most LN transactions not being truly private, since their analysis has found that most payments occur via single-hop paths. As a remediation, the authors propose partial route obfuscation/extension by adding multiple low-fee hops. Currently still work in progress, [5] is very close to [4] in its approach and already provides some insights into second-layer payments, invoices and payment channels in general. The Lightning Network uses the Sphinx protocol to implement onion routing, as specified in [14]. The version used in current Lightning versions is based on [7] and [11], the latter of which also provides performance comparisons between competing protocols.

4 Probing Attack

4.1 Design

The Lightning Network uses an invoice system to handle payments. A LN invoice consists of a destination node ID, a label, a creation timestamp, an expiry timestamp, a CLTV (Check Lock Time Verify) expiry timestamp and a payment hash. Paying an invoice with a randomized payment hash is possible (since the routing nodes are yet oblivious to the actual hash) and will route the payment successfully to its’ destination, which forms the basis of this attack. Optionally it can contain an amount (leaving this field empty would be equal in principle to a blank cheque), a verbal description, a BTC fallback address in case the payment is unsuccessful, and a payment route suggestion. This invoice is then encoded, signed by the payee, and finally sent to the payer.

Having received a valid invoice (e.g. through their browser or directly via e-mail), the payer can now either use the route suggestion within the invoice or query the network themselves, and then send the payment to the payee along the route which has been determined. In this section, we will use the c-lightning RPC interface via Python exclusively – the functions involved are getroute() [25] and sendpay() [26], which takes two arguments: the return object from a getroute() call for a given route, a given amount and a given riskfactor, as well as the payment hash. Using sendpay() on its own (meaning, with a random payment hash instead of data from a corresponding invoice) will naturally result in one of two following error codes:

  • 204 (failure along route): This error indicates that one of the hops was unable to forward the payment to the next hop. This can be either due to insufficient funds or a non-existent connection between two adjacent hops along the specified route. If we have ensured that all nodes are connected as depicted in Figure 2, we can safely assume the former. One sequence of events leading up to this error can be seen in Figure 3.

Figure 3: Causing a 204 error by trying to send a payment to Node 4, which Node 3 is unable to perform.

16399 (permanent failure at destination): Given the absence of a 204 error, the attempted payment has reached the last hop. As we are using a random payment hash, realistically the destination node will throw an error, signalling that no matching preimage has been found to produce the payment hash. The procedure to provoke a 16399 error code can be seen in Figure 4. Figure 4: Causing a 16399 error by trying to send a payment to Node 4, who can’t produce a matching preimage and thus fails the payment.

The goal of this attack is to trace payment flow over a channel, which the attacker node is directly or indirectly connected to. The attacker node will therefore initially attempt to determine whether a payment has occurred over the observed channel between the penultimate and final node along the route. To this end, the attacker will send out periodic probes to the final node (the “victim”), containing the amount which has been determined by the initial probe. If channel weights remain unaltered, each of these probes should return a 16399 error code. If a payment does occur however, the penultimate node will find itself unable to forward the payment on the outgoing channel to our target, yielding a 204 error response. Upon receiving this message, we can then restart the process of our initial probe and ultimately arrive at the exact amount of millisatoshis (msat), which have been transferred.

4.2 Lab Implementation

Recalling Figure 2, we have chosen Node 3 as our attacker node and Node 4 as our target node – hence, the initial goal of Node 3 is to determine the max- imum payment flow between Nodes 2 and 4. To conduct our tests, each of the channels has been set up with a balance of 200,000,000 msat, with each node holding a stake of 100,000,000 msat in each of its channels. Node 3 will hold a slightly higher balance in order to accommodate probing fees. We can use the total channel balance, as received via gossip, as an upper ceiling for this value (200,000,000 msat in this case). We can then send payments from Node 3 to Node 4 with random payment hashes – resulting in either error code 16399 or error code 204 (§4.1). To this end, we perform a binary search on the available funds which we can transfer, searching for the highest value yielding a 16399 error instead of a 204 error. The algorithms used for both initial probing and deriving the actual channel balance from Node 2 to Node 4 are depicted in Algorithms 1 and 2.

Algorithm 1: Probing a channel for a given amount of msat

Result: Either error code 204 or 16399

[ \text{payment_hash} = \text{random.hex}(); \ \text{node_id} = \text{node ID of final node on victim channel}; \ \text{msat} = \text{value to probe for}; \ \text{route} = \text{getroute(node_id, msat)}; \ \text{sendpay(route, payment_hash)}; ]

Algorithm 2: Finding the initial maximum channel balance

Result: amount_msat – initial channel balance

[ \text{min_msat} = 0; \ \text{max_msat} = \text{channel.balance}; \ \text{amount_msat} = \text{channel.balance} / 2; \ \text{while True do} \ \hspace{1em} \text{if } \text{probe(amount_msat)} == 16399 \text{ then} \ \hspace{2em} \text{min_msat} = \text{amount_msat}; \ \hspace{1em} \text{else} \ \hspace{2em} \text{if } \text{amount_msat} == 204 \text{ then} \ \hspace{3em} \text{max_msat} = \text{amount_msat}; \ \hspace{2em} \text{else} \ \hspace{3em} \text{return } \text{“No suitable route found.”}; \ \hspace{1em} \text{end} \ \hspace{1em} \text{end} \ \hspace{1em} \text{if } \text{max_msat} – \text{min_msat} \leq 1000 \text{ then} \ \hspace{2em} \text{return amount_msat}; \ \hspace{1em} \text{else} \ \hspace{2em} \text{// continue to minimise maximum error} \ \hspace{2em} \text{end} \ \hspace{1em} \text{amount_msat} = (\text{min_msat} + \text{max_msat}) / 2 \ \text{end} ]

We thus arrive at the approximate maximum amount, which Node 2 can transfer to Node 4. The next step is to continuously probe for this amount of msat in regular intervals. The expected response is a 16399 error code, with a 204 error code implying that the amount we are trying to send is higher than the available amount which Node 2 can transfer to Node 4 (or that it has disconnected from Node 4). Upon receiving a 204 response, we start looking for the maximum payable amount to Node 4 once more. Subtracting the new amount from the old amount, we arrive at the size of the transaction which has occurred between Nodes 3 and 4.

After 17 probes by Node 3, Algorithm 2 has yielded an initial balance of 99,999,237 msat, which is in line with the channel balance we have allocated between Nodes 2 and 4. The next step is to monitor the channel for potential weight changes (Algorithm 3).

Algorithm 3: Finding the initial maximum channel balance

Result: New maximum flow from penultimate to final node

[ \text{init_max} = \text{initial channel balance}; \ \text{new_max} = \text{init_max}; \ \text{t} = \text{time to wait between checks}; \ \text{while True do} \ \hspace{1em} \text{sleep(t);} \ \hspace{1em} \text{if probe(init_max) == 204 then} \ \hspace{2em} \text{// channel balance has decreased} \ \hspace{2em} \text{return find_init_max();} \ \hspace{2em} \text{// potentially calculate delta} \ \hspace{1em} \text{else} \ \hspace{2em} \text{if (init_max + 1000) == 16399 then} \ \hspace{3em} \text{// channel balance has increased} \ \hspace{3em} \text{return find_init_max();} \ \hspace{3em} \text{// potentially calculate delta} \ \hspace{2em} \text{else} \ \hspace{3em} \text{return error;} \ \hspace{1em} \text{end} \ \text{end} \ \text{end} ]

To verify this, we have transferred 50,000,000 msat from Node 2 to Node 4, with our program detecting this soon after (we have set t to 5 seconds in order to avoid excessive probing) and returning an updated balance of 49,998,237 msat. We then transferred another 30,000,000 msat from Node 1 to Node 4, with our program again picking up the change and reporting the new channel balance at 19,997,389 msat.


Useful information for enthusiasts:

Contact me via Telegram: @ExploitDarlenePRO