-
-
Notifications
You must be signed in to change notification settings - Fork 90
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
Secure-Join protocol may have bugs / produce inconsistencies #1177
Comments
For a non-secure-join we could be concerned about someone changing the first message from bob to alice. In which case we need to run a full setup-contact flow first, after which alice can join bob to the group. For this we'd probably need tweaks to the QR-code and state so alice knows there is still something to do at the end. |
I am not convinced yet it is true what you are claiming quite factually here :) |
deltachat-core-rust/src/securejoin.rs Line 602 in 8f8db0c
deltachat-core-rust/src/securejoin.rs Line 626 in 8f8db0c
From verified-group or setup-contact protocol point of view at this point we need a signed & encrypted message from alice. For joining a non-verified group alice may need to send the Chat-Group-Member-Added message plain text. And finally I'm not sure if bob can know if they're joining a verified group or not (the line at deltachat-core-rust/src/securejoin.rs Line 604 in 8f8db0c
|
On Wed, Jan 15, 2020 at 01:13 -0800, Floris Bruynooghe wrote:
https://github.com/deltachat/deltachat-core-rust/blob/8f8db0c43108e8a9386f89df23bee7ed45836a3f/src/securejoin.rs#L602 is problematic. The problem is that for bob to know alice is verified in the verified-group protocol alice needs to send a signed & encrypted vg-member-added. But instead we are trying to allow this to be not verified while later verifying alice anyway: https://github.com/deltachat/deltachat-core-rust/blob/8f8db0c43108e8a9386f89df23bee7ed45836a3f/src/securejoin.rs#L626.
L626 Bob calling "mark_peer_as_verified()" will return an error if Alice's autocrypt-key does
not match the QR-mediated key-fingerprint of Alice. So Bob will only mark Alice as verified
if she has been sending the proper key (in the previous step 4 with the vc-auth-required message).
There is thus no chance here that Bob will mark Alice wrongly as verified.
From verified-group or setup-contact protocol point of view at this point we need a signed & encrypted message from alice. For joining a non-verified group alice may need to send the Chat-Group-Member-Added message plain text.
An attacker could replace alice's member-added message to Bob
with a different cleartext Member-added message so that
a) Bob thinks he joined an opportunistic group
b) Alice thinks she added Bob to a verified group
Note1, however, that the verified group members, which Alice produced the
QR-invite code for, will send encrypted messages to Bob's actual key.
The attacker can not gain access to those messages.
Note2, that Bob might send cleartext messages to - what he believes to be -
the opportunistic group. But those messages will not appear as proper
content in the verified chat of the verified group Alice invited for.
Note3, that the attacker can not send a modified encrypted member-added message
because he would need to sign it with Alice's proper key which he doesn't have.
Regarding Note3, however, i think we need to modify
https://github.com/deltachat/deltachat-core-rust/blob/master/src/securejoin.rs#L614
to ensure if the message is encrypted that it is signed with alice's proper key.
This Note3 attack should be addressed in the current code because otherwise
Bob could send an encrypted message that the attacker can read -- but Bob will
do this to an opportunistic group, i.e. his chat UX does not carry a "verified" sign.
Opportunistic group are naturally vulnerable to active attacks so Bob has not been mislead
but it's still better to fix it.
And finally I'm not sure if bob can know if they're joining a verified group or not (the line at https://github.com/deltachat/deltachat-core-rust/blob/8f8db0c43108e8a9386f89df23bee7ed45836a3f/src/securejoin.rs#L604 just always says it is not a verified group because that's its failure mode and the chat doesn't exist yet so it fails)
Let's indeed consider extending the QR-invite code to include information
whether the group-to-be-joined is a verified group or not. See #1178.
|
A very rough note: the claims to this being correct mean that the deltachat-core-rust/src/securejoin.rs Line 626 in 8f8db0c
deltachat-core-rust/src/securejoin.rs Lines 602 to 624 in 8f8db0c
|
I think the |
yip, i also think, the whole vg_expect_encrypted part can be removed. it can be easily bypassed anyway and seems not to add any security. |
I believe the discussion at nextleap-project/countermitm#83 points out that when we do not check whether |
Just a quick note I'm looking at finally resolving this. I'm investigating introducing a non-user-visible |
So here's my proposal, I've thought through this by now and think this works.
I think this upholds the security properties of the secure-join and setup-contact protocols while still allowing it to be used to join opportunistic groups as it does today. The behaviour change for users is minimal. I'll follow up with PRs to implement this. |
Aspirational doc comment, making clear where verification happens and what the deviations from countermitm are:
|
Thanks for writing this aspirational doc comment, very useful, and helps thinking about it. For a long time i pondered that step 6ff are not needed for both sides to mark the other as verified. Due to the two-generals problem we can never have both sides end up in "bidirectionally verified" state and being sure that the other side also knows that. So i think we can simply have unverified/verified contacts and we have to live with the fact that it might be one-sided. IOW, the "bi-directionally verified" state is not needed. However, we will need to explore the error cases/issues arising from only one side marking the other as "verified" (also can happen with dropped messages/spam-sorted etc.). Not doing that here right now. This is more about the claim that we can (aim to) already have step 5 result in both sides reaching "verified state" with each other. There might be a few refinements we need to do for Bob's "2 b) vg-request" message and Alice's "3 d) vg-auth-required" reply. We can send a challenge (if we don't already implicitly do) such that Alice's signed and encrypted message "vg-auth-required" arrives, Bob knows that:
The last point is important because Bob's vg-request message was unencrypted (he only knows A's fingerprint at this point) and a MITM could exchange Bob's key before handing the vg-request message to Alice. But Bob does know Alice's fingerprint, and as soon as Bob receives Alice's "vg-auth-required", and she has correctly signed off on using Bob's proper key, Bob can conclude that the email and privatekey is controlled by Alice's device as indicated on the QR code. Bob can mark Alice as "verified". This means that Bob can send messages to Alice that only she can decrypt, and that when Alice sends a message to Bob, that nobody except him can decrypt it. Thus Bob "having verified Alice" means that any message to/from Alice is MITM-safe and that Alice is in control of her e-mail pipeline. Now in step 5, after Bob send an encrypted+signed vg-request-with-auth message to Alice, which entails the QR-contained "auth" token, Alice knows that Bob actually got the QR code (we assume that Alice and Bob have an unobservable second channel). Therefore, Alice marks Bob as verified. She knows that any message to/from Bob is MITM-safe, and that Bob is control of the associated e-mail pipeline. There is now no need to send "contact-confirmed" anymore, and we don't need to mix it with "member-added". Happy to do a little A/V about this sometime. |
I almost entirely agree with all you're saying here. You're essentially spelling out what the uni-directional verified state means, which I think in short is: contact matches/controls their email and associated key. You then also argue that there's no need to get to the bi-directional verified state (at least for Bob, since Alice knows uni- and bi-directional state in the same step). And for a long time I thought so too, due to the two-generals problem. But our conversations around this topic when this issue was initially filed changed my mind. When Alice has Bob bi-directionally verified she knows that both: 1) Bob matches his email and key, 2) Bob knows Alice by her email and key. When Bob has Alice bi-directionally verified he also knows this of Alice. The two-generals problem only results in Alice never knowing whether Bob ever made it to bi-directional verified, for all she knows he might be stuck on the uni-directional verified state. I think it's better to keep the UI's idea of what verified means as bi-directional and not downgrade it to uni-directional. For one, Alice can never have Bob as uni-directional so it would make the protocol asymmetric. Secondly countermitm figured all this stuff out for us, and using it only costs us one extra message. |
I spelled out the definition of "verified" a bit more above (in an edit update) ....
I think Alice already knows this without a confirmation message.
My suggestion is to no use "uni/bi" at all and just use "verified/unverified" with "X marked as verified" meaning that I:
IOW, the "verification" flag is not one-sided, because we learn that the other side learned of us properly. When Alice receives Bob's vg-request-with-auth mail, the can mark Bob as verified in the exact same sense: She knows that Bob is in control of his email/key and she knows that Bob knows her proper key. |
I think the uni-bi directional conversation has confused us a bit. I entirely agree with that the user should only know of a "verified" or not state. Currently the implementation calls this state bi-directional verified and I explicitly introduced an intermediate step as uni-directional in order to deal with Bob not reaching the verified state in join-group (i chose this name also only because there was already such a state defined in an enum). There is no reason at all to even keep this state in the implementation and we could get rid of the name entirely if that helps. The only part that mattered in my proposal is that when joining a non-verified group (vg-member-added was sent in clear text), Bob does not mark Alice as a verified contact. For the other part, if I understand correctly you're questioning whether step 6b vc-contact-confirm is really needed to for Bob to mark Alice verified, suggesting he could mark Alice verified after step 4a (after vc-auth-required was sent). A way of looking at this is to ask what Bob knows after he received 6b vc-contact-confirm which he did not know after he received 3d vc-auth-required. This list of yours, of what Bob knows after 3d vc-auth-required is pretty good. I'm re-writing it here a little, because I think it should be fully symmetric as afterwards it does not matter who started the process (and I collapsed your last two bullet points into one):
This is what I think we would like the verified state to be. But I do not think point 3 is satisfied after 3d vc-auth-required. The problem is that Alice does not yet know whether Bob has been intercepted or not, so Alice does not yet know the first two points at this stage. And thus while Bob knows the first two, he does not know the third. Before Alice knows Bob really controls his email and his key, she needs to receive the AUTH key in a secure way from Bob (the 4b vc-request-with-auth step). |
If Alice's vg-auth-required message to Bob contains her signature on the info "Encrypted-To bob email/key" and Bob can verify the signature from the QR, then Bob can be sure of point 3 of your definition, i.e. he knows that Alice knows his proper keys and email. He thus does not need to wait for contact-confirm to mark Alice as verified. Note in order for what i said to become true we might have to modify Alice's vg-auth-required method to let her ascertain/sign where she encrypted/mailed to. See also https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-09.html#section-5.2.3.29 for an effort to do this at the pgp level. |
Oh, thanks for pointing out that currently autocrypt/pgp doesn't have the property of signing the intended recipient. I think I've known this is the past but was assuming that was already true - but it of course is not. However I still don't think that if we had this, Bob would have Alice verified after her 3d vc-auth-required message. At this point Bob knows she has his key, but crucially Alice still doesn't know this. And the 3rd bullet point above says the peer has to confirm they know you by your key and email. In other words if you aborted at after 3d vc-auth-required then Alice can still not store anything about what she learned from the handshake. However if you aborted after 4b vc-request-with-auth Bob can actually store some info about Alice, even though that's currently not done. Perhaps we should actually do this? So using the uni- and bi-directional terminology again, I think uni-directional means you have point 1&2, but not point 3. And for 6a to be reached perhaps it should even be a requirement that Bob stores the uni-directional verified state ("you know this is Alice, she might not know you are Bob"). |
@flub did your merged PR above solved all or most of the concerns you raised here? What are the remaining concerns? Thanks! |
@dumblob I don't think it resolves everything here yet. Not sure everything that remains, I didn't re-read this entire thread. One thing that remains is figuring out what single vs bi-directional verification means. There was some recent offline discussion where it seemed that distinguishing those two may make some sense. Basically bi-directional means you can introduce others into verified groups, where a uni-directional verification can't do that. |
I am refactoring securejoin in #5059. I remove Then I am going to add a column to Bob should mark Alice as one-way verified (copy public key to verified key) after verifying that public key matches invite fingerprint. This happens when Bob receives vc-auth-required or immediately after scanning the QR code if we already have a key. Alice should mark Bob as bidirectionally verified when she receives Bob should mark Alice as bidirectionally verified when |
But when a message containing |
If |
So, processing |
Thanks for finally getting this done @link2xt ! |
So question is how should we fix this? The protocol for QR-joining non-verified groups needs to change, but which way?
The text was updated successfully, but these errors were encountered: