-
Notifications
You must be signed in to change notification settings - Fork 117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracking: security: Limit ability of synthetic nodes to spread throughout network. Credit: Ziggurat Team #7824
Comments
A good first step would be listing our existing defences against this attack. Note that some of Zebra's behaviour in the report is outdated. @mpguerra who would you like to do that work? |
Our previous analysis of this issue is in ticket #1869, where we listed our defences at the time, and decided they were good enough. |
I think this was closed by mistake |
Hey team! Please add your planning poker estimate with Zenhub @arya2 @oxarbitrage @teor2345 @upbqdn |
I estimated this ticket assuming that we'd choose 1-3 potential fixes from the list of suggested fixes, and not do all of them. |
Could we do just these fixes here, or re-open #1869 for these fixes and convert this one to a tracking issue if we want to do more?
It could also send any excess addresses as |
If the goal is to delay connecting to these peers until we've tried other more reliable/secure peers, then marking them as alternate already does that. So I'm not sure I want to add more code that introduces similar behaviour using a different mechanism. That seems like it would make any bugs harder to diagnose. zebra/zebra-network/src/meta_addr.rs Lines 125 to 152 in f2b1737
I'm also cautious about adding more state to a system that's already complex. This part of the code has a history of hangs, so I'm particularly cautious of adding further delays. We already use the version message and remote IP address of inbound connections to create alternate peers. So this change would also change the behaviour of those addresses. |
I've re-opened and updated #1869, some of the designs in it actually made this problem worse. (So I'm glad we waited this long to implement it.) Before we start work or open tickets, let's:
I've added your suggestion to the list, and added some benefits and drawbacks. |
What do you think of this suggestion?
I can't see anywhere we limit the number of peers, so the current limit is the 1000 peer protocol limit. |
It looks like the only strictly-required fix for this issue and it's important that addresses be selected at random. |
Ok, I've marked that as a required change, and added some benefits and drawbacks. These changes seem similar, so let's discuss them together. What do you think their benefits and drawbacks are?
|
Zebra will find peers faster if we keep all of the addresses, and will drop the May use more memory if stored per connection.
I'm not sure what this means.
Why send the addresses when a peer is disconnected rather than when the addresses are received? |
Can you add this advantage to the ticket?
50 bytes for 1000 addresses for 200 connections is still only 10MB, so I think we're fine here.
At the moment, we keep the last unsolicited address message from each peer, ignoring messages with only one address. (Unless we have no addresses at all.) We drop previously stored addresses when we get a new message. Then if we query that peer, we take the entire message and add it to our address book. But in this new design we're taking some addresses and leaving some behind. So we might want to add extra unsolicited addresses to the start of our stored addresses (like an
Because our goal was to only put messages in our address book if we requested them from a peer, rather than letting peers add to our address book on their schedule. If peers can modify our internal address book by sending unsolicited address messages, that makes it harder to implement securely. But sending addresses when the peer is disconnected also has this issue, so maybe we shouldn't do this at all. Because a peer could connect, send addresses, and disconnect to get them in our address book. |
So I think that just leaves these proposed changes for discussion:
I think we agree the address book query limit is an essential part of this ticket. Did you want to add advantages and disadvantages in the ticket? Also, should it be per-connection or an overall limit? |
Yep, added.
Nothing noteworthy, a little complexity.
Ohh. Advantages:
Both of those seem crucial. I think this is also a required a change, but perhaps for another high-priority issue. Disadvantages:
Ah, good idea. I think it would be okay to send them immediately if the address book, when sent a new
Yes, I think so.
I can't seem to think of any disadvantages, but I added the advantages.
I think it should be per-connection, I don't think the default values should be a problem for systems that are already able to run Zebra., and it's a relatively trivial amount of memory that I don't think will surprise users providing their own
Or both, but as a separate issue, per-connection is enough for now. |
The current defence against an adversary filling the address book is:
These defences are already implemented. And let's assume that we implement taking only a few addresses separately. So that advantage has already been assigned to that change. So I think that the remaining advantage for storing a list of recent addresses is improved connectivity. Because we're keeping more addresses available if we need them and decide to query for them.
I'm not sure it is, there are easy to implement attacks that evade a per-connection limit. Can you think of one? |
I removed this part because it doesn't match Zebra's current behaviour. It is based on an idea from the ticket that we decided not to do. Currently these addresses are kept in the per-connection cache. |
I added a new potential fix:
Currently a peer can fill Zebra's address book by repeatedly connecting and sending a different IP in each version message. This seems like a trivial attack that's worth preventing. It also removes the NeverAttemptedAlternate status (because we're not sending any peers with that status any more, we're just treating them as if they were gossiped) which simplifies the code a lot. And we can remove the |
@arya2 let's schedule a meeting to make the final decisions on what we're doing for this ticket? I think we have enough information and analysis now. |
Agreed.
Oh. It's going to evict any address from the address book to insert new addresses rather than drop the new address when it has a lower connection state. Yeah, I could, that's a problem. An overall limit is a good idea. |
Hmm, I think we might be talking about different changes here. #7823 is about rate-limiting how often peers can request addresses from Zebra. It's good to have a strict per-connection limit before the request is sent to the inbound service, because that stops a single connection overloading the node. But reconnecting will reset that limit, so we also need a less strict overall limit in the inbound service. Or we could rate-limit getaddr requests per connection, with a constant timer starting when the connection is successfully negotiated? That way we wouldn't need a global rate-limit, because reconnecting would still encounter the same time limit. Hmm, but then you could still do it in parallel across multiple peers. Maybe we do need a global limit. |
A similar reconnection attack can be used to fill the address book via version messages or remote IPs, and NeverAttemptedAlternate. |
Here's a much simpler design that still meets the goal of limiting how many of its addresses Zebra gives out:
This means it doesn't matter how many connections or how many reconnections an adversary makes, they will still get the same set of addresses until we decide to change them. A similar design is used by DNS seeders to avoid revealing all their addresses. |
I updated "Always keep the latest unique addresses from each connected peer, regardless of which address message they were sent in" with:
If we're not dropping a lot of addresses from the cache, there's no point switching to unique addresses, because the address book makes addresses unique anyway. |
un-scheduling, tracking issues should not be scheduled in a sprint, the issues that they are tracking should be scheduled instead. |
I think this change is also more complicated than discussed, because there is still some code using
I've moved these both to a "more analysis needed" section. If we think they're worth doing, let's make optional tickets with needs-investigation tags? |
I think we can close this as sufficiently complete. |
Motivation
"RT-S1 f1" from "Red Team report on Zcash testnet"
And
"RT-S1 f2" from "Red Team report on Zcash testnet"
Complex Code or Requirements
There is nothing particularly complex here.
Potential Fixes
Before starting work, discuss the impact of each potential fix on this vulnerability with the team, and decide on 1-3 fixes that have the greatest impact.
Required Changes
These changes must be made to fix the issues:
GetAddr
responses. Credit: Ziggurat Team #7823To deal with the drawbacks of these other changes, make this small change in the same PR as #1869:
Accepted Changes
These changes are useful but not strictly required:
Needs More Analysis
These changes were accepted, but they've since turned out to be more complicated than expected:
Option
fromMetaAddr.{services,untrusted_last_seen}
None
for either of these fields, and decide on acceptable defaultsRejected Changes
Changes that aren't needed or don't work
NeverAttemptedAlternate
(or a new status that is a lower priority than failed, or moveNeverAttemptedAlternate
to a lower priority than failed)Testing
Related Work
The text was updated successfully, but these errors were encountered: