siv-org / siv

Secure Internet Voting protocol
https://siv.org
Other
13 stars 9 forks source link

POST /api/submit-invalidation-response has weak auth currently #247

Open dsernst opened 2 months ago

dsernst commented 2 months ago

The POST api/submit-invalidation-response endpoint currently implies the "Invalidation Response" message is coming from the voter whose vote was invalidated, but it's currently quite easy for anyone else to take that over.

image

Overview

This is a low-priority endpoint, but it could be used to send a message to the election administrator while impersonating a voter. Perhaps this could be leveraged to launch another attack using the message body as the payload, eg spear-phishing.

image

Weakness

The problem is the endpoint only requires election_id, message, and auth_token to use, but auth tokens are no longer secret once votes are submitted. Not for invalidated votes, nor for all non-invalidated votes too. Non-invalidated votes aren't meant to ever use this endpoint (the front-end for it is only shown on the Vote Submitted screen, after a vote is invalidated), but this /submit-invalidation-response endpoint isn't checking.

Existing mitigation

The good news is we do have live logging on this endpoint, so we can be sure no one has ever used it this way, and immediately see if anyone ever did attempt to do so.

Nonetheless it would be good to tighten this up properly so it's not even a possibility.

Solution

In addition to blocking this endpoint from being used for non-invalidated votes:

  1. We can't use voter auth tokens, since they are assumed public after casting votes.
  2. If we switched to votes cast using priv/pub key pairs, we could use those, but unclear if/when that might happen.
  3. We could issue the voter a new auth token after they vote, but this is a little annoying, especially just for this one endpoint.
  4. Much cleaner would be if we properly leveraged the ZK Proof That A Device Cast A SIV Vote nature of SIV encrypted votes. Since this UI is only meant to be accessed from the submitted screen, we can safely assume the voter has already submitted an encrypted vote (effectively a pubkey), and has access to all the associated randomizers (priv keys) already at hand. So the front-end could build a cryptographic signature, and then the endpoint could validate that signature, to confirm the voter who submitted the vote is the same one writing this message.