The Ur Project

Documenting the craft of stacking things so they remain stacked. For a very long time.

Architecture - TUF and signing - part 14

The Ur Project adopts The Update Framework - https://theupdateframework.io/. According to the framework site:

The Update Framework (TUF) maintains the security of software update systems, providing protection even against attackers that compromise the repository or signing keys. TUF provides a flexible framework and specification that developers can adopt into any software update system.

If this sounds familiar

That would make a lot of sense. In essence, Clear Linux OS already implemented a chained-trust model where verification chains down through all the relevant bits from server down to end-user content. And it didn't have to rely on a specific HTTPS server - content could live on a CDN or mirror and still have the proper chain of trust in place. Even with HTTP-based updates, TUF provides enough security that it should protect against MITM style attacks, although with HTTP you'd be vulnerable to "injection-blocking" where an attacker could keep a user's system busy downloading garbage, but the end user system would just discard the falsified data.

If this sounds new and experimental

TUF isn't very old by itself. The draft spec is from '22. So it's only 4 years old. The last spec was published in '23 - so the working group publishing it took a year to iron out the spec. But it's widely used already and a few big projects (Python, Joomla, PHP, others) are implementing TUF as a backbone for delivering secure updates to their users. Many of these have outlined their choice for using TUF online, so if you're interested in the why question and want more opinions than just mine, you should go check out the https://theupdateframework.io/community/adoptions/ page at the project.

What's the underlying model

The TUF framework centers around designing a system that protects users from various real-world style attacks on integrity of their system. The most obvious attacks are attacks that insert/inject compromised code into the system by MITM style attacks. Fortunately, almost every distribution protects against this sort of attack by checking signatures to see if it's coming from a trusted source. Somewhat easily defeated.

A second line of attacks is when an attacker gives you an update that is older, and known to be insecure. It might be a library or daemon that had a known vulnerability. The attacker downgrades your system, and now can use a known exploit to gain access or manipulate your system further.

An even more complex line of attacks is where an attacker tries to tell a user's system that it has an upgrade for the system that is actually newer than the user's system has, but it's not the newest one that has a vulnerability fixed. The user upgrades to a vulnerable version of a software component.

And finally, the attacker manages to gain access to the signing keys, and now can sign malicious content as if it originates from the trusted source, and now all users of this system are vulnerable to injected payloads.

These vectors are verbatim from https://theupdateframework.io/docs/overview/.

Roll it.

If you read the threat model you'll see that there's a big problem when signing keys are obtained by attackers. The posture from TUF is that this is inevitable - one should plan for such an event. The solution is that keys are rolled regularly, and that keys expire. By doing this, even if keys are obtained, their usefulness expires (rapidly) and the window an attacker has to monetize on these obtained keys rapidly closes.

This has implications for the repository server: repos become a living thing. They are anything but static - keys are rolling constantly and this heartbeat makes it so that clients can know that they are trustworthy. A client that encounters a stale repository knows immediately that their content isn't to be trusted, and it should not proceed to update from this stale server.

If the official repo server goes stale, nothing is lost. If the staleness is a temporary outage, the repo can become alive again at a later point in time, and then users can continue to update their systems against the repository. But this requires the real (fresh/rolled) keys, and not the outdated keys that an attacker may have gained in the past.

How well do I trust this?

That's a really good question for everyone using The Ur Project and The Update Framework! I myself ask this question because the burden is on my shoulders to make sure this is implemented correctly, but even more because I am putting my trust in a new system.

Several things I can say though. The folks that I worked with at Intel that built a secure Linux OS at the time with me are people I trust. And one of them was an editor of the specification of the TUF spec: Joshua Lock. Joshua is a great guy and incredibly smart, but also rooted his experience in building real life distribution projects, some of which we worked on together.

Second, the folks at Intel made us run the gauntlet to prove that Clear Linux OS was safe and didn't expose users to unknown risks. I owe many of them a great deal of thanks because they shared their knowledge and experience with me as to how bad or good every aspect of code we wrote or implemented for it was. So cheers to Ryan, Terri, Joshua, Casey, Matthew(a), John, Miki and many others.

What these people taught me was an attitude. The attitude that no matter how hard you try, things will slip and get too complex to ascertain. And so you have to apply defense in depth. Build not just one but many lines of defense. Do your best and don't over promise. TUF is just that - a set of mitigations against certain attacks, properly stacked and built on robustness assuming the inevitable may one day happen, and be ready for that.

Back to reviewing

There's more code to re-review another time, just to make sure it's all done right.

--sofar (aka Auke)