{"action":"created","issue":{"url":"https://api.github.com/repos/saltyrtc/saltyrtc-meta/issues/46","repository_url":"https://api.github.com/repos/saltyrtc/saltyrtc-meta","labels_url":"https://api.github.com/repos/saltyrtc/saltyrtc-meta/issues/46/labels{/name}","comments_url":"https://api.github.com/repos/saltyrtc/saltyrtc-meta/issues/46/comments","events_url":"https://api.github.com/repos/saltyrtc/saltyrtc-meta/issues/46/events","html_url":"https://github.com/saltyrtc/saltyrtc-meta/issues/46","id":177671667,"number":46,"title":"Mitigating MITM between Client and Server","user":{"login":"lgrahl","id":1793755,"avatar_url":"https://avatars.githubusercontent.com/u/1793755?v=3","gravatar_id":"","url":"https://api.github.com/users/lgrahl","html_url":"https://github.com/lgrahl","followers_url":"https://api.github.com/users/lgrahl/followers","following_url":"https://api.github.com/users/lgrahl/following{/other_user}","gists_url":"https://api.github.com/users/lgrahl/gists{/gist_id}","starred_url":"https://api.github.com/users/lgrahl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lgrahl/subscriptions","organizations_url":"https://api.github.com/users/lgrahl/orgs","repos_url":"https://api.github.com/users/lgrahl/repos","events_url":"https://api.github.com/users/lgrahl/events{/privacy}","received_events_url":"https://api.github.com/users/lgrahl/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/saltyrtc/saltyrtc-meta/labels/bug","name":"bug","color":"ee0701"},{"url":"https://api.github.com/repos/saltyrtc/saltyrtc-meta/labels/signalling","name":"signalling","color":"fbca04"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/saltyrtc/saltyrtc-meta/milestones/1","html_url":"https://github.com/saltyrtc/saltyrtc-meta/milestones/Clean%20Up%20Protocol","labels_url":"https://api.github.com/repos/saltyrtc/saltyrtc-meta/milestones/1/labels","id":1977793,"number":1,"title":"Clean Up Protocol","description":"The protocol should be very precise regarding implementations. The target is to have an RFC-like protocol documentation.","creator":{"login":"lgrahl","id":1793755,"avatar_url":"https://avatars.githubusercontent.com/u/1793755?v=3","gravatar_id":"","url":"https://api.github.com/users/lgrahl","html_url":"https://github.com/lgrahl","followers_url":"https://api.github.com/users/lgrahl/followers","following_url":"https://api.github.com/users/lgrahl/following{/other_user}","gists_url":"https://api.github.com/users/lgrahl/gists{/gist_id}","starred_url":"https://api.github.com/users/lgrahl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lgrahl/subscriptions","organizations_url":"https://api.github.com/users/lgrahl/orgs","repos_url":"https://api.github.com/users/lgrahl/repos","events_url":"https://api.github.com/users/lgrahl/events{/privacy}","received_events_url":"https://api.github.com/users/lgrahl/received_events","type":"User","site_admin":false},"open_issues":17,"closed_issues":3,"state":"open","created_at":"2016-09-01T13:24:38Z","updated_at":"2016-09-18T19:41:00Z","due_on":null,"closed_at":null},"comments":2,"created_at":"2016-09-18T19:40:33Z","updated_at":"2016-09-19T08:03:12Z","closed_at":null,"body":"There's a possible MITM attack between client and server I've discovered some time ago. To be honest, it's not much of a problem because messages between clients are still end-to-end encrypted and cannot be decrypted by the server at all. It only works on unsecure WebSocket servers (no TLS) or WebSocket servers with broken TLS. Still, it makes our transport encryption look rather pointless.\r\n\r\n## Terminology\r\n\r\nC = Client\r\nS = Server\r\nA = Attacker\r\n\r\n## MITM Attack (Initiator)\r\n\r\nA generates two key pairs, **a1** and **a2**. **pk_a1** is the public key of **a1** and **sk_a1** is the secret key of **a1**.\r\n\r\nA replaces the path the initiator provided by **pk_a2**.\r\n\r\n```\r\nS <-- Path: pk_a2 ---------- A <-- Path: pk_c ------------ C\r\n```\r\n\r\nA replaces the key of the server in *server-hello* by **pk_a1**.\r\n\r\n```\r\nS --- server-hello: pk_s --> A --- server-hello: pk_a1 --> C\r\n```\r\n\r\nA decrypts *client-auth* by `box(sk_a1, pk_c)`, then encrypts and sends it to the server by `box(sk_a2, pk_s)`.\r\n\r\n```\r\nS <-- client-auth ---------- A <-- client-auth ----------- C\r\n```\r\n\r\nA decrypts *server-auth* by `box(sk_a2, pk_s)`, then encrypts and sends it to the initiator by `box(sk_a1, pk_c)`. Any further messages between initiator and server can be decrypted and modified by A.\r\n\r\n```\r\nS --- server-auth ---------> A --- server-auth ----------> C\r\n```\r\n\r\nThe benefit for A is questionable at best because A needs to change the path. Therefore, no responder would be able to connect to the initiator. Still, A can take the role of the server for the initiator.\r\n\r\n## MITM Attack (Responder)\r\n\r\nA generates two key pairs, **a1** and **a2**. **pk_a1** is the public key of **a1** and **sk_a1** is the secret key of **a1**.\r\n\r\nA does not need to change the path for responders as the path does not take part during authentication of responders.\r\n\r\n```\r\nS <-- Path: pk_i ----------- A <-- Path: pk_i ------------ C\r\n```\r\n\r\nA replaces the key of the server in *server-hello* with **pk_a1**.\r\n\r\n```\r\nS --- server-hello: pk_s --> A --- server-hello: pk_a1 --> C\r\n```\r\n\r\nA replaces the key of the responder in *client-hello* with **pk_a2**.\r\n\r\n```\r\nS <-- client-hello: pk_a2 -- A <-- server-hello: pk_c ---- C\r\n```\r\n\r\nA decrypts *client-auth* by `box(sk_a1, pk_c)`, then encrypts and sends it to the server by `box(sk_a2, pk_s)`.\r\n\r\n```\r\nS <-- client-auth ---------- A <-- client-auth ----------- C\r\n```\r\n\r\nA decrypts *server-auth* by `box(sk_a2, pk_s)`, then encrypts and sends it to the responder by `box(sk_a1, pk_c)`. Any further messages between responder and server can be decrypted and modified by A.\r\n\r\n```\r\nS --- server-auth ---------> A --- server-auth ----------> C\r\n```\r\n\r\nIn this case, the benefit for A is much better than with an initiator as the path does not need to be changed. Therefore, clients that communicate with one another via the server would not even know that their communication is completely visible to A. Still, the benefits are marginal: A would be able to announce new initiators, drop responders and let responders repeat messages.\r\n\r\n## Mitigation\r\n\r\nSo, my idea is to add an OPTIONAL but RECOMMENDED section to the server.\r\n\r\nThe server has an OPTIONAL permanent key pair (**sk_sp** and **pk_sp**). Clients know the public key of the server's permanent key pair. The key has no lifetime or any other fancy certificate stuff, it should be as simple as possible.\r\n\r\nIn the *server-auth*, we add another field that is REQUIRED to be set by the server if he has a permanent key pair. That field, named *signed_keys* contains `sign(pk_s || pk_c, sk_sp)`. The client verifies that signature. (Note: I've edited my previous stupid idea here)\r\n\r\nAnd that's it. An attacker would need to have the permanent key pair to sign its own keys.\r\n\r\n## Discussion\r\n\r\nHave I missed something? Is signing the concatenation of the public keys enough to mitigate replay attacks? Or should we add a x byte random field as well and add that to the concatenated data? @dbrgn"},"comment":{"url":"https://api.github.com/repos/saltyrtc/saltyrtc-meta/issues/comments/247932062","html_url":"https://github.com/saltyrtc/saltyrtc-meta/issues/46#issuecomment-247932062","issue_url":"https://api.github.com/repos/saltyrtc/saltyrtc-meta/issues/46","id":247932062,"user":{"login":"lgrahl","id":1793755,"avatar_url":"https://avatars.githubusercontent.com/u/1793755?v=3","gravatar_id":"","url":"https://api.github.com/users/lgrahl","html_url":"https://github.com/lgrahl","followers_url":"https://api.github.com/users/lgrahl/followers","following_url":"https://api.github.com/users/lgrahl/following{/other_user}","gists_url":"https://api.github.com/users/lgrahl/gists{/gist_id}","starred_url":"https://api.github.com/users/lgrahl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lgrahl/subscriptions","organizations_url":"https://api.github.com/users/lgrahl/orgs","repos_url":"https://api.github.com/users/lgrahl/repos","events_url":"https://api.github.com/users/lgrahl/events{/privacy}","received_events_url":"https://api.github.com/users/lgrahl/received_events","type":"User","site_admin":false},"created_at":"2016-09-19T08:03:12Z","updated_at":"2016-09-19T08:03:12Z","body":"Meh, tweetnacl-js seems to be using the new signing algorithm and libsodium the old one? And we need different keys for that, so I think the authenticated encryption approach should be fine."}}
{"actor":{"display_login":"lgrahl"}}