Allow retries for secret retrieval by the same client
Hi! First of all, I am not sure which version of the secrets app our administrator has installed. Is there a way how I can see that as a mere nextcloud user? I ran into the problem I describe below. If you have already fixed it, my apologies.
Here are the steps I took
- Created a secret via the page https://nextcloud.example.de/index.php/apps/secrets/# and clicking on "New Secret"
- that got me a link to share: https://nextcloud.example.de/index.php/apps/secrets/show/5467e3ed2d264cf4b7505db38527265c#BhVgdtPqruT4+64O1Hk2cmdcId7PaUzdsAJWw8p1Jjc=
- There is also the notice: "Your secret is stored end-to-end encrypted on the server. It can only be decrypted by someone who has been given the link. Once retrieved successfully, the secret will be deleted on the server" (emphasis added)
- In another browser, I pasted that link, but without the part starting with #, which appears to be the decryption key
- The resulting page says "The following secret has been shared with you securely: Please make sure you have copied and stored the secret before closing this page! It is now deleted on the server." and "Error loading secret. Is your link correct?". My secret is not shown.
- In the first browser, I reload https://nextcloud.example.de/index.php/apps/secrets/# to update it. I click on the name that I gave my secret. I see "This secret has already been retrieved and its content was consequently deleted from the server.".
- Oops! The secret has been lost.
I guess the crux of my report is retrieved successfully. In the example, it isn't retrieved successfully. An attacker can delete somebody else's secrets, even without knowing the secret part of the URL. That's a denial of service attack.
I'm not sure if this is solvable, or if you will need to adjust the promise to the user.
Hm, good point about the DOS attack. I'm not sure how relevant that really is for malicious intents though, as an attacker would need to guess the random uuid of the secret to delete it purposefully.
But I'll give it some more thought.
However, regarding errors in non-malicious retrieval, that's certainly an issue, albeit not easy to solve. Maybe it would be an option to attempt retries from the same IP (i. e. IP-pinning) for a few minutes after the first request or something like that...
Anyways, if you are expecting an attack like described by you, there's always the option to share a secret password protected. But that's no excuse to ignore the issue, of course.
The way to do it that I could think of doesn't sound very nice, because it is somewhat complicated. It would involve that the server side doesn't delete the secret just yet, but waits for a confirmation somehow that the decryption went ok. But it should not wait too long (a couple of seconds maybe?), otherwise you can too easily have double retrieval.
I guess for the retrieve-once feature it is more crucial to avoid double retrieval than to ensure retrieval. The feature only ever makes sense if the recipient can be assured that his successful retrieval implies that nobody else has ever been or will ever be able to retrieve the same secret. A malicious interceptor, however, cannot be trusted to confirm successful retrieval and/or decryption. A retrieved secret thus must always be assumed to be retrieved and decrypted.
@matthiasbernhardt is right. We can under no cirumstances allow retrieval of one secret by multiple clients. There are cryptographic ways to solve this, but that's not trivial to do.
For example, we could use asymetric cryptography to allow a secret to be retrieved more than once, but only by a single client, which would be better than IP pinning, but that's also quite complex. Right now, I'm not sure if the benefit of any of the solutions outweighs the added complexity or reduced security.
I have two questions,
- if the newly created "secret" link was passed through a shortener before being given to owner for sharing purpose, could this issue be resolved?
Let's say we create a secret link: https://nextcloud.example.de/index.php/apps/secrets/show/5467e3ed2d264cf4b7505db38527265c#BhVgdtPqruT4+64O1Hk2cmdcId7PaUzdsAJWw8p1Jjc= but I'm only shown https://nextcloud.example.de/secrets/k2n349hhd98UY% anyone who clicks on the shortened (sharing) link would not have the capability to exclude the part after the '#'
- Now for the part of the original secret link before the '#', is this associated to a user or file or random?
The reason I ask is if it (5467e3ed2d264cf4b7505db38527265c) is assign to user X for every files user creates. an "attacker" can just refresh this link (https://nextcloud.example.de/index.php/apps/secrets/show/5467e3ed2d264cf4b7505db38527265c) and cause the interruption of sharing.
If it it random or file, it is less likely for targeted attack.
I'm a newbie, just putting my ¢2
@taziobaker A link shortener would only solve some cases where this issue occurs (for example it won't solve the case where the request reaches the server successfully, but the response is being lost due to network issues). Also it would break the end to end encryption because whatever service provides the link shortener has both the secret id and the key, so it can perform a man in the middle attack on the secret without any way for the user to notice.
Regarding your second question: The part before the '#' is a randomly generated string and will be different for every shared secret link.
Thank you for your prompt reply.
I hear you about the man-in-the-middle, but what if the shortener is inside the NextCloud installation? Maybe it's my unknowledgeable mind in this field making my stubborn to ask this last question.
@taziobaker nc secrets is designed to share secrets end-to-end encrypted, which means, that not even the Nextcloud server knows them. Therefore, even using the same NC server as link shortener would break e2e encryption.
But I'll think about ways to create shorter links. Maybe we can improve this with compression of sorts
I finally understand your reason. There is no need to shorten the link for aesthetic reason, it was an ignorant idea to avoid tampering with the actual link.