-
Notifications
You must be signed in to change notification settings - Fork 55
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
avoid trying to update root role every time #225
Comments
Hi @nexustar, thank you for taking the time to file this issue. Historically TUF did work this way: root metadata was listed as a This behaviour was changed to improve TUF's compromise resilience (and, I think, simplifies implementation of the client workflow). Signing keys for the snapshot role are often kept online or used in an automated fashion. With the old TUF behaviour, if the snapshot role was compromised an attacker may choose to continue to list old versions of the root metadata in snapshot which could refer to the compromised snapshot key as being valid (at least until such time as the old root metadata expires). Unfortunately, tracking the full history of when this change was introduced is difficult. The earliest references I could find are:
|
This issue mentions avoiding unnecessary root downloads as a motivation for including the root version in the snapshot file. But there is a more important motivation: It would allow quickly detecting freeze attacks against the root metadata. I was surprised that TUF does not already do this. One of the main reasons for having the timestamp file in TUF is that freeze attacks can be detected quickly, because it has a short validity period. But because the root version is not listed in either timestamp or snapshot, this protection against freeze attacks does not extend to the root metadata. The root metadata commonly has a long validity period of several months, but at the same time it is important that updates are noticed quickly. The TUF specification acknowledges this limitation:
For example, a new root version is created with one or more root keys rotated, but keys for other roles are unchanged. An attacker who controls the repository can hide the new root version, and clients would not notice that anything is wrong until the previous root expires. If the root version was part of the snapshot, then clients could notice the problem as soon as the previous timestamp expires. As a side note, the TUF website still describes the previous spec versions where the root version was part of the snapshot:
Implementing root freeze protectionHere is how this could be implemented in the spec. The description of snapshot.json is updated to say that it also MUST list the version number of the root metadata. In the client update workflow, a step is inserted to report failure if the root version is not equal to the version listed in the snapshot. For backward compatibility, this check is omitted if the snapshot does not list the root version. It is possible that the version check fails, because the repository was concurrently updated with a new root, snapshot and timestamp, just between the time where the client fetches the root, and the time where the client fetches the timestamp. This is not an entirely new problem; this situation could have caused verification failures previously if e.g. timestamp keys were rotated. This problem could be mitigated by retrying the update from the beginning if a root version mismatch is detected. But properly fixing this requires implementing the root download optimization (i.e. taking the root version from the snapshot instead of trying to download new roots until a newer one is not found), which would ensure that we get a consistent view of the repository including the root, even if it is concurrently being updated. Implementing root download optimizationOnce we have the root version in the snapshot, this could also be used to avoid downloading the root if unchanged. This is only an optimization, and for compatibility with existing TUF repos without this addition, implementations would have to retain the old update behavior as a fallback. Currently, even the snapshot and target download are not optimized, see #235. Implementing this optimization would require first downloading the timestamp, and if needed the snapshot, and extracting the root version from the snapshot, all before verifying signatures on the timestamp or snapshot. There is a potential problem from this optimization: In case the repository was recovered from a compromise, it is possible that the new snapshot has the same version as a previous attacker-created snapshot. If a client sees that the snapshot version is unchanged and thus skips the snapshot download (even though the snapshot on the server has changed), it would fail to notice that the root has updated. To fix this potential problem, either the snapshot or the root download optimization should only be enabled if the timestamp includes a hash of the snapshot, such that the client can be sure that the locally cached snapshot is up to date. |
Thanks for taking the time to respond here. I wanted to echo @joshua Lock
***@***.***> 's thoughts about client optimization and add a few
of my own related to the security tradeoffs.
In the case that the repository and the keys it stores online are
compromised (which is essentially always timestamp and almost always
snapshot), the attacker can lie about things like the version number of the
root metadata. Note that if the repository is recovered to a good state
which is visible to a user, then the user will always get the latest root
role, timestamp, snapshot, etc.
So let's consider the case where the attacker's ability to interfere with
the repository lasts a very long time and the snapshot key / timestamp key
are/were also compromised. In this case, the attacker can sign whatever
snapshot they want and "freeze" the root role even if we include the
version number in the snapshot. Only the timeout of the root role's
metadata will eventually be detected. So as I understand what is written
above, I don't think any proposed scheme can help with this situation.
Okay, so this leaves another case unaddressed: What if the attacker has
saved metadata from timestamp and/or snapshot and can pretend to be the
repository (i.e., MITM), but hasn't compromised the actual signing keys.
If the attacker hasn't compromised the timestamp key, then any freeze
attack is still limited by this key's lifetime, which is quite short. If
the attacker has compromised the timestamp key, but not the snapshot key,
and is a persistent MITM / has a long term repository compromise, then the
attacker would be able to replay old snapshot files with the old root key.
In this case, I think the proposed solution would help, because a user
would detect a freeze attack when the snapshot files expired. This is
likely better than the root key expiry, but this time can still be rather
long.
One other thing to note is that if you do list the root role in the
snapshot and then decide not to download it if it is not updated, this does
mean that a MITM who has compromised only the snapshot key but is not a
persistent MITM, can potentially stop you from getting a new root file.
At first glance, this may not seem particularly likely to happen in
practice, but CDNs which origin pull content upon request (as is common)
would make clients vulnerable to this sort of attack, when they otherwise
would not likely be for an extended period. CDNs are also pretty common
amongst adopters, so are actually a case we need to worry about.
Note, this isn't meant to justify that we made the right tradeoff here.
We did spend some time working this out on a whiteboard and thought we
were making the best choice here. There may be other things we hadn't
thought of, errors in judgment / analysis, and of course reasonable minds
can always differ at how to value different attack cases.
…On Thu, Dec 12, 2024 at 6:12 AM Jan Schär ***@***.***> wrote:
This issue mentions avoiding unnecessary root downloads as a motivation
for including the root version in the snapshot file. But there is a more
important motivation: It would allow quickly detecting freeze attacks
against the root metadata. I was surprised that TUF does not already do
this. One of the main reasons for having the timestamp file in TUF is that
freeze attacks can be detected quickly, because it has a short validity
period. But because the root version is not listed in either timestamp or
snapshot, this protection against freeze attacks does not extend to the
root metadata. The root metadata commonly has a long validity period of
several months, but at the same time it is important that updates are
noticed quickly.
The TUF specification
<https://theupdateframework.github.io/specification/v1.0.33/#key-management-and-migration>
acknowledges this limitation:
Note that an attacker, who controls the repository, can launch freeze
attacks by withholding new root metadata. The attacker does not need to
compromise root keys to do so. However, these freeze attacks are limited by
the expiration time of the latest root metadata available to the client.
For example, a new root version is created with one or more root keys
rotated, but keys for other roles are unchanged. An attacker who controls
the repository can hide the new root version, and clients would not notice
that anything is wrong until the previous root expires. If the root version
was part of the snapshot, then clients could notice the problem as soon as
the previous timestamp expires.
As a side note, the TUF website
<https://theupdateframework.io/docs/metadata/#snapshot-metadata-snapshotjson>
still describes the previous spec versions where the root version was part
of the snapshot:
The snapshot.json metadata file lists version numbers of all metadata
files other than timestamp.json.
Implementing root freeze protection
Here is how this could be implemented in the spec. The description of
snapshot.json is updated to say that it also MUST list the version number
of the root metadata. In the client update workflow, a step is inserted to
report failure if the root version is not equal to the version listed in
the snapshot. For backward compatibility, this check is omitted if the
snapshot does not list the root version.
It is possible that the version check fails, because the repository was
concurrently updated with a new root, snapshot and timestamp, just between
the time where the client fetches the root, and the time where the client
fetches the timestamp. This is not an entirely new problem; this situation
could have caused verification failures previously if e.g. timestamp keys
were rotated. This problem could be mitigated by retrying the update from
the beginning if a root version mismatch is detected. But properly fixing
this requires implementing the root download optimization (i.e. taking the
root version from the snapshot instead of trying to download new roots
until a newer one is not found), which would ensure that we get a
consistent view of the repository including the root, even if it is
concurrently being updated.
Implementing root download optimization
Once we have the root version in the snapshot, this could also be used to
avoid downloading the root if unchanged. This is only an optimization, and
for compatibility with existing TUF repos without this addition,
implementations would have to retain the old update behavior as a fallback.
Currently, even the snapshot and target download are not optimized, see
#235 <#235>.
Implementing this optimization would require first downloading the
timestamp, and if needed the snapshot, and extracting the root version from
the snapshot, all before verifying signatures on the timestamp or snapshot.
There is a potential problem from this optimization: In case the
repository was recovered from a compromise, it is possible that the new
snapshot has the same version as a previous attacker-created snapshot. If a
client sees that the snapshot version is unchanged and thus skips the
snapshot download (even though the snapshot on the server has changed), it
would fail to notice that the root has updated. To fix this potential
problem, either the snapshot or the root download optimization should only
be enabled if the timestamp includes a hash of the snapshot, such that the
client can be sure that the locally cached snapshot is up to date.
—
Reply to this email directly, view it on GitHub
<#225 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAGROD6LTPIQODCL7JIAUJ32FFVRPAVCNFSM6AAAAABTPRGOUSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKMZYGU4DIOBWHE>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
At beginning of update, TUF client try to update root role,but most of time there is no update of root role. For a check for updates step, at lease 2 download is needed (n+1.root.json and timestamp.json if there is no update)
if record version of root role in snapshot role, we can fetch timestamp role first, and update it when timestamp role changed and snapshot say it need to update.
On security way, I think it is the same because if the attacker can return fake snapshot,he also can pretend that there is no n+1 version of root role
The text was updated successfully, but these errors were encountered: