Skip to content
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

Add release support/downgrade protection #13

Open
rugk opened this issue Apr 11, 2018 · 5 comments
Open

Add release support/downgrade protection #13

rugk opened this issue Apr 11, 2018 · 5 comments

Comments

@rugk
Copy link

rugk commented Apr 11, 2018

Your not very low aim is to provide the same security to web versions of software, as for native desktop apps.

Okay, you verify the integrity (and to some extend also authenticity) of the software, fine.

Now, however, desktop apps with usual downloads also have another advantage here.

You can edit a released version of the software and know this is secure. Who you can subsequently download it.
Audits can this be made for specific versions of a software.

Also you can find a vulnerability in a specific version. This is then fixed in the next version and the software is updated.
You can prevent downgrade attacks NY just checking the version of the new software is newer than the old one.

All this requires versions. That is something web applications usually do not have.
This, this add-on e.g. does not prevent downgrade attacks.

in practise

Say version 1.0.0 has a vulnerability. Now v1.0.1 is released and the server admin updates the software.
When the server admin now wants to attack a user, they can just serve the old v1.0.0 once and this exploit the known vulnerability.

protection

I suggest to implement some version checking in this add-on.
Maybe use the manifest.json or something like this and add a custom version field. Or better include it in the (signed) HTML file. When a signed website is visited, this add-on should then just record (save) the version number of the software.
When the website is visited the next time, it just compares the version number and shows a critical error when the version number is lower than the saved old one.
That's it, theoretically wore easy! (Of course you need to use a very good library for version comparison or so, because when this cab be circumvented your whole protection can be circumvented.)

And as an additional protection, it may require that a version number is present. The software creator had to include it, but IMHO they should do so, as this is an attack you have to consider.
For the start, you could make this an optional thing. Or just require it, AFAIK not too many projects use this extension for now.😉

@baryluk
Copy link

baryluk commented Jun 15, 2018

This can be done server side. Even older signed version should communicate to server what is own version, and server can reject or track older versions. This also allows to support i.e. 2 or more concurrent versions in the meantime, i.e. when the APIs are changing, but people still do have older version in caches, or you want to do gradual rollout to only part of users, etc.

@rugk
Copy link
Author

rugk commented Jun 15, 2018

Hmm okay, but this needs some active implementation by the website itself… And developers don't know this.
It would certainly be better, if it was built-in.

But wait… no… it does not work, because this scenario involves a compromised server. So an attacker can (and will) of course also replace the file (or server routine), which determinates the current "up-to-date" version. E.g.

  • client requests version.txt from server to check for up-to-date version
  • server is compromised: code itself is replaced with older vulnerable version and version.txt is replaced with old version -> downgrade attack

So this certainly needs to be tracked client-side.

@baryluk
Copy link

baryluk commented Jun 15, 2018

And developers don't know this.

They should know it. In distributed systems it is common to have multiple versions of the code in the wild that communicate with your server.

But wait… no… it does not work, because this scenario involves a compromised server. So an attacker can (and will) of course also replace the file (or server routine), which determinates the current "up-to-date" version. E.g.

Ah. That is why all messages from the server should be also at least HMAC signed and timestamped. This way even if "server" or its HTTPS channel is compromised, it cannot lie. Even by replay attack.

@rugk
Copy link
Author

rugk commented Jun 15, 2018

And developers don't know this.

They should know it. In distributed systems it is common to have multiple versions of the code in the wild that communicate with your server.

No, that's not what I meant. It's actually that they should know that they basically have to implement this replay protection in a secure manner to actually use the "signed pages" add-on in a secure way.
And it get's harder, see below…

the server should be also at least HMAC signed and timestamped

Okay, so the client get's the information:

  • current allowed version number(s)
  • when it was signed
  • "signed" via HMAC with a secret that does not live on a server

Problems:

  • for an HMAC, the secret must be secret, because it can be used to create that hash. But the client has to verify the HMAC to verify the authenticity and thus needs the secret key… on the client but not on the server(?). I can hardly think of a way this can be accomplished.
  • the only way to prevent a replay protection here is then to compare the timestamp. But to which value should it be compared? A fixed value, i.e. if the version is older than 90days, then show a security error? This would have two issues:
    • the web service must be updated each 90 days at least, which introduced potentially useless version bumps, or at least, re-signings (note the signings need to be done offline and manually uploaded to the server…)
    • the validity period however must be be too large, because it determinates the time an attacker could do downgrade attacks, so in our example above, they could attack the service for 90days – that's way to much

So:

  • to prevent the first issue, they could use a "usual" asymmetric crypto, i.e. PGP, so basically sign yet another document.
  • the second issue could be solved by using 1 day as the vadility period and update just the "signature" of the version.txt file each day

But each day – offline. Without automation! By a human developer??!

No, nobody wants to do this.


And my point with "developers don't know this" was that this add-on must provide security out-of-the-box if the devs follow the guidelines in a correct way. And as a downgrade attack is an issue for any web service, which uses this add-on, it's prevention should be implement inside of the add-on. Otherwise each dev implements their own stuff and potentially makes mistakes, i.e. introduces vulnerabilities. And as you can see above it is not easy: It would require an PGP lib yet again (although you have in in the extension, already), so it is not only troubling from a security point of view, but also a re-doing unnecessary work and using resources.

@rugk
Copy link
Author

rugk commented Jun 15, 2018

Actually you could implement this simple "versioning" approach I described initially (which is way easier to implement then the signing I described above) and urge devs to use it, but notice them if they want to e.g. do staged rollouts or so, they can just leave the version number away (or set it to a special value, which would allow later opt-outs, so it may be better) and then state that they have to implement their own mechanism to prevent replay attacks – which is, lightly said, hard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants